Changeset d3e4d6c for src/ResolvExpr
- Timestamp:
- Aug 23, 2017, 6:22:07 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:
- 87e08e24, cb811ac
- Parents:
- 9f07232 (diff), bd37119 (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:
-
- 12 edited
-
Alternative.cc (modified) (2 diffs)
-
Alternative.h (modified) (1 diff)
-
AlternativeFinder.cc (modified) (31 diffs)
-
CastCost.cc (modified) (6 diffs)
-
CommonType.cc (modified) (12 diffs)
-
ConversionCost.cc (modified) (11 diffs)
-
ConversionCost.h (modified) (2 diffs)
-
Cost.h (modified) (4 diffs)
-
PtrsAssignable.cc (modified) (3 diffs)
-
ResolveTypeof.cc (modified) (1 diff)
-
Unify.cc (modified) (4 diffs)
-
typeops.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/Alternative.cc
r9f07232 rd3e4d6c 34 34 : cost( cost ), cvtCost( cvtCost ), expr( expr ), env( env ) {} 35 35 36 Alternative::Alternative( const Alternative &other ) { 37 initialize( other, *this ); 36 Alternative::Alternative( const Alternative &other ) : cost( other.cost ), cvtCost( other.cvtCost ), expr( maybeClone( other.expr ) ), env( other.env ) { 38 37 } 39 38 40 39 Alternative &Alternative::operator=( const Alternative &other ) { 41 40 if ( &other == this ) return *this; 42 initialize( other, *this ); 41 delete expr; 42 cost = other.cost; 43 cvtCost = other.cvtCost; 44 expr = maybeClone( other.expr ); 45 env = other.env; 43 46 return *this; 44 47 } … … 57 60 other.expr = nullptr; 58 61 return *this; 59 }60 61 void Alternative::initialize( const Alternative &src, Alternative &dest ) {62 dest.cost = src.cost;63 dest.cvtCost = src.cvtCost;64 dest.expr = maybeClone( src.expr );65 dest.env = src.env;66 62 } 67 63 -
src/ResolvExpr/Alternative.h
r9f07232 rd3e4d6c 39 39 ~Alternative(); 40 40 41 void initialize( const Alternative &src, Alternative &dest );42 43 41 void print( std::ostream &os, int indent = 0 ) const; 44 42 -
src/ResolvExpr/AlternativeFinder.cc
r9f07232 rd3e4d6c 67 67 68 68 Cost sumCost( const AltList &in ) { 69 Cost total ;69 Cost total = Cost::zero; 70 70 for ( AltList::const_iterator i = in.begin(); i != in.end(); ++i ) { 71 71 total += i->cost; … … 144 144 expr->get_result()->accept( global_renamer ); 145 145 } 146 } 146 147 void referenceToRvalueConversion( Expression *& expr ) { 148 if ( dynamic_cast< ReferenceType * >( expr->get_result() ) ) { 149 // cast away reference from expr 150 expr = new CastExpr( expr, expr->get_result()->stripReferences()->clone() ); 151 } 152 } 153 } // namespace 147 154 148 155 template< typename InputIterator, typename OutputIterator > … … 186 193 if ( alternatives.begin() == oldBegin ) { 187 194 std::ostringstream stream; 188 stream << "Can't choose between " << alternatives.size() << " alternatives for expression "; 195 AltList winners; 196 findMinCost( alternatives.begin(), alternatives.end(), back_inserter( winners ) ); 197 stream << "Can't choose between " << winners.size() << " alternatives for expression "; 189 198 expr->print( stream ); 190 199 stream << "Alternatives are:"; 191 AltList winners;192 findMinCost( alternatives.begin(), alternatives.end(), back_inserter( winners ) );193 200 printAlts( winners, stream, 8 ); 194 201 throw SemanticError( stream.str() ); … … 213 220 void AlternativeFinder::addAnonConversions( const Alternative & alt ) { 214 221 // adds anonymous member interpretations whenever an aggregate value type is seen. 215 Expression * expr = alt.expr->clone(); 216 std::unique_ptr< Expression > manager( expr ); // RAII for expr 217 alt.env.apply( expr->get_result() ); 218 if ( StructInstType *structInst = dynamic_cast< StructInstType* >( expr->get_result() ) ) { 222 // it's okay for the aggregate expression to have reference type -- cast it to the base type to treat the aggregate as the referenced value 223 std::unique_ptr<Expression> aggrExpr( alt.expr->clone() ); 224 alt.env.apply( aggrExpr->get_result() ); 225 Type * aggrType = aggrExpr->get_result(); 226 if ( dynamic_cast< ReferenceType * >( aggrType ) ) { 227 aggrType = aggrType->stripReferences(); 228 aggrExpr.reset( new CastExpr( aggrExpr.release(), aggrType->clone() ) ); 229 } 230 231 if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->get_result() ) ) { 219 232 NameExpr nameExpr( "" ); 220 addAggMembers( structInst, expr, alt.cost+Cost( 0, 0, 1 ), alt.env, &nameExpr );221 } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( expr->get_result() ) ) {233 addAggMembers( structInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, &nameExpr ); 234 } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->get_result() ) ) { 222 235 NameExpr nameExpr( "" ); 223 addAggMembers( unionInst, expr, alt.cost+Cost( 0, 0, 1 ), alt.env, &nameExpr );236 addAggMembers( unionInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, &nameExpr ); 224 237 } // if 225 238 } … … 228 241 void AlternativeFinder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) { 229 242 // by this point, member must be a name expr 230 NameExpr * nameExpr = safe_dynamic_cast< NameExpr * >( member ); 243 NameExpr * nameExpr = dynamic_cast< NameExpr * >( member ); 244 if ( ! nameExpr ) return; 231 245 const std::string & name = nameExpr->get_name(); 232 246 std::list< Declaration* > members; … … 250 264 // during parsing and reusing that information here. 251 265 std::stringstream ss( constantExpr->get_constant()->get_value() ); 252 int val ;266 int val = 0; 253 267 std::string tmp; 254 268 if ( ss >> val && ! (ss >> tmp) ) { … … 277 291 FunctionType *function = safe_dynamic_cast< FunctionType* >( pointer->get_base() ); 278 292 279 Cost convCost ( 0, 0, 0 );293 Cost convCost = Cost::zero; 280 294 std::list< DeclarationWithType* >& formals = function->get_parameters(); 281 295 std::list< DeclarationWithType* >::iterator formal = formals.begin(); … … 290 304 actualType->print( std::cerr, 8 ); 291 305 ) 292 Cost actualCost ;306 Cost actualCost = Cost::zero; 293 307 if ( formal == formals.end() ) { 294 308 if ( function->get_isVarArgs() ) { 295 convCost += Cost( 1, 0, 0 ); 309 convCost.incUnsafe(); 310 // convert reference-typed expressions to value-typed expressions 311 referenceToRvalueConversion( *actualExpr ); 296 312 continue; 297 313 } else { … … 305 321 std::cerr << std::endl << " to "; 306 322 formalType->print( std::cerr, 8 ); 323 std::cerr << std::endl << "environment is: "; 324 alt.env.print( std::cerr, 8 ); 325 std::cerr << std::endl; 307 326 ) 308 327 Cost newCost = conversionCost( actualType, formalType, indexer, alt.env ); … … 316 335 convCost += newCost; 317 336 actualCost += newCost; 318 if ( actualCost != Cost ( 0, 0, 0 )) {337 if ( actualCost != Cost::zero ) { 319 338 Type *newType = formalType->clone(); 320 339 alt.env.apply( newType ); 321 340 *actualExpr = new CastExpr( *actualExpr, newType ); 322 341 } 323 convCost += Cost( 0, polyCost( formalType, alt.env, indexer ) + polyCost( actualType, alt.env, indexer ), 0);342 convCost.incPoly( polyCost( formalType, alt.env, indexer ) + polyCost( actualType, alt.env, indexer ) ); 324 343 ++formal; // can't be in for-loop update because of the continue 325 344 } … … 343 362 } 344 363 convCost += newCost; 345 convCost += Cost( 0, polyCost( assert->second.formalType, alt.env, indexer ) + polyCost( assert->second.actualType, alt.env, indexer ), 0);364 convCost.incPoly( polyCost( assert->second.formalType, alt.env, indexer ) + polyCost( assert->second.actualType, alt.env, indexer ) ); 346 365 } 347 366 … … 400 419 Expression * actual = actualIt->expr; 401 420 Type * actualType = actual->get_result(); 421 402 422 PRINT( 403 423 std::cerr << "formal type is "; … … 408 428 ) 409 429 if ( ! unify( formalType, actualType, resultEnv, resultNeed, resultHave, openVars, indexer ) ) { 430 // std::cerr << "unify failed" << std::endl; 410 431 return false; 411 432 } … … 452 473 // match flattened actuals with formal parameters - actuals will be grouped to match 453 474 // with formals as appropriate 454 Cost cost ;475 Cost cost = Cost::zero; 455 476 std::list< Expression * > newExprs; 456 477 ObjectDecl * obj = safe_dynamic_cast< ObjectDecl * >( formal ); … … 613 634 AssertionSet newNeed; 614 635 //AssertionParentSet needParents; 636 PRINT( 637 std::cerr << "env is: " << std::endl; 638 newAlt.env.print( std::cerr, 0 ); 639 std::cerr << std::endl; 640 ) 641 615 642 inferRecursive( need.begin(), need.end(), newAlt, openVars, decls, newNeed, /*needParents,*/ 0, indexer, out ); 616 643 // PRINT( … … 643 670 makeExprList( instantiatedActuals, appExpr->get_args() ); 644 671 PRINT( 672 std::cerr << "instantiate function success: " << appExpr << std::endl; 645 673 std::cerr << "need assertions:" << std::endl; 646 674 printAssertionSet( resultNeed, std::cerr, 8 ); … … 663 691 UntypedExpr *vexpr = untypedExpr->clone(); 664 692 vexpr->set_result( pt.clone() ); 665 alternatives.push_back( Alternative( vexpr, env, Cost ()) );693 alternatives.push_back( Alternative( vexpr, env, Cost::zero) ); 666 694 return; 667 695 } … … 681 709 AltList candidates; 682 710 SemanticError errors; 683 for ( AltList:: const_iterator func = funcFinder.alternatives.begin(); func != funcFinder.alternatives.end(); ++func ) {711 for ( AltList::iterator func = funcFinder.alternatives.begin(); func != funcFinder.alternatives.end(); ++func ) { 684 712 try { 685 713 PRINT( … … 688 716 ) 689 717 // check if the type is pointer to function 690 PointerType *pointer; 691 if ( ( pointer = dynamic_cast< PointerType* >( func->expr->get_result() ) ) ) { 718 if ( PointerType *pointer = dynamic_cast< PointerType* >( func->expr->get_result()->stripReferences() ) ) { 692 719 if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() ) ) { 720 referenceToRvalueConversion( func->expr ); 693 721 for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) { 694 722 // XXX … … 696 724 makeFunctionAlternatives( *func, function, *actualAlt, std::back_inserter( candidates ) ); 697 725 } 698 } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( pointer->get_base() ) ) { 699 EqvClass eqvClass; 700 if ( func->env.lookup( typeInst->get_name(), eqvClass ) && eqvClass.type ) { 701 if ( FunctionType *function = dynamic_cast< FunctionType* >( eqvClass.type ) ) { 702 for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) { 703 makeFunctionAlternatives( *func, function, *actualAlt, std::back_inserter( candidates ) ); 704 } // for 705 } // if 726 } 727 } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( func->expr->get_result()->stripReferences() ) ) { // handle ftype (e.g. *? on function pointer) 728 referenceToRvalueConversion( func->expr ); 729 EqvClass eqvClass; 730 if ( func->env.lookup( typeInst->get_name(), eqvClass ) && eqvClass.type ) { 731 if ( FunctionType *function = dynamic_cast< FunctionType* >( eqvClass.type ) ) { 732 for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) { 733 makeFunctionAlternatives( *func, function, *actualAlt, std::back_inserter( candidates ) ); 734 } // for 706 735 } // if 707 736 } // if … … 722 751 } 723 752 724 for ( AltList:: const_iterator funcOp = funcOpFinder.alternatives.begin(); funcOp != funcOpFinder.alternatives.end(); ++funcOp ) {753 for ( AltList::iterator funcOp = funcOpFinder.alternatives.begin(); funcOp != funcOpFinder.alternatives.end(); ++funcOp ) { 725 754 // check if the type is pointer to function 726 PointerType *pointer; 727 if ( ( pointer = dynamic_cast< PointerType* >( funcOp->expr->get_result() ) ) ) { 755 if ( PointerType *pointer = dynamic_cast< PointerType* >( funcOp->expr->get_result()->stripReferences() ) ) { 728 756 if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() ) ) { 757 referenceToRvalueConversion( funcOp->expr ); 729 758 for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) { 730 759 AltList currentAlt; … … 753 782 PointerType *pointer = safe_dynamic_cast< PointerType* >( appExpr->get_function()->get_result() ); 754 783 FunctionType *function = safe_dynamic_cast< FunctionType* >( pointer->get_base() ); 755 std::cerr << "Case +++++++++++++ "<< std::endl;784 std::cerr << "Case +++++++++++++ " << appExpr->get_function() << std::endl; 756 785 std::cerr << "formals are:" << std::endl; 757 786 printAll( function->get_parameters(), std::cerr, 8 ); … … 796 825 bool isLvalue( Expression *expr ) { 797 826 // xxx - recurse into tuples? 798 return expr->has_result() && expr->get_result()->get_lvalue();827 return expr->has_result() && ( expr->get_result()->get_lvalue() || dynamic_cast< ReferenceType * >( expr->get_result() ) ); 799 828 } 800 829 … … 810 839 811 840 Expression * restructureCast( Expression * argExpr, Type * toType ) { 812 if ( argExpr->get_result()->size() > 1 && ! toType->isVoid() ) { 813 // Argument expression is a tuple and the target type is not void. Cast each member of the tuple 814 // to its corresponding target type, producing the tuple of those cast expressions. If there are 815 // more components of the tuple than components in the target type, then excess components do not 816 // come out in the result expression (but UniqueExprs ensure that side effects will still be done). 817 if ( Tuples::maybeImpure( argExpr ) && ! dynamic_cast< UniqueExpr * >( argExpr ) ) { 841 if ( argExpr->get_result()->size() > 1 && ! toType->isVoid() && ! dynamic_cast<ReferenceType *>( toType ) ) { 842 // Argument expression is a tuple and the target type is not void and not a reference type. 843 // Cast each member of the tuple to its corresponding target type, producing the tuple of those 844 // cast expressions. If there are more components of the tuple than components in the target type, 845 // then excess components do not come out in the result expression (but UniqueExprs ensure that 846 // side effects will still be done). 847 if ( Tuples::maybeImpureIgnoreUnique( argExpr ) ) { 818 848 // expressions which may contain side effects require a single unique instance of the expression. 819 849 argExpr = new UniqueExpr( argExpr ); … … 855 885 // that are cast directly. The candidate is invalid if it has fewer results than there are types to cast 856 886 // to. 857 int discardedValues = (*i).expr->get_result()->size() - castExpr->get_result()->size();887 int discardedValues = i->expr->get_result()->size() - castExpr->get_result()->size(); 858 888 if ( discardedValues < 0 ) continue; 859 889 // xxx - may need to go into tuple types and extract relevant types and use unifyList. Note that currently, this does not 860 890 // allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3])) 861 891 // unification run for side-effects 862 unify( castExpr->get_result(), (*i).expr->get_result(), i->env, needAssertions, haveAssertions, openVars, indexer );863 Cost thisCost = castCost( (*i).expr->get_result(), castExpr->get_result(), indexer, i->env );892 unify( castExpr->get_result(), i->expr->get_result(), i->env, needAssertions, haveAssertions, openVars, indexer ); 893 Cost thisCost = castCost( i->expr->get_result(), castExpr->get_result(), indexer, i->env ); 864 894 if ( thisCost != Cost::infinity ) { 865 895 // count one safe conversion for each value that is thrown away 866 thisCost += Cost( 0, 0,discardedValues );896 thisCost.incSafe( discardedValues ); 867 897 868 898 candidates.push_back( Alternative( restructureCast( i->expr->clone(), toType ), i->env, i->cost, thisCost ) ); … … 895 925 funcFinder.findWithAdjustment( memberExpr->get_aggregate() ); 896 926 for ( AltList::const_iterator agg = funcFinder.alternatives.begin(); agg != funcFinder.alternatives.end(); ++agg ) { 897 if ( StructInstType *structInst = dynamic_cast< StructInstType* >( agg->expr->get_result() ) ) { 898 addAggMembers( structInst, agg->expr, agg->cost, agg->env, memberExpr->get_member() ); 899 } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( agg->expr->get_result() ) ) { 900 addAggMembers( unionInst, agg->expr, agg->cost, agg->env, memberExpr->get_member() ); 901 } else if ( TupleType * tupleType = dynamic_cast< TupleType * >( agg->expr->get_result() ) ) { 902 addTupleMembers( tupleType, agg->expr, agg->cost, agg->env, memberExpr->get_member() ); 927 // it's okay for the aggregate expression to have reference type -- cast it to the base type to treat the aggregate as the referenced value 928 std::unique_ptr<Expression> aggrExpr( agg->expr->clone() ); 929 Type * aggrType = aggrExpr->get_result(); 930 if ( dynamic_cast< ReferenceType * >( aggrType ) ) { 931 aggrType = aggrType->stripReferences(); 932 aggrExpr.reset( new CastExpr( aggrExpr.release(), aggrType->clone() ) ); 933 } 934 // find member of the given type 935 if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->get_result() ) ) { 936 addAggMembers( structInst, aggrExpr.get(), agg->cost, agg->env, memberExpr->get_member() ); 937 } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->get_result() ) ) { 938 addAggMembers( unionInst, aggrExpr.get(), agg->cost, agg->env, memberExpr->get_member() ); 939 } else if ( TupleType * tupleType = dynamic_cast< TupleType * >( aggrExpr->get_result() ) ) { 940 addTupleMembers( tupleType, aggrExpr.get(), agg->cost, agg->env, memberExpr->get_member() ); 903 941 } // if 904 942 } // for … … 915 953 for ( std::list< DeclarationWithType* >::iterator i = declList.begin(); i != declList.end(); ++i ) { 916 954 VariableExpr newExpr( *i, nameExpr->get_argName() ); 917 alternatives.push_back( Alternative( newExpr.clone(), env, Cost ()) );955 alternatives.push_back( Alternative( newExpr.clone(), env, Cost::zero ) ); 918 956 PRINT( 919 957 std::cerr << "decl is "; … … 955 993 // return the lowest cost alternative for the argument 956 994 Alternative &choice = winners.front(); 995 referenceToRvalueConversion( choice.expr ); 957 996 alternatives.push_back( Alternative( new SizeofExpr( choice.expr->clone() ), choice.env, Cost::zero ) ); 958 997 } // if … … 975 1014 // return the lowest cost alternative for the argument 976 1015 Alternative &choice = winners.front(); 1016 referenceToRvalueConversion( choice.expr ); 977 1017 alternatives.push_back( Alternative( new AlignofExpr( choice.expr->clone() ), choice.env, Cost::zero ) ); 978 1018 } // if … … 1059 1099 for ( std::list< DeclarationWithType* >::iterator i = attrList.begin(); i != attrList.end(); ++i ) { 1060 1100 VariableExpr newExpr( *i ); 1061 alternatives.push_back( Alternative( newExpr.clone(), env, Cost ()) );1101 alternatives.push_back( Alternative( newExpr.clone(), env, Cost::zero ) ); 1062 1102 renameTypes( alternatives.back().expr ); 1063 1103 } // for … … 1232 1272 if ( thisCost != Cost::infinity ) { 1233 1273 // count one safe conversion for each value that is thrown away 1234 thisCost += Cost( 0, 0,discardedValues );1274 thisCost.incSafe( discardedValues ); 1235 1275 candidates.push_back( Alternative( new InitExpr( restructureCast( alt.expr->clone(), toType ), initAlt.designation->clone() ), newEnv, alt.cost, thisCost ) ); 1236 1276 } -
src/ResolvExpr/CastCost.cc
r9f07232 rd3e4d6c 49 49 assert( type ); 50 50 if ( type->get_base() ) { 51 return castCost( src, type->get_base(), indexer, env ) + Cost ( 0, 0, 1 );51 return castCost( src, type->get_base(), indexer, env ) + Cost::safe; 52 52 } // if 53 53 } // if 54 54 } // if 55 55 if ( typesCompatibleIgnoreQualifiers( src, dest, indexer, env ) ) { 56 return Cost ( 0, 0, 0 );56 return Cost::zero; 57 57 } else if ( dynamic_cast< VoidType* >( dest ) ) { 58 return Cost( 0, 0, 1 ); 58 return Cost::safe; 59 } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( dest ) ) { 60 return convertToReferenceCost( src, refType, indexer, env ); 59 61 } else { 60 62 CastCost converter( dest, indexer, env ); … … 64 66 } else { 65 67 // xxx - why are we adding cost 0 here? 66 return converter.get_cost() + Cost ( 0, 0, 0 );68 return converter.get_cost() + Cost::zero; 67 69 } // if 68 70 } // if … … 77 79 if ( destAsPointer && basicType->isInteger() ) { 78 80 // necessary for, e.g. unsigned long => void* 79 cost = Cost ( 1, 0, 0 );81 cost = Cost::unsafe; 80 82 } else { 81 ConversionCost::visit( basicType);83 cost = conversionCost( basicType, dest, indexer, env ); 82 84 } // if 83 85 } … … 86 88 if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) { 87 89 if ( pointerType->get_qualifiers() <= destAsPtr->get_qualifiers() && typesCompatibleIgnoreQualifiers( pointerType->get_base(), destAsPtr->get_base(), indexer, env ) ) { 88 cost = Cost ( 0, 0, 1 );90 cost = Cost::safe; 89 91 } else { 90 92 TypeEnvironment newEnv( env ); … … 93 95 int castResult = ptrsCastable( pointerType->get_base(), destAsPtr->get_base(), newEnv, indexer ); 94 96 if ( castResult > 0 ) { 95 cost = Cost ( 0, 0, 1 );97 cost = Cost::safe; 96 98 } else if ( castResult < 0 ) { 97 99 cost = Cost::infinity; … … 101 103 if ( destAsBasic->isInteger() ) { 102 104 // necessary for, e.g. void* => unsigned long 103 cost = Cost ( 1, 0, 0 );105 cost = Cost::unsafe; 104 106 } // if 105 107 } -
src/ResolvExpr/CommonType.cc
r9f07232 rd3e4d6c 26 26 #include "typeops.h" // for isFtype 27 27 28 29 /// #define DEBUG 28 // #define DEBUG 30 29 31 30 namespace ResolvExpr { … … 39 38 virtual void visit( PointerType *pointerType ); 40 39 virtual void visit( ArrayType *arrayType ); 40 virtual void visit( ReferenceType *refType ); 41 41 virtual void visit( FunctionType *functionType ); 42 42 virtual void visit( StructInstType *aggregateUseType ); … … 50 50 virtual void visit( OneType *oneType ); 51 51 52 void getCommonWithVoidPointer( PointerType* voidPointer, PointerType* otherPointer ); 52 template< typename Pointer > void getCommonWithVoidPointer( Pointer* voidPointer, Pointer* otherPointer ); 53 template< typename RefType > void handleRefType( RefType *inst, Type *other ); 53 54 54 55 Type *result; … … 60 61 }; 61 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; 65 AssertionSet have, need; 66 OpenVarSet newOpen( openVars ); 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; 88 } 89 62 90 Type *commonType( Type *type1, Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars ) { 63 91 CommonType visitor( type2, widenFirst, widenSecond, indexer, env, openVars ); 92 93 int depth1 = type1->referenceDepth(); 94 int depth2 = type2->referenceDepth(); 95 if ( depth1 > 0 || depth2 > 0 ) { 96 int diff = depth1-depth2; 97 // TODO: should it be possible for commonType to generate complicated conversions? I would argue no, only conversions that involve types of the same reference level or a difference of 1 should be allowed. 98 if ( diff > 1 || diff < -1 ) return nullptr; 99 100 // special case where one type has a reference depth of 1 larger than the other 101 if ( diff > 0 ) { 102 return handleReference( safe_dynamic_cast<ReferenceType *>( type1 ), type2, widenFirst, widenSecond, indexer, env, openVars ); 103 } else if ( diff < 0 ) { 104 return handleReference( safe_dynamic_cast<ReferenceType *>( type2 ), type1, widenSecond, widenFirst, indexer, env, openVars ); 105 } 106 // otherwise, both are reference types of the same depth and this is handled by the CommonType visitor. 107 } 108 64 109 type1->accept( visitor ); 65 110 Type *result = visitor.get_result(); … … 88 133 } // if 89 134 #ifdef DEBUG 90 std::c out<< "============= commonType" << std::endl << "type1 is ";91 type1->print( std::c out);92 std::c out<< " type2 is ";93 type2->print( std::c out);135 std::cerr << "============= commonType" << std::endl << "type1 is "; 136 type1->print( std::cerr ); 137 std::cerr << " type2 is "; 138 type2->print( std::cerr ); 94 139 if ( result ) { 95 std::c out<< " common type is ";96 result->print( std::c out);140 std::cerr << " common type is "; 141 result->print( std::cerr ); 97 142 } else { 98 std::c out<< " no common type";99 } // if 100 std::c out<< std::endl;143 std::cerr << " no common type"; 144 } // if 145 std::cerr << std::endl; 101 146 #endif 102 147 return result; … … 150 195 } 151 196 152 void CommonType::getCommonWithVoidPointer( PointerType* voidPointer, PointerType* otherPointer ) { 197 template< typename Pointer > 198 void CommonType::getCommonWithVoidPointer( Pointer* voidPointer, Pointer* otherPointer ) { 153 199 if ( TypeInstType* var = dynamic_cast< TypeInstType* >( otherPointer->get_base() ) ) { 154 200 OpenVarSet::const_iterator entry = openVars.find( var->get_name() ); … … 165 211 void CommonType::visit( PointerType *pointerType ) { 166 212 if ( PointerType *otherPointer = dynamic_cast< PointerType* >( type2 ) ) { 213 // std::cerr << "commonType: two pointers: " << pointerType << " / " << otherPointer << std::endl; 167 214 if ( widenFirst && dynamic_cast< VoidType* >( otherPointer->get_base() ) && ! isFtype(pointerType->get_base()) ) { 168 215 getCommonWithVoidPointer( otherPointer, pointerType ); … … 171 218 } else if ( ( pointerType->get_base()->get_qualifiers() >= otherPointer->get_base()->get_qualifiers() || widenFirst ) 172 219 && ( pointerType->get_base()->get_qualifiers() <= otherPointer->get_base()->get_qualifiers() || widenSecond ) ) { 220 // std::cerr << "middle case" << std::endl; 173 221 Type::Qualifiers tq1 = pointerType->get_base()->get_qualifiers(), tq2 = otherPointer->get_base()->get_qualifiers(); 174 222 pointerType->get_base()->get_qualifiers() = Type::Qualifiers(); … … 177 225 OpenVarSet newOpen( openVars ); 178 226 if ( unifyExact( pointerType->get_base(), otherPointer->get_base(), env, have, need, newOpen, indexer ) ) { 227 // std::cerr << "unifyExact success" << std::endl; 179 228 if ( tq1 < tq2 ) { 180 229 result = pointerType->clone(); … … 184 233 result->get_qualifiers() = tq1 | tq2; 185 234 } else { 186 /// std::c out<< "place for ptr-to-type" << std::endl;235 /// std::cerr << "place for ptr-to-type" << std::endl; 187 236 } // if 188 237 pointerType->get_base()->get_qualifiers() = tq1; … … 196 245 197 246 void CommonType::visit( __attribute((unused)) ArrayType *arrayType ) {} 247 248 void CommonType::visit( ReferenceType *refType ) { 249 if ( ReferenceType *otherRef = dynamic_cast< ReferenceType* >( type2 ) ) { 250 // std::cerr << "commonType: both references: " << refType << " / " << otherRef << std::endl; 251 // std::cerr << ( refType->get_base()->get_qualifiers() >= otherRef->get_base()->get_qualifiers() || widenFirst ) << (refType->get_base()->get_qualifiers() <= otherRef->get_base()->get_qualifiers() || widenSecond) << std::endl; 252 if ( widenFirst && dynamic_cast< VoidType* >( otherRef->get_base() ) && ! isFtype(refType->get_base()) ) { 253 getCommonWithVoidPointer( otherRef, refType ); 254 } else if ( widenSecond && dynamic_cast< VoidType* >( refType->get_base() ) && ! isFtype(otherRef->get_base()) ) { 255 getCommonWithVoidPointer( refType, otherRef ); 256 } else if ( ( refType->get_base()->get_qualifiers() >= otherRef->get_base()->get_qualifiers() || widenFirst ) 257 && ( refType->get_base()->get_qualifiers() <= otherRef->get_base()->get_qualifiers() || widenSecond ) ) { 258 // std::cerr << "middle case" << std::endl; 259 Type::Qualifiers tq1 = refType->get_base()->get_qualifiers(), tq2 = otherRef->get_base()->get_qualifiers(); 260 refType->get_base()->get_qualifiers() = Type::Qualifiers(); 261 otherRef->get_base()->get_qualifiers() = Type::Qualifiers(); 262 AssertionSet have, need; 263 OpenVarSet newOpen( openVars ); 264 if ( unifyExact( refType->get_base(), otherRef->get_base(), env, have, need, newOpen, indexer ) ) { 265 if ( tq1 < tq2 ) { 266 result = refType->clone(); 267 } else { 268 result = otherRef->clone(); 269 } // if 270 result->get_qualifiers() = tq1 | tq2; 271 } else { 272 /// std::cerr << "place for ptr-to-type" << std::endl; 273 } // if 274 refType->get_base()->get_qualifiers() = tq1; 275 otherRef->get_base()->get_qualifiers() = tq2; 276 } // if 277 } else if ( widenSecond && dynamic_cast< ZeroType* >( type2 ) ) { 278 result = refType->clone(); 279 result->get_qualifiers() |= type2->get_qualifiers(); 280 } // if 281 } 282 198 283 void CommonType::visit( __attribute((unused)) FunctionType *functionType ) {} 199 284 void CommonType::visit( __attribute((unused)) StructInstType *aggregateUseType ) {} … … 203 288 if ( dynamic_cast< BasicType * >( type2 ) || dynamic_cast< ZeroType* >( type2 ) || dynamic_cast< OneType* >( type2 ) ) { 204 289 // reuse BasicType, EnumInstType code by swapping type2 with enumInstType 205 Type * temp = type2;290 ValueGuard< Type * > temp( type2 ); 206 291 type2 = enumInstType; 207 temp->accept( *this ); 208 type2 = temp; 292 temp.old->accept( *this ); 209 293 } // if 210 294 } -
src/ResolvExpr/ConversionCost.cc
r9f07232 rd3e4d6c 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 } -
src/ResolvExpr/ConversionCost.h
r9f07232 rd3e4d6c 37 37 virtual void visit(PointerType *pointerType); 38 38 virtual void visit(ArrayType *arrayType); 39 virtual void visit(ReferenceType *refType); 39 40 virtual void visit(FunctionType *functionType); 40 41 virtual void visit(StructInstType *aggregateUseType); … … 53 54 const TypeEnvironment &env; 54 55 }; 56 57 Cost convertToReferenceCost( Type * src, ReferenceType * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env ); 55 58 } // namespace ResolvExpr 56 59 -
src/ResolvExpr/Cost.h
r9f07232 rd3e4d6c 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // Cost.h -- 7 // Cost.h -- 8 8 // 9 9 // Author : Richard C. Bilson … … 20 20 namespace ResolvExpr { 21 21 class Cost { 22 private: 23 Cost( int unsafeCost, int polyCost, int safeCost, int referenceCost ); 24 22 25 public: 23 Cost(); 24 Cost( int unsafe, int poly, int safe ); 25 26 void incUnsafe( int inc = 1 ); 27 void incPoly( int inc = 1 ); 28 void incSafe( int inc = 1 ); 29 26 Cost & incUnsafe( int inc = 1 ); 27 Cost & incPoly( int inc = 1 ); 28 Cost & incSafe( int inc = 1 ); 29 Cost & incReference( int inc = 1 ); 30 30 31 Cost operator+( const Cost &other ) const; 31 32 Cost operator-( const Cost &other ) const; … … 35 36 bool operator!=( const Cost &other ) const; 36 37 friend std::ostream &operator<<( std::ostream &os, const Cost &cost ); 37 38 38 39 static const Cost zero; 39 40 static const Cost infinity; 41 42 static const Cost unsafe; 43 static const Cost poly; 44 static const Cost safe; 45 static const Cost reference; 40 46 private: 41 47 int compare( const Cost &other ) const; 42 48 43 int unsafe; 44 int poly; 45 int safe; 49 int unsafeCost; 50 int polyCost; 51 int safeCost; 52 int referenceCost; 46 53 }; 47 54 48 inline Cost::Cost( ) : unsafe( 0 ), poly( 0 ), safe( 0) {}55 inline Cost::Cost( int unsafeCost, int polyCost, int safeCost, int referenceCost ) : unsafeCost( unsafeCost ), polyCost( polyCost ), safeCost( safeCost ), referenceCost( referenceCost ) {} 49 56 50 inline Cost ::Cost( int unsafe, int poly, int safe ) : unsafe( unsafe ), poly( poly ), safe( safe ) {}51 52 inline void Cost::incUnsafe( int inc ) {53 unsafe += inc;57 inline Cost & Cost::incUnsafe( int inc ) { 58 if ( *this == infinity ) return *this; 59 unsafeCost += inc; 60 return *this; 54 61 } 55 62 56 inline void Cost::incPoly( int inc ) { 57 poly += inc; 63 inline Cost & Cost::incPoly( int inc ) { 64 if ( *this == infinity ) return *this; 65 polyCost += inc; 66 return *this; 58 67 } 59 68 60 inline void Cost::incSafe( int inc ) { 61 safe += inc; 69 inline Cost & Cost::incSafe( int inc ) { 70 if ( *this == infinity ) return *this; 71 safeCost += inc; 72 return *this; 73 } 74 75 inline Cost & Cost::incReference( int inc ) { 76 if ( *this == infinity ) return *this; 77 referenceCost += inc; 78 return *this; 62 79 } 63 80 64 81 inline Cost Cost::operator+( const Cost &other ) const { 65 return Cost( unsafe + other.unsafe, poly + other.poly, safe + other.safe ); 82 if ( *this == infinity || other == infinity ) return infinity; 83 return Cost( unsafeCost + other.unsafeCost, polyCost + other.polyCost, safeCost + other.safeCost, referenceCost + other.referenceCost ); 66 84 } 67 85 68 86 inline Cost Cost::operator-( const Cost &other ) const { 69 return Cost( unsafe - other.unsafe, poly - other.poly, safe - other.safe ); 87 if ( *this == infinity || other == infinity ) return infinity; 88 return Cost( unsafeCost - other.unsafeCost, polyCost - other.polyCost, safeCost - other.safeCost, referenceCost - other.referenceCost ); 70 89 } 71 90 72 91 inline Cost &Cost::operator+=( const Cost &other ) { 73 unsafe += other.unsafe; 74 poly += other.poly; 75 safe += other.safe; 92 if ( *this == infinity ) return *this; 93 if ( other == infinity ) { 94 *this = infinity; 95 return *this; 96 } 97 unsafeCost += other.unsafeCost; 98 polyCost += other.polyCost; 99 safeCost += other.safeCost; 100 referenceCost += other.referenceCost; 76 101 return *this; 77 102 } 78 103 79 104 inline bool Cost::operator<( const Cost &other ) const { 80 if ( *this == infinity ) return false; 81 if ( other == infinity ) return true; 82 if ( unsafe > other.unsafe ) { 105 if ( *this == infinity ) return false; 106 if ( other == infinity ) return true; 107 108 if ( unsafeCost > other.unsafeCost ) { 83 109 return false; 84 } else if ( unsafe < other.unsafe) {110 } else if ( unsafeCost < other.unsafeCost ) { 85 111 return true; 86 } else if ( poly > other.poly) {112 } else if ( polyCost > other.polyCost ) { 87 113 return false; 88 } else if ( poly < other.poly) {114 } else if ( polyCost < other.polyCost ) { 89 115 return true; 90 } else if ( safe > other.safe) {116 } else if ( safeCost > other.safeCost ) { 91 117 return false; 92 } else if ( safe < other.safe) {118 } else if ( safeCost < other.safeCost ) { 93 119 return true; 94 } else{120 } else if ( referenceCost > other.referenceCost ) { 95 121 return false; 96 } // if 122 } else if ( referenceCost < other.referenceCost ) { 123 return true; 124 } else { 125 return false; 126 } // if 97 127 } 98 128 99 129 inline bool Cost::operator==( const Cost &other ) const { 100 return unsafe == other.unsafe 101 && poly == other.poly 102 && safe == other.safe; 130 return unsafeCost == other.unsafeCost 131 && polyCost == other.polyCost 132 && safeCost == other.safeCost 133 && referenceCost == other.referenceCost; 103 134 } 104 135 … … 108 139 109 140 inline std::ostream &operator<<( std::ostream &os, const Cost &cost ) { 110 os << "( " << cost.unsafe << ", " << cost.poly << ", " << cost.safe<< " )";141 os << "( " << cost.unsafeCost << ", " << cost.polyCost << ", " << cost.safeCost << ", " << cost.referenceCost << " )"; 111 142 return os; 112 143 } -
src/ResolvExpr/PtrsAssignable.cc
r9f07232 rd3e4d6c 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // PtrsAssignable.cc -- 7 // PtrsAssignable.cc -- 8 8 // 9 9 // Author : Richard C. Bilson … … 82 82 void PtrsAssignable::visit( __attribute__((unused)) UnionInstType *inst ) {} 83 83 84 void PtrsAssignable::visit( EnumInstType * inst) {85 if ( dynamic_cast< EnumInstType* >( inst ) ) {84 void PtrsAssignable::visit( EnumInstType * ) { 85 if ( dynamic_cast< EnumInstType* >( dest ) ) { 86 86 result = 1; 87 } else if ( BasicType *bt = dynamic_cast< BasicType* >( inst ) ) {87 } else if ( BasicType *bt = dynamic_cast< BasicType* >( dest ) ) { 88 88 result = bt->get_kind() == BasicType::SignedInt; 89 89 } … … 104 104 void PtrsAssignable::visit( __attribute__((unused)) ZeroType *zeroType ) {} 105 105 void PtrsAssignable::visit( __attribute__((unused)) OneType *oneType ) {} 106 106 107 107 } // namespace ResolvExpr 108 108 -
src/ResolvExpr/ResolveTypeof.cc
r9f07232 rd3e4d6c 65 65 assert( newExpr->has_result() && ! newExpr->get_result()->isVoid() ); 66 66 Type *newType = newExpr->get_result(); 67 newExpr->set_result( nullptr ); 67 68 delete typeofType; 69 delete newExpr; 68 70 return newType; 69 71 } // if -
src/ResolvExpr/Unify.cc
r9f07232 rd3e4d6c 53 53 virtual void visit(PointerType *pointerType); 54 54 virtual void visit(ArrayType *arrayType); 55 virtual void visit(ReferenceType *refType); 55 56 virtual void visit(FunctionType *functionType); 56 57 virtual void visit(StructInstType *aggregateUseType); … … 153 154 154 155 bool bindVar( TypeInstType *typeInst, Type *other, const TypeDecl::Data & data, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ) { 156 // remove references from other, so that type variables can only bind to value types 157 other = other->stripReferences(); 155 158 OpenVarSet::const_iterator tyvar = openVars.find( typeInst->get_name() ); 156 159 assert( tyvar != openVars.end() ); … … 387 390 } // if 388 391 } else { 392 common = type1->clone(); 393 common->get_qualifiers() = tq1 | tq2; 389 394 result = true; 390 395 } // if … … 436 441 markAssertions( haveAssertions, needAssertions, pointerType ); 437 442 markAssertions( haveAssertions, needAssertions, otherPointer ); 443 } // if 444 } 445 446 void Unify::visit(ReferenceType *refType) { 447 if ( ReferenceType *otherRef = dynamic_cast< ReferenceType* >( type2 ) ) { 448 result = unifyExact( refType->get_base(), otherRef->get_base(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 449 markAssertions( haveAssertions, needAssertions, refType ); 450 markAssertions( haveAssertions, needAssertions, otherRef ); 438 451 } // if 439 452 } -
src/ResolvExpr/typeops.h
r9f07232 rd3e4d6c 66 66 Cost castCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env ); 67 67 68 template< typename SrcIterator, typename DestIterator >69 Cost castCostList( SrcIterator srcBegin, SrcIterator srcEnd, DestIterator destBegin, DestIterator destEnd, const SymTab::Indexer &indexer, const TypeEnvironment &env ) {70 Cost ret;71 if ( destBegin == destEnd ) {72 if ( srcBegin == srcEnd ) {73 return Cost::zero;74 } else {75 return Cost( 0, 0, 1 );76 } // if77 } // if78 while ( srcBegin != srcEnd && destBegin != destEnd ) {79 Cost thisCost = castCost( *srcBegin++, *destBegin++, indexer, env );80 if ( thisCost == Cost::infinity ) {81 return Cost::infinity;82 } // if83 ret += thisCost;84 } // while85 if ( srcBegin == srcEnd && destBegin == destEnd ) {86 return ret;87 } else {88 return Cost::infinity;89 } // if90 }91 92 68 // in ConversionCost.cc 93 69 Cost conversionCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env ); 94 95 template< typename SrcIterator, typename DestIterator >96 Cost conversionCostList( SrcIterator srcBegin, SrcIterator srcEnd, DestIterator destBegin, DestIterator destEnd, const SymTab::Indexer &indexer, const TypeEnvironment &env ) {97 Cost ret;98 while ( srcBegin != srcEnd && destBegin != destEnd ) {99 Cost thisCost = conversionCost( *srcBegin++, *destBegin++, indexer, env );100 if ( thisCost == Cost::infinity ) {101 return Cost::infinity;102 } // if103 ret += thisCost;104 } // while105 if ( srcBegin == srcEnd && destBegin == destEnd ) {106 return ret;107 } else {108 return Cost::infinity;109 } // if110 }111 70 112 71 // in PtrsAssignable.cc
Note:
See TracChangeset
for help on using the changeset viewer.