Changeset 28e58fd for src/ResolvExpr/ConversionCost.cc
- Timestamp:
- Aug 25, 2017, 10:38:34 AM (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:
- 800d275
- Parents:
- af08051 (diff), 3eab308c (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
raf08051 r28e58fd 28 28 29 29 namespace ResolvExpr { 30 const Cost Cost::zero = Cost( 0, 0, 0 ); 31 const Cost Cost::infinity = Cost( -1, -1, -1 ); 30 const Cost Cost::zero = Cost( 0, 0, 0, 0 ); 31 const Cost Cost::infinity = Cost( -1, -1, -1, -1 ); 32 const Cost Cost::unsafe = Cost( 1, 0, 0, 0 ); 33 const Cost Cost::poly = Cost( 0, 1, 0, 0 ); 34 const Cost Cost::safe = Cost( 0, 0, 1, 0 ); 35 const Cost Cost::reference = Cost( 0, 0, 0, 1 ); 36 37 #if 0 38 #define PRINT(x) x 39 #else 40 #define PRINT(x) 41 #endif 32 42 33 43 Cost conversionCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env ) { … … 35 45 EqvClass eqvClass; 36 46 NamedTypeDecl *namedType; 37 /// std::cout << "type inst " << destAsTypeInst->get_name(); 47 PRINT( std::cerr << "type inst " << destAsTypeInst->get_name(); ) 38 48 if ( env.lookup( destAsTypeInst->get_name(), eqvClass ) ) { 39 49 if ( eqvClass.type ) { … … 43 53 } 44 54 } else if ( ( namedType = indexer.lookupType( destAsTypeInst->get_name() ) ) ) { 45 /// std::cout << " found" << std::endl; 55 PRINT( std::cerr << " found" << std::endl; ) 46 56 TypeDecl *type = dynamic_cast< TypeDecl* >( namedType ); 47 57 // all typedefs should be gone by this point 48 58 assert( type ); 49 59 if ( type->get_base() ) { 50 return conversionCost( src, type->get_base(), indexer, env ) + Cost ( 0, 0, 1 );60 return conversionCost( src, type->get_base(), indexer, env ) + Cost::safe; 51 61 } // if 52 62 } // if 53 /// std::cout << " not found" << std::endl; 54 } // if 55 /// std::cout << "src is "; 56 /// src->print( std::cout ); 57 /// std::cout << std::endl << "dest is "; 58 /// dest->print( std::cout ); 59 /// std::cout << std::endl << "env is" << std::endl; 60 /// env.print( std::cout, 8 ); 63 PRINT( std::cerr << " not found" << std::endl; ) 64 } // if 65 PRINT( 66 std::cerr << "src is "; 67 src->print( std::cerr ); 68 std::cerr << std::endl << "dest is "; 69 dest->print( std::cerr ); 70 std::cerr << std::endl << "env is" << std::endl; 71 env.print( std::cerr, 8 ); 72 ) 61 73 if ( typesCompatibleIgnoreQualifiers( src, dest, indexer, env ) ) { 62 /// std::cout << "compatible!" << std::endl; 63 return Cost ( 0, 0, 0 );74 PRINT( std::cerr << "compatible!" << std::endl; ) 75 return Cost::zero; 64 76 } else if ( dynamic_cast< VoidType* >( dest ) ) { 65 return Cost( 0, 0, 1 ); 77 return Cost::safe; 78 } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( dest ) ) { 79 PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; ) 80 return convertToReferenceCost( src, refType, indexer, env ); 66 81 } else { 67 82 ConversionCost converter( dest, indexer, env ); … … 70 85 return Cost::infinity; 71 86 } else { 72 return converter.get_cost() + Cost( 0, 0, 0 ); 73 } // if 74 } // if 87 return converter.get_cost() + Cost::zero; 88 } // if 89 } // if 90 } 91 92 Cost convertToReferenceCost( Type * src, Type * dest, int diff, const SymTab::Indexer & indexer, const TypeEnvironment & env ) { 93 PRINT( std::cerr << "convert to reference cost..." << std::endl; ) 94 if ( diff > 0 ) { 95 // TODO: document this 96 Cost cost = convertToReferenceCost( safe_dynamic_cast< ReferenceType * >( src )->get_base(), dest, diff-1, indexer, env ); 97 cost.incReference(); 98 return cost; 99 } else if ( diff < -1 ) { 100 // TODO: document this 101 Cost cost = convertToReferenceCost( src, safe_dynamic_cast< ReferenceType * >( dest )->get_base(), diff+1, indexer, env ); 102 cost.incReference(); 103 return cost; 104 } else if ( diff == 0 ) { 105 ReferenceType * srcAsRef = dynamic_cast< ReferenceType * >( src ); 106 ReferenceType * destAsRef = dynamic_cast< ReferenceType * >( dest ); 107 if ( srcAsRef && destAsRef ) { // pointer-like conversions between references 108 PRINT( std::cerr << "converting between references" << std::endl; ) 109 if ( srcAsRef->get_base()->get_qualifiers() <= destAsRef->get_base()->get_qualifiers() && typesCompatibleIgnoreQualifiers( srcAsRef->get_base(), destAsRef->get_base(), indexer, env ) ) { 110 return Cost::safe; 111 } else { // xxx - this discards reference qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right? 112 int assignResult = ptrsAssignable( srcAsRef->get_base(), destAsRef->get_base(), env ); 113 PRINT( std::cerr << "comparing references: " << assignResult << " " << srcAsRef << " " << destAsRef << std::endl; ) 114 if ( assignResult < 0 ) { 115 return Cost::safe; 116 } else if ( assignResult > 0 ) { 117 return Cost::unsafe; 118 } // if 119 } // if 120 } else { 121 PRINT( std::cerr << "reference to rvalue conversion" << std::endl; ) 122 ConversionCost converter( dest, indexer, env ); 123 src->accept( converter ); 124 return converter.get_cost(); 125 } // if 126 } else { 127 ReferenceType * destAsRef = dynamic_cast< ReferenceType * >( dest ); 128 assert( diff == -1 && destAsRef ); 129 if ( typesCompatibleIgnoreQualifiers( src, destAsRef->get_base(), indexer, env ) ) { 130 PRINT( std::cerr << "converting compatible base type" << std::endl; ) 131 if ( src->get_lvalue() ) { 132 PRINT( 133 std::cerr << "lvalue to reference conversion" << std::endl; 134 std::cerr << src << " => " << destAsRef << std::endl; 135 ) 136 // lvalue-to-reference conversion: cv lvalue T => cv T & 137 if ( src->get_qualifiers() == destAsRef->get_base()->get_qualifiers() ) { 138 return Cost::reference; // cost needs to be non-zero to add cast 139 } if ( src->get_qualifiers() < destAsRef->get_base()->get_qualifiers() ) { 140 return Cost::safe; // cost needs to be higher than previous cast to differentiate adding qualifiers vs. keeping same 141 } else { 142 return Cost::unsafe; 143 } // if 144 } else if ( destAsRef->get_base()->get_const() ) { 145 PRINT( std::cerr << "rvalue to const ref conversion" << std::endl; ) 146 // rvalue-to-const-reference conversion: T => const T & 147 return Cost::safe; 148 } else { 149 PRINT( std::cerr << "rvalue to non-const reference conversion" << std::endl; ) 150 // rvalue-to-reference conversion: T => T & 151 return Cost::unsafe; 152 } // if 153 } // if 154 PRINT( std::cerr << "attempting to convert from incompatible base type -- fail" << std::endl; ) 155 } 156 return Cost::infinity; 157 } 158 159 Cost convertToReferenceCost( Type * src, ReferenceType * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env ) { 160 int sdepth = src->referenceDepth(), ddepth = dest->referenceDepth(); 161 return convertToReferenceCost( src, dest, sdepth-ddepth, indexer, env ); 75 162 } 76 163 … … 164 251 int tableResult = costMatrix[ basicType->get_kind() ][ destAsBasic->get_kind() ]; 165 252 if ( tableResult == -1 ) { 166 cost = Cost( 1, 0, 0 ); 167 } else { 168 cost = Cost( 0, 0, tableResult ); 253 cost = Cost::unsafe; 254 } else { 255 cost = Cost::zero; 256 cost.incSafe( tableResult ); 169 257 } // if 170 258 } else if ( dynamic_cast< EnumInstType *>( dest ) ) { 171 259 // xxx - not positive this is correct, but appears to allow casting int => enum 172 cost = Cost ( 1, 0, 0 );260 cost = Cost::unsafe; 173 261 } else if ( dynamic_cast< ZeroType* >( dest ) != nullptr || dynamic_cast< OneType* >( dest ) != nullptr ) { 174 cost = Cost ( 1, 0, 0 );262 cost = Cost::unsafe; 175 263 } // if 176 264 } … … 178 266 void ConversionCost::visit(PointerType *pointerType) { 179 267 if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) { 180 if ( pointerType->get_base()->get_qualifiers() <= destAsPtr->get_base()->get_qualifiers() && typesCompatibleIgnoreQualifiers( pointerType->get_base(), destAsPtr->get_base(), indexer, env ) ) { 181 cost = Cost( 0, 0, 1 ); 182 } else { 268 PRINT( std::cerr << pointerType << " ===> " << destAsPtr; ) 269 Type::Qualifiers tq1 = pointerType->get_base()->get_qualifiers(); 270 Type::Qualifiers tq2 = destAsPtr->get_base()->get_qualifiers(); 271 if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( pointerType->get_base(), destAsPtr->get_base(), indexer, env ) ) { 272 if ( tq1 == tq2 ) { 273 // types are the same 274 cost = Cost::zero; 275 } else { 276 // types are the same, except otherPointer has more qualifiers 277 PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; ) 278 cost = Cost::safe; 279 } 280 } else { // xxx - this discards qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right? 183 281 int assignResult = ptrsAssignable( pointerType->get_base(), destAsPtr->get_base(), env ); 184 if ( assignResult < 0 ) { 185 cost = Cost( 0, 0, 1 ); 282 PRINT( std::cerr << " :: " << assignResult << std::endl; ) 283 if ( assignResult < 0 && pointerType->get_base()->get_qualifiers() <= destAsPtr->get_qualifiers() ) { 284 cost = Cost::safe; 186 285 } else if ( assignResult > 0 ) { 187 cost = Cost ( 1, 0, 0 );286 cost = Cost::unsafe; 188 287 } // if 288 // assignResult == 0 means Cost::Infinity 189 289 } // if 190 290 } else if ( dynamic_cast< ZeroType* >( dest ) != nullptr || dynamic_cast< OneType* >( dest ) != nullptr ) { 191 cost = Cost ( 1, 0, 0 );291 cost = Cost::unsafe; 192 292 } // if 193 293 } 194 294 195 295 void ConversionCost::visit(__attribute((unused)) ArrayType *arrayType) {} 296 297 void ConversionCost::visit(ReferenceType *refType) { 298 // Note: dest can never be a reference, since it would have been caught in an earlier check 299 assert( ! dynamic_cast< ReferenceType * >( dest ) ); 300 // convert reference to rvalue: cv T1 & => T2 301 // recursively compute conversion cost from T1 to T2. 302 // cv can be safely dropped because of 'implicit dereference' behavior. 303 refType->get_base()->accept( *this ); 304 if ( refType->get_base()->get_qualifiers() == dest->get_qualifiers() ) { 305 cost.incReference(); // prefer exact qualifiers 306 } else if ( refType->get_base()->get_qualifiers() < dest->get_qualifiers() ) { 307 cost.incSafe(); // then gaining qualifiers 308 } else { 309 cost.incUnsafe(); // lose qualifiers as last resort 310 } 311 PRINT( std::cerr << refType << " ==> " << dest << " " << cost << std::endl; ) 312 } 313 196 314 void ConversionCost::visit(__attribute((unused)) FunctionType *functionType) {} 197 315 … … 215 333 static Type::Qualifiers q; 216 334 static BasicType integer( q, BasicType::SignedInt ); 217 integer.accept( *this ); 218 if ( cost < Cost ( 1, 0, 0 )) {335 integer.accept( *this ); // safe if dest >= int 336 if ( cost < Cost::unsafe ) { 219 337 cost.incSafe(); 220 338 } // if … … 238 356 assert( type ); 239 357 if ( type->get_base() ) { 240 cost = conversionCost( type->get_base(), dest, indexer, env ) + Cost ( 0, 0, 1 );358 cost = conversionCost( type->get_base(), dest, indexer, env ) + Cost::safe; 241 359 } // if 242 360 } // if … … 244 362 245 363 void ConversionCost::visit( __attribute((unused)) TupleType *tupleType) { 246 Cost c ;364 Cost c = Cost::zero; 247 365 if ( TupleType *destAsTuple = dynamic_cast< TupleType* >( dest ) ) { 248 366 std::list< Type* >::const_iterator srcIt = tupleType->get_types().begin(); … … 276 394 int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->get_kind() ]; 277 395 if ( tableResult == -1 ) { 278 cost = Cost( 1, 0, 0 ); 279 } else { 280 cost = Cost( 0, 0, tableResult + 1 ); 396 cost = Cost::unsafe; 397 } else { 398 cost = Cost::zero; 399 cost.incSafe( tableResult + 1 ); 281 400 } 282 401 } else if ( dynamic_cast< PointerType* >( dest ) ) { 283 cost = Cost ( 0, 0, 1 );402 cost = Cost::safe; 284 403 } 285 404 } … … 292 411 int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->get_kind() ]; 293 412 if ( tableResult == -1 ) { 294 cost = Cost( 1, 0, 0 ); 295 } else { 296 cost = Cost( 0, 0, tableResult + 1 ); 413 cost = Cost::unsafe; 414 } else { 415 cost = Cost::zero; 416 cost.incSafe( tableResult + 1 ); 297 417 } 298 418 }
Note:
See TracChangeset
for help on using the changeset viewer.