Changeset 89be1c68 for src/ResolvExpr/ConversionCost.cc
- Timestamp:
- Jul 17, 2017, 2:35:52 PM (7 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:
- 7ebaa56
- Parents:
- b46e3bd
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/ConversionCost.cc
rb46e3bd r89be1c68 45 45 assert( type ); 46 46 if ( type->get_base() ) { 47 return conversionCost( src, type->get_base(), indexer, env ) + Cost ( 0, 0, 1 );47 return conversionCost( src, type->get_base(), indexer, env ) + Cost::safe; 48 48 } // if 49 49 } // if … … 58 58 if ( typesCompatibleIgnoreQualifiers( src, dest, indexer, env ) ) { 59 59 /// std::cout << "compatible!" << std::endl; 60 return Cost ( 0, 0, 0 );60 return Cost::zero; 61 61 } else if ( dynamic_cast< VoidType* >( dest ) ) { 62 return Cost ( 0, 0, 1 );62 return Cost::safe; 63 63 } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( dest ) ) { 64 64 // std::cerr << "conversionCost: dest is reference" << std::endl; … … 70 70 return Cost::infinity; 71 71 } else { 72 return converter.get_cost() + Cost( 0, 0, 0 ); 73 } // if 74 } // if 75 } 76 77 Cost convertToReferenceCost( Type * src, ReferenceType * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env ) { 78 // std::cerr << "convert to reference cost..." << std::endl; 79 if ( ReferenceType *srcAsRef = dynamic_cast< ReferenceType * >( src ) ) { // pointer-like conversions between references 80 // std::cerr << "converting between references" << std::endl; 81 if ( srcAsRef->get_base()->get_qualifiers() <= dest->get_base()->get_qualifiers() && typesCompatibleIgnoreQualifiers( srcAsRef->get_base(), dest->get_base(), indexer, env ) ) { 82 return Cost( 0, 0, 1 ); 83 } else { // xxx - this discards reference qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right? 84 int assignResult = ptrsAssignable( srcAsRef->get_base(), dest->get_base(), env ); 85 if ( assignResult < 0 ) { 86 return Cost( 0, 0, 1 ); 87 } else if ( assignResult > 0 ) { 88 return Cost( 1, 0, 0 ); 89 } // if 90 } // if 91 } else if ( typesCompatibleIgnoreQualifiers( src, dest->get_base(), indexer, env ) ) { 92 // std::cerr << "converting compatible base type" << std::endl; 93 if ( src->get_lvalue() ) { 94 // std::cerr << "lvalue to reference conversion" << std::endl; 95 // lvalue-to-reference conversion: cv lvalue T => cv T & 96 if ( src->get_qualifiers() == dest->get_base()->get_qualifiers() ) { 97 return Cost( 0, 0, 1 ); // cost needs to be non-zero to add cast 98 } if ( src->get_qualifiers() < dest->get_base()->get_qualifiers() ) { 99 return Cost( 0, 0, 2 ); // cost needs to be higher than previous cast to differentiate adding qualifiers vs. keeping same 72 return converter.get_cost() + Cost::zero; 73 } // if 74 } // if 75 } 76 77 Cost convertToReferenceCost( Type * src, Type * dest, int diff, const SymTab::Indexer & indexer, const TypeEnvironment & env ) { 78 std::cerr << "convert to reference cost..." << std::endl; 79 if ( diff > 0 ) { 80 // TODO: document this 81 Cost cost = convertToReferenceCost( safe_dynamic_cast< ReferenceType * >( src )->get_base(), dest, diff-1, indexer, env ); 82 // TODO: increment reference cost 83 cost.incSafe(); 84 return cost; 85 } else if ( diff < -1 ) { 86 // TODO: document this 87 Cost cost = convertToReferenceCost( src, safe_dynamic_cast< ReferenceType * >( dest )->get_base(), diff+1, indexer, env ); 88 // TODO: increment reference cost 89 cost.incSafe(); 90 return cost; 91 } else if ( diff == 0 ) { 92 ReferenceType * srcAsRef = dynamic_cast< ReferenceType * >( src ); 93 ReferenceType * destAsRef = dynamic_cast< ReferenceType * >( dest ); 94 if ( srcAsRef && destAsRef ) { // pointer-like conversions between references 95 std::cerr << "converting between references" << std::endl; 96 if ( srcAsRef->get_base()->get_qualifiers() <= destAsRef->get_base()->get_qualifiers() && typesCompatibleIgnoreQualifiers( srcAsRef->get_base(), destAsRef->get_base(), indexer, env ) ) { 97 return Cost::safe; 98 } else { // xxx - this discards reference qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right? 99 int assignResult = ptrsAssignable( srcAsRef->get_base(), destAsRef->get_base(), env ); 100 if ( assignResult < 0 ) { 101 return Cost::safe; 102 } else if ( assignResult > 0 ) { 103 return Cost::unsafe; 104 } // if 105 } // if 106 } else { 107 std::cerr << "reference to rvalue conversion" << std::endl; 108 ConversionCost converter( dest, indexer, env ); 109 src->accept( converter ); 110 return converter.get_cost(); 111 } // if 112 } else { 113 ReferenceType * destAsRef = dynamic_cast< ReferenceType * >( dest ); 114 assert( diff == -1 && destAsRef ); 115 if ( typesCompatibleIgnoreQualifiers( src, destAsRef->get_base(), indexer, env ) ) { 116 std::cerr << "converting compatible base type" << std::endl; 117 if ( src->get_lvalue() ) { 118 std::cerr << "lvalue to reference conversion" << std::endl; 119 // lvalue-to-reference conversion: cv lvalue T => cv T & 120 if ( src->get_qualifiers() == destAsRef->get_base()->get_qualifiers() ) { 121 return Cost::safe; // cost needs to be non-zero to add cast 122 } if ( src->get_qualifiers() < destAsRef->get_base()->get_qualifiers() ) { 123 return Cost::safe + Cost::safe; // cost needs to be higher than previous cast to differentiate adding qualifiers vs. keeping same 124 } else { 125 return Cost::unsafe; 126 } // if 127 } else if ( destAsRef->get_base()->get_const() ) { 128 std::cerr << "rvalue to const ref conversion" << std::endl; 129 // rvalue-to-const-reference conversion: T => const T & 130 return Cost::safe; 100 131 } else { 101 return Cost( 1, 0, 0 ); 102 } 103 } else if ( dest->get_base()->get_const() ) { 104 // std::cerr << "rvalue to const ref conversion" << std::endl; 105 // rvalue-to-const-reference conversion: T => const T & 106 return Cost( 0, 0, 1 ); 107 } else { 108 // std::cerr << "rvalue to non-const reference conversion" << std::endl; 109 // rvalue-to-reference conversion: T => T & 110 return Cost( 1, 0, 0 ); 111 } 112 } else { 113 // std::cerr << "attempting to convert from incompatible base type -- fail" << std::endl; 132 // std::cerr << "rvalue to non-const reference conversion" << std::endl; 133 // rvalue-to-reference conversion: T => T & 134 return Cost::unsafe; 135 } // if 136 } // if 137 std::cerr << "attempting to convert from incompatible base type -- fail" << std::endl; 114 138 } 115 139 return Cost::infinity; 140 } 141 142 Cost convertToReferenceCost( Type * src, ReferenceType * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env ) { 143 int sdepth = src->referenceDepth(), ddepth = dest->referenceDepth(); 144 return convertToReferenceCost( src, dest, sdepth-ddepth, indexer, env ); 116 145 } 117 146 … … 205 234 int tableResult = costMatrix[ basicType->get_kind() ][ destAsBasic->get_kind() ]; 206 235 if ( tableResult == -1 ) { 207 cost = Cost( 1, 0, 0 ); 208 } else { 209 cost = Cost( 0, 0, tableResult ); 236 cost = Cost::unsafe; 237 } else { 238 cost = Cost::zero; 239 cost.incSafe( tableResult ); 210 240 } // if 211 241 } else if ( dynamic_cast< EnumInstType *>( dest ) ) { 212 242 // xxx - not positive this is correct, but appears to allow casting int => enum 213 cost = Cost ( 1, 0, 0 );243 cost = Cost::unsafe; 214 244 } else if ( dynamic_cast< ZeroType* >( dest ) != nullptr || dynamic_cast< OneType* >( dest ) != nullptr ) { 215 cost = Cost ( 1, 0, 0 );245 cost = Cost::unsafe; 216 246 } // if 217 247 } … … 220 250 if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) { 221 251 if ( pointerType->get_base()->get_qualifiers() <= destAsPtr->get_base()->get_qualifiers() && typesCompatibleIgnoreQualifiers( pointerType->get_base(), destAsPtr->get_base(), indexer, env ) ) { 222 cost = Cost ( 0, 0, 1 );252 cost = Cost::safe; 223 253 } else { // xxx - this discards pointer qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right? 224 254 int assignResult = ptrsAssignable( pointerType->get_base(), destAsPtr->get_base(), env ); 225 255 if ( assignResult < 0 ) { 226 cost = Cost ( 0, 0, 1 );256 cost = Cost::safe; 227 257 } else if ( assignResult > 0 ) { 228 cost = Cost ( 1, 0, 0 );258 cost = Cost::unsafe; 229 259 } // if 230 260 } // if 231 261 } else if ( dynamic_cast< ZeroType* >( dest ) != nullptr || dynamic_cast< OneType* >( dest ) != nullptr ) { 232 cost = Cost ( 1, 0, 0 );262 cost = Cost::unsafe; 233 263 } // if 234 264 } … … 243 273 // cv can be safely dropped because of 'implicit dereference' behavior. 244 274 refType->get_base()->accept( *this ); 275 // TODO: increment reference cost 276 cost.incSafe(); 245 277 } 246 278 … … 267 299 static BasicType integer( q, BasicType::SignedInt ); 268 300 integer.accept( *this ); // safe if dest >= int 269 if ( cost < Cost ( 1, 0, 0 )) {301 if ( cost < Cost::unsafe ) { 270 302 cost.incSafe(); 271 303 } // if … … 289 321 assert( type ); 290 322 if ( type->get_base() ) { 291 cost = conversionCost( type->get_base(), dest, indexer, env ) + Cost ( 0, 0, 1 );323 cost = conversionCost( type->get_base(), dest, indexer, env ) + Cost::safe; 292 324 } // if 293 325 } // if … … 295 327 296 328 void ConversionCost::visit( __attribute((unused)) TupleType *tupleType) { 297 Cost c ;329 Cost c = Cost::zero; 298 330 if ( TupleType *destAsTuple = dynamic_cast< TupleType* >( dest ) ) { 299 331 std::list< Type* >::const_iterator srcIt = tupleType->get_types().begin(); … … 327 359 int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->get_kind() ]; 328 360 if ( tableResult == -1 ) { 329 cost = Cost( 1, 0, 0 ); 330 } else { 331 cost = Cost( 0, 0, tableResult + 1 ); 361 cost = Cost::unsafe; 362 } else { 363 cost = Cost::zero; 364 cost.incSafe( tableResult + 1 ); 332 365 } 333 366 } else if ( dynamic_cast< PointerType* >( dest ) ) { 334 cost = Cost ( 0, 0, 1 );367 cost = Cost::safe; 335 368 } 336 369 } … … 343 376 int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->get_kind() ]; 344 377 if ( tableResult == -1 ) { 345 cost = Cost( 1, 0, 0 ); 346 } else { 347 cost = Cost( 0, 0, tableResult + 1 ); 378 cost = Cost::unsafe; 379 } else { 380 cost = Cost::zero; 381 cost.incSafe( tableResult + 1 ); 348 382 } 349 383 }
Note: See TracChangeset
for help on using the changeset viewer.