Changeset 136ccd7 for src/ResolvExpr
- Timestamp:
- Nov 3, 2017, 3:01:31 PM (8 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, cleanup-dtors, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum, stuck-waitfor-destruct
- Children:
- 4ee36bf0
- Parents:
- 4ee1efb (diff), 760ba67 (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/ResolvExpr
- Files:
-
- 7 edited
-
AlternativeFinder.cc (modified) (4 diffs)
-
CommonType.cc (modified) (2 diffs)
-
ConversionCost.cc (modified) (12 diffs)
-
PolyCost.cc (modified) (3 diffs)
-
PtrsAssignable.cc (modified) (6 diffs)
-
PtrsCastable.cc (modified) (4 diffs)
-
Unify.cc (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/AlternativeFinder.cc
r4ee1efb r136ccd7 122 122 ) 123 123 mapPlace->second.isAmbiguous = true; 124 } else { 125 PRINT( 126 std::cerr << "cost " << candidate->cost << " loses to " << mapPlace->second.candidate->cost << std::endl; 127 ) 124 128 } 125 129 } else { … … 127 131 } 128 132 } 129 130 PRINT(131 std::cerr << "there are " << selected.size() << " alternatives before elimination" << std::endl;132 )133 133 134 134 // accept the alternatives that were unambiguous … … 181 181 } 182 182 if ( prune ) { 183 auto oldsize = alternatives.size(); 183 184 PRINT( 184 185 std::cerr << "alternatives before prune:" << std::endl; … … 198 199 } 199 200 alternatives.erase( oldBegin, alternatives.end() ); 201 PRINT( 202 std::cerr << "there are " << oldsize << " alternatives before elimination" << std::endl; 203 ) 200 204 PRINT( 201 205 std::cerr << "there are " << alternatives.size() << " alternatives after elimination" << std::endl; -
src/ResolvExpr/CommonType.cc
r4ee1efb r136ccd7 61 61 }; 62 62 63 Type * handleReference( ReferenceType * refType, Type * other, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment & env, const OpenVarSet &openVars ) {64 Type * result = nullptr, *common = nullptr;63 Type * handleReference( Type * t1, Type * t2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment & env, const OpenVarSet &openVars ) { 64 Type * common = nullptr; 65 65 AssertionSet have, need; 66 66 OpenVarSet newOpen( openVars ); 67 67 // need unify to bind type variables 68 if ( unify( refType->get_base(), other, env, have, need, newOpen, indexer, common ) ) { 69 // std::cerr << "unify success" << std::endl; 70 if ( widenSecond ) { 71 // std::cerr << "widen second" << std::endl; 72 if ( widenFirst || other->get_qualifiers() <= refType->get_qualifiers() ) { 73 result = new ReferenceType( refType->get_qualifiers(), common ); // refType->clone(); 74 result->get_qualifiers() |= other->get_qualifiers(); 75 } 76 } else if ( widenFirst ) { 77 // std::cerr << "widen first" << std::endl; 78 if ( widenSecond || refType->get_qualifiers() <= other->get_qualifiers() ) { 79 result = common; 80 result->get_qualifiers() |= refType->get_qualifiers(); 81 } 82 } 83 } else { 84 // std::cerr << "exact unify failed: " << refType << " " << other << std::endl; 85 } 86 // std::cerr << "common type of reference [" << refType << "] and non-reference [" << other << "] is [" << result << "]" << std::endl; 87 return result; 68 if ( unify( t1, t2, env, have, need, newOpen, indexer, common ) ) { 69 // std::cerr << "unify success: " << widenFirst << " " << widenSecond << std::endl; 70 if ( (widenFirst || t2->get_qualifiers() <= t1->get_qualifiers()) && (widenSecond || t1->get_qualifiers() <= t2->get_qualifiers()) ) { 71 // std::cerr << "widen okay" << std::endl; 72 common->get_qualifiers() |= t1->get_qualifiers(); 73 common->get_qualifiers() |= t2->get_qualifiers(); 74 return common; 75 } 76 } 77 // std::cerr << "exact unify failed: " << t1 << " " << t2 << std::endl; 78 return nullptr; 88 79 } 89 80 … … 99 90 100 91 // special case where one type has a reference depth of 1 larger than the other 101 if ( diff > 0 ) { 102 return handleReference( strict_dynamic_cast<ReferenceType *>( type1 ), type2, widenFirst, widenSecond, indexer, env, openVars ); 103 } else if ( diff < 0 ) { 104 return handleReference( strict_dynamic_cast<ReferenceType *>( type2 ), type1, widenSecond, widenFirst, indexer, env, openVars ); 92 if ( diff > 0 || diff < 0 ) { 93 Type * result = nullptr; 94 if ( ReferenceType * ref1 = dynamic_cast< ReferenceType * >( type1 ) ) { 95 // formal is reference, so result should be reference 96 result = handleReference( ref1->base, type2, widenFirst, widenSecond, indexer, env, openVars ); 97 if ( result ) result = new ReferenceType( ref1->get_qualifiers(), result ); 98 } else { 99 // formal is value, so result should be value 100 ReferenceType * ref2 = strict_dynamic_cast< ReferenceType * > ( type2 ); 101 result = handleReference( type1, ref2->base, widenFirst, widenSecond, indexer, env, openVars ); 102 } 103 // std::cerr << "common type of reference [" << type1 << "] and [" << type2 << "] is [" << result << "]" << std::endl; 104 return result; 105 105 } 106 106 // otherwise, both are reference types of the same depth and this is handled by the CommonType visitor. -
src/ResolvExpr/ConversionCost.cc
r4ee1efb r136ccd7 28 28 29 29 namespace ResolvExpr { 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 );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 36 37 37 #if 0 … … 113 113 int assignResult = func( srcAsRef->get_base(), destAsRef->get_base(), env, indexer ); 114 114 PRINT( std::cerr << "comparing references: " << assignResult << " " << srcAsRef << " " << destAsRef << std::endl; ) 115 if ( assignResult <0 ) {115 if ( assignResult > 0 ) { 116 116 return Cost::safe; 117 } else if ( assignResult >0 ) {117 } else if ( assignResult < 0 ) { 118 118 return Cost::unsafe; 119 119 } // if … … 269 269 } 270 270 271 void ConversionCost::visit( PointerType *pointerType) {271 void ConversionCost::visit( PointerType * pointerType ) { 272 272 if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) { 273 273 PRINT( std::cerr << pointerType << " ===> " << destAsPtr; ) … … 284 284 } 285 285 } else { // xxx - this discards qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right? 286 int assignResult = ptrsAssignable( pointerType-> get_base(), destAsPtr->get_base(), env );286 int assignResult = ptrsAssignable( pointerType->base, destAsPtr->base, env ); 287 287 PRINT( std::cerr << " :: " << assignResult << std::endl; ) 288 if ( assignResult <0 && pointerType->get_base()->get_qualifiers() <= destAsPtr->get_qualifiers() ) {288 if ( assignResult > 0 && pointerType->get_base()->get_qualifiers() <= destAsPtr->get_qualifiers() ) { 289 289 cost = Cost::safe; 290 } else if ( assignResult >0 ) {290 } else if ( assignResult < 0 ) { 291 291 cost = Cost::unsafe; 292 292 } // if 293 293 // assignResult == 0 means Cost::Infinity 294 294 } // if 295 } else if ( dynamic_cast< ZeroType * >( dest ) != nullptr || dynamic_cast< OneType* >( dest ) != nullptr) {295 } else if ( dynamic_cast< ZeroType * >( dest ) ) { 296 296 cost = Cost::unsafe; 297 297 } // if 298 298 } 299 299 300 void ConversionCost::visit( __attribute((unused)) ArrayType *arrayType) {}301 302 void ConversionCost::visit( ReferenceType *refType) {300 void ConversionCost::visit( ArrayType * ) {} 301 302 void ConversionCost::visit( ReferenceType * refType ) { 303 303 // Note: dest can never be a reference, since it would have been caught in an earlier check 304 304 assert( ! dynamic_cast< ReferenceType * >( dest ) ); … … 317 317 } 318 318 319 void ConversionCost::visit( __attribute((unused)) FunctionType *functionType) {}320 321 void ConversionCost::visit( StructInstType *inst) {319 void ConversionCost::visit( FunctionType * ) {} 320 321 void ConversionCost::visit( StructInstType * inst ) { 322 322 if ( StructInstType *destAsInst = dynamic_cast< StructInstType* >( dest ) ) { 323 323 if ( inst->name == destAsInst->name ) { … … 327 327 } 328 328 329 void ConversionCost::visit( UnionInstType *inst) {329 void ConversionCost::visit( UnionInstType * inst ) { 330 330 if ( UnionInstType *destAsInst = dynamic_cast< UnionInstType* >( dest ) ) { 331 331 if ( inst->name == destAsInst->name ) { … … 335 335 } 336 336 337 void ConversionCost::visit( __attribute((unused)) EnumInstType *inst) {337 void ConversionCost::visit( EnumInstType * ) { 338 338 static Type::Qualifiers q; 339 339 static BasicType integer( q, BasicType::SignedInt ); … … 344 344 } 345 345 346 void ConversionCost::visit( __attribute((unused)) TraitInstType *inst) { 347 } 348 349 void ConversionCost::visit(TypeInstType *inst) { 346 void ConversionCost::visit( TraitInstType * ) {} 347 348 void ConversionCost::visit( TypeInstType *inst ) { 350 349 EqvClass eqvClass; 351 350 NamedTypeDecl *namedType; … … 366 365 } 367 366 368 void ConversionCost::visit( __attribute((unused)) TupleType *tupleType) {367 void ConversionCost::visit( TupleType * tupleType ) { 369 368 Cost c = Cost::zero; 370 if ( TupleType * destAsTuple = dynamic_cast< TupleType* >( dest ) ) {371 std::list< Type * >::const_iterator srcIt = tupleType->get_types().begin();372 std::list< Type * >::const_iterator destIt = destAsTuple->get_types().begin();369 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(); 373 372 while ( srcIt != tupleType->get_types().end() && destIt != destAsTuple->get_types().end() ) { 374 373 Cost newCost = conversionCost( *srcIt++, *destIt++, indexer, env ); … … 386 385 } 387 386 388 void ConversionCost::visit( __attribute((unused)) VarArgsType *varArgsType) {387 void ConversionCost::visit( VarArgsType * ) { 389 388 if ( dynamic_cast< VarArgsType* >( dest ) ) { 390 389 cost = Cost::zero; … … 392 391 } 393 392 394 void ConversionCost::visit( __attribute((unused)) ZeroType *zeroType) {395 if ( dynamic_cast< ZeroType * >( dest ) ) {393 void ConversionCost::visit( ZeroType * ) { 394 if ( dynamic_cast< ZeroType * >( dest ) ) { 396 395 cost = Cost::zero; 397 396 } else if ( BasicType *destAsBasic = dynamic_cast< BasicType* >( dest ) ) { … … 409 408 } 410 409 411 void ConversionCost::visit( __attribute((unused)) OneType *oneType) {412 if ( dynamic_cast< OneType * >( dest ) ) {410 void ConversionCost::visit( OneType * ) { 411 if ( dynamic_cast< OneType * >( dest ) ) { 413 412 cost = Cost::zero; 414 413 } else if ( BasicType *destAsBasic = dynamic_cast< BasicType* >( dest ) ) { -
src/ResolvExpr/PolyCost.cc
r4ee1efb r136ccd7 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // PolyCost.cc -- 7 // PolyCost.cc -- 8 8 // 9 9 // Author : Richard C. Bilson … … 31 31 }; 32 32 33 int polyCost( Type *type, const TypeEnvironment & env, const SymTab::Indexer &indexer ) {33 int polyCost( Type *type, const TypeEnvironment & env, const SymTab::Indexer &indexer ) { 34 34 PolyCost coster( env, indexer ); 35 35 type->accept( coster ); … … 37 37 } 38 38 39 PolyCost::PolyCost( const TypeEnvironment & env, const SymTab::Indexer &indexer ) : result( 0 ), env( env ), indexer( indexer ) {39 PolyCost::PolyCost( const TypeEnvironment & env, const SymTab::Indexer & indexer ) : result( 0 ), env( env ), indexer( indexer ) { 40 40 } 41 41 42 void PolyCost::visit(TypeInstType * typeInst) {42 void PolyCost::visit(TypeInstType * typeInst) { 43 43 EqvClass eqvClass; 44 if ( env.lookup( typeInst-> get_name(), eqvClass ) ) {44 if ( env.lookup( typeInst->name, eqvClass ) ) { 45 45 if ( eqvClass.type ) { 46 if ( TypeInstType *otherTypeInst = dynamic_cast< TypeInstType* >( eqvClass.type ) ) { 47 if ( indexer.lookupType( otherTypeInst->get_name() ) ) { 46 if ( TypeInstType * otherTypeInst = dynamic_cast< TypeInstType* >( eqvClass.type ) ) { 47 if ( indexer.lookupType( otherTypeInst->name ) ) { 48 // bound to opaque type 48 49 result += 1; 49 50 } // if 50 51 } else { 52 // bound to concrete type 51 53 result += 1; 52 54 } // if -
src/ResolvExpr/PtrsAssignable.cc
r4ee1efb r136ccd7 47 47 48 48 int ptrsAssignable( Type *src, Type *dest, const TypeEnvironment &env ) { 49 // std::cerr << "assignable: " << src << " | " << dest << std::endl; 49 50 if ( TypeInstType *destAsTypeInst = dynamic_cast< TypeInstType* >( dest ) ) { 50 51 EqvClass eqvClass; … … 54 55 } // if 55 56 if ( dynamic_cast< VoidType* >( dest ) ) { 56 return 1; 57 // void * = T * for any T is unsafe 58 // xxx - this should be safe, but that currently breaks the build 59 return -1; 57 60 } else { 58 61 PtrsAssignable ptrs( dest, env ); … … 65 68 66 69 void PtrsAssignable::visit( __attribute((unused)) VoidType *voidType ) { 67 if ( dynamic_cast< FunctionType* >( dest ) ) {68 result = 0;69 } else {70 result = -1;70 if ( ! dynamic_cast< FunctionType* >( dest ) ) { 71 // T * = void * is safe for any T that is not a function type. 72 // xxx - this should be unsafe... 73 result = 1; 71 74 } // if 72 75 } … … 75 78 void PtrsAssignable::visit( __attribute__((unused)) PointerType *pointerType ) {} 76 79 void PtrsAssignable::visit( __attribute__((unused)) ArrayType *arrayType ) {} 77 void PtrsAssignable::visit( __attribute__((unused)) FunctionType *functionType ) { 78 result = -1; 79 } 80 void PtrsAssignable::visit( __attribute__((unused)) FunctionType *functionType ) {} 80 81 81 82 void PtrsAssignable::visit( __attribute__((unused)) StructInstType *inst ) {} … … 83 84 84 85 void PtrsAssignable::visit( EnumInstType * ) { 85 if ( dynamic_cast< EnumInstType* >( dest ) ) { 86 if ( dynamic_cast< BasicType* >( dest ) ) { 87 // int * = E *, etc. is safe. This isn't technically correct, as each 88 // enum has one basic type that it is compatible with, an that type can 89 // differ from enum to enum. Without replicating GCC's internal logic, 90 // there is no way to know which type this particular enum is compatible 91 // with, so punt on this for now. 86 92 result = 1; 87 } else if ( BasicType *bt = dynamic_cast< BasicType* >( dest ) ) {88 result = bt->get_kind() == BasicType::SignedInt;89 93 } 90 94 } … … 94 98 EqvClass eqvClass; 95 99 if ( env.lookup( inst->get_name(), eqvClass ) && eqvClass.type ) { 100 // T * = S * for any S depends on the type bound to T 96 101 result = ptrsAssignable( eqvClass.type, dest, env ); 97 } else {98 result = 0;99 102 } // if 100 103 } -
src/ResolvExpr/PtrsCastable.cc
r4ee1efb r136ccd7 50 50 }; 51 51 52 int objectCast( Type *src, const TypeEnvironment &env, const SymTab::Indexer &indexer ) { 53 if ( dynamic_cast< FunctionType* >( src ) ) { 54 return -1; 55 } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( src ) ) { 56 EqvClass eqvClass; 57 if ( NamedTypeDecl *ntDecl = indexer.lookupType( typeInst->get_name() ) ) { 58 if ( TypeDecl *tyDecl = dynamic_cast< TypeDecl* >( ntDecl ) ) { 59 if ( tyDecl->get_kind() == TypeDecl::Ftype ) { 52 namespace { 53 int objectCast( Type *src, const TypeEnvironment &env, const SymTab::Indexer &indexer ) { 54 if ( dynamic_cast< FunctionType* >( src ) ) { 55 return -1; 56 } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( src ) ) { 57 EqvClass eqvClass; 58 if ( NamedTypeDecl *ntDecl = indexer.lookupType( typeInst->get_name() ) ) { 59 if ( TypeDecl *tyDecl = dynamic_cast< TypeDecl* >( ntDecl ) ) { 60 if ( tyDecl->get_kind() == TypeDecl::Ftype ) { 61 return -1; 62 } // if 63 } //if 64 } else if ( env.lookup( typeInst->get_name(), eqvClass ) ) { 65 if ( eqvClass.data.kind == TypeDecl::Ftype ) { 60 66 return -1; 61 67 } // if 62 } //if63 } else if ( env.lookup( typeInst->get_name(), eqvClass ) ) {64 if ( eqvClass.data.kind == TypeDecl::Ftype ) {65 return -1;66 68 } // if 67 } // if68 } //if69 return 1;70 }71 int functionCast( Type *src, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {72 return -1 * objectCast( src, env, indexer ); // reverse the sense of objectCast69 } //if 70 return 1; 71 } 72 int functionCast( Type *src, const TypeEnvironment &env, const SymTab::Indexer &indexer ) { 73 return -1 * objectCast( src, env, indexer ); // reverse the sense of objectCast 74 } 73 75 } 74 76 … … 93 95 } 94 96 95 void PtrsCastable::visit( __attribute__((unused)) VoidType *voidType) {97 void PtrsCastable::visit( VoidType * ) { 96 98 result = objectCast( dest, env, indexer ); 97 99 } 98 100 99 void PtrsCastable::visit( __attribute__((unused)) BasicType *basicType) {101 void PtrsCastable::visit( BasicType * ) { 100 102 result = objectCast( dest, env, indexer ); 101 103 } 102 104 103 void PtrsCastable::visit( __attribute__((unused)) PointerType *pointerType) {105 void PtrsCastable::visit( PointerType * ) { 104 106 result = objectCast( dest, env, indexer ); 105 107 } 106 108 107 void PtrsCastable::visit( __attribute__((unused)) ArrayType *arrayType) {109 void PtrsCastable::visit( ArrayType * ) { 108 110 result = objectCast( dest, env, indexer ); 109 111 } 110 112 111 void PtrsCastable::visit( __attribute__((unused)) FunctionType *functionType) {113 void PtrsCastable::visit( FunctionType * ) { 112 114 // result = -1; 113 115 result = functionCast( dest, env, indexer ); 114 116 } 115 117 116 void PtrsCastable::visit( __attribute__((unused)) StructInstType *inst) {118 void PtrsCastable::visit( StructInstType * ) { 117 119 result = objectCast( dest, env, indexer ); 118 120 } 119 121 120 void PtrsCastable::visit( __attribute__((unused)) UnionInstType *inst) {122 void PtrsCastable::visit( UnionInstType * ) { 121 123 result = objectCast( dest, env, indexer ); 122 124 } 123 125 124 void PtrsCastable::visit( __attribute__((unused)) EnumInstType *inst) {126 void PtrsCastable::visit( EnumInstType * ) { 125 127 if ( dynamic_cast< EnumInstType* >( dest ) ) { 126 128 result = 1; … … 136 138 } 137 139 138 void PtrsCastable::visit( __attribute__((unused)) TraitInstType *inst) {}140 void PtrsCastable::visit( TraitInstType * ) {} 139 141 140 142 void PtrsCastable::visit(TypeInstType *inst) { … … 143 145 } 144 146 145 void PtrsCastable::visit( __attribute__((unused)) TupleType *tupleType) {147 void PtrsCastable::visit( TupleType * ) { 146 148 result = objectCast( dest, env, indexer ); 147 149 } 148 150 149 void PtrsCastable::visit( __attribute__((unused)) VarArgsType *varArgsType) {151 void PtrsCastable::visit( VarArgsType * ) { 150 152 result = objectCast( dest, env, indexer ); 151 153 } 152 154 153 void PtrsCastable::visit( __attribute__((unused)) ZeroType *zeroType) {155 void PtrsCastable::visit( ZeroType * ) { 154 156 result = objectCast( dest, env, indexer ); 155 157 } 156 158 157 void PtrsCastable::visit( __attribute__((unused)) OneType *oneType) {159 void PtrsCastable::visit( OneType * ) { 158 160 result = objectCast( dest, env, indexer ); 159 161 } -
src/ResolvExpr/Unify.cc
r4ee1efb r136ccd7 138 138 bool tyVarCompatible( const TypeDecl::Data & data, Type *type ) { 139 139 switch ( data.kind ) { 140 case TypeDecl::Any:141 140 case TypeDecl::Dtype: 142 141 // to bind to an object type variable, the type must not be a function type.
Note:
See TracChangeset
for help on using the changeset viewer.