Changeset b1e63ac5 for src/ResolvExpr
- Timestamp:
- Jul 4, 2017, 9:40:16 AM (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:
- 208e5be
- Parents:
- 9c951e3 (diff), f7cb0bc (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:
-
- 2 added
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/AlternativeFinder.cc
r9c951e3 rb1e63ac5 97 97 /// Prunes a list of alternatives down to those that have the minimum conversion cost for a given return type; skips ambiguous interpretations 98 98 template< typename InputIterator, typename OutputIterator > 99 void pruneAlternatives( InputIterator begin, InputIterator end, OutputIterator out , const SymTab::Indexer &indexer) {99 void pruneAlternatives( InputIterator begin, InputIterator end, OutputIterator out ) { 100 100 // select the alternatives that have the minimum conversion cost for a particular set of result types 101 101 std::map< std::string, PruneStruct > selected; … … 183 183 ) 184 184 AltList::iterator oldBegin = alternatives.begin(); 185 pruneAlternatives( alternatives.begin(), alternatives.end(), front_inserter( alternatives ) , indexer);185 pruneAlternatives( alternatives.begin(), alternatives.end(), front_inserter( alternatives ) ); 186 186 if ( alternatives.begin() == oldBegin ) { 187 187 std::ostringstream stream; … … 604 604 // ) 605 605 SymTab::Indexer decls( indexer ); 606 PRINT(607 std::cerr << "============= original indexer" << std::endl;608 indexer.print( std::cerr );609 std::cerr << "============= new indexer" << std::endl;610 decls.print( std::cerr );611 )606 // PRINT( 607 // std::cerr << "============= original indexer" << std::endl; 608 // indexer.print( std::cerr ); 609 // std::cerr << "============= new indexer" << std::endl; 610 // decls.print( std::cerr ); 611 // ) 612 612 addToIndexer( have, decls ); 613 613 AssertionSet newNeed; … … 627 627 TypeEnvironment resultEnv; 628 628 makeUnifiableVars( funcType, openVars, resultNeed ); 629 resultEnv.add( funcType->get_forall() ); // add all type variables as open variables now so that those not used in the parameter list are still considered open 629 630 AltList instantiatedActuals; // filled by instantiate function 630 631 if ( targetType && ! targetType->isVoid() && ! funcType->get_returnVals().empty() ) { … … 808 809 } 809 810 811 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 ) ) { 818 // expressions which may contain side effects require a single unique instance of the expression. 819 argExpr = new UniqueExpr( argExpr ); 820 } 821 std::list< Expression * > componentExprs; 822 for ( unsigned int i = 0; i < toType->size(); i++ ) { 823 // cast each component 824 TupleIndexExpr * idx = new TupleIndexExpr( argExpr->clone(), i ); 825 componentExprs.push_back( restructureCast( idx, toType->getComponent( i ) ) ); 826 } 827 delete argExpr; 828 assert( componentExprs.size() > 0 ); 829 // produce the tuple of casts 830 return new TupleExpr( componentExprs ); 831 } else { 832 // handle normally 833 return new CastExpr( argExpr, toType->clone() ); 834 } 835 } 836 810 837 void AlternativeFinder::visit( CastExpr *castExpr ) { 811 838 Type *& toType = castExpr->get_result(); … … 839 866 thisCost += Cost( 0, 0, discardedValues ); 840 867 841 Expression * argExpr = i->expr->clone(); 842 if ( argExpr->get_result()->size() > 1 && ! castExpr->get_result()->isVoid() ) { 843 // Argument expression is a tuple and the target type is not void. Cast each member of the tuple 844 // to its corresponding target type, producing the tuple of those cast expressions. If there are 845 // more components of the tuple than components in the target type, then excess components do not 846 // come out in the result expression (but UniqueExprs ensure that side effects will still be done). 847 if ( Tuples::maybeImpure( argExpr ) && ! dynamic_cast< UniqueExpr * >( argExpr ) ) { 848 // expressions which may contain side effects require a single unique instance of the expression. 849 argExpr = new UniqueExpr( argExpr ); 850 } 851 std::list< Expression * > componentExprs; 852 for ( unsigned int i = 0; i < castExpr->get_result()->size(); i++ ) { 853 // cast each component 854 TupleIndexExpr * idx = new TupleIndexExpr( argExpr->clone(), i ); 855 componentExprs.push_back( new CastExpr( idx, castExpr->get_result()->getComponent( i )->clone() ) ); 856 } 857 delete argExpr; 858 assert( componentExprs.size() > 0 ); 859 // produce the tuple of casts 860 candidates.push_back( Alternative( new TupleExpr( componentExprs ), i->env, i->cost, thisCost ) ); 861 } else { 862 // handle normally 863 candidates.push_back( Alternative( new CastExpr( argExpr->clone(), toType->clone() ), i->env, i->cost, thisCost ) ); 864 } 868 candidates.push_back( Alternative( restructureCast( i->expr->clone(), toType ), i->env, i->cost, thisCost ) ); 865 869 } // if 866 870 } // for … … 1181 1185 } 1182 1186 1187 void AlternativeFinder::visit( UntypedInitExpr *initExpr ) { 1188 // handle each option like a cast 1189 AltList candidates; 1190 PRINT( std::cerr << "untyped init expr: " << initExpr << std::endl; ) 1191 // O(N^2) checks of d-types with e-types 1192 for ( InitAlternative & initAlt : initExpr->get_initAlts() ) { 1193 Type * toType = resolveTypeof( initAlt.type, indexer ); 1194 SymTab::validateType( toType, &indexer ); 1195 adjustExprType( toType, env, indexer ); 1196 // Ideally the call to findWithAdjustment could be moved out of the loop, but unfortunately it currently has to occur inside or else 1197 // polymorphic return types are not properly bound to the initialization type, since return type variables are only open for the duration of resolving 1198 // the UntypedExpr. This is only actually an issue in initialization contexts that allow more than one possible initialization type, but it is still suboptimal. 1199 AlternativeFinder finder( indexer, env ); 1200 finder.targetType = toType; 1201 finder.findWithAdjustment( initExpr->get_expr() ); 1202 for ( Alternative & alt : finder.get_alternatives() ) { 1203 TypeEnvironment newEnv( alt.env ); 1204 AssertionSet needAssertions, haveAssertions; 1205 OpenVarSet openVars; // find things in env that don't have a "representative type" and claim those are open vars? 1206 PRINT( std::cerr << " @ " << toType << " " << initAlt.designation << std::endl; ) 1207 // It's possible that a cast can throw away some values in a multiply-valued expression. (An example is a 1208 // cast-to-void, which casts from one value to zero.) Figure out the prefix of the subexpression results 1209 // that are cast directly. The candidate is invalid if it has fewer results than there are types to cast 1210 // to. 1211 int discardedValues = alt.expr->get_result()->size() - toType->size(); 1212 if ( discardedValues < 0 ) continue; 1213 // xxx - may need to go into tuple types and extract relevant types and use unifyList. Note that currently, this does not 1214 // allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3])) 1215 // unification run for side-effects 1216 unify( toType, alt.expr->get_result(), newEnv, needAssertions, haveAssertions, openVars, indexer ); // xxx - do some inspecting on this line... why isn't result bound to initAlt.type?? 1217 1218 Cost thisCost = castCost( alt.expr->get_result(), toType, indexer, newEnv ); 1219 if ( thisCost != Cost::infinity ) { 1220 // count one safe conversion for each value that is thrown away 1221 thisCost += Cost( 0, 0, discardedValues ); 1222 candidates.push_back( Alternative( new InitExpr( restructureCast( alt.expr->clone(), toType ), initAlt.designation->clone() ), newEnv, alt.cost, thisCost ) ); 1223 } 1224 } 1225 } 1226 1227 // findMinCost selects the alternatives with the lowest "cost" members, but has the side effect of copying the 1228 // cvtCost member to the cost member (since the old cost is now irrelevant). Thus, calling findMinCost twice 1229 // selects first based on argument cost, then on conversion cost. 1230 AltList minArgCost; 1231 findMinCost( candidates.begin(), candidates.end(), std::back_inserter( minArgCost ) ); 1232 findMinCost( minArgCost.begin(), minArgCost.end(), std::back_inserter( alternatives ) ); 1233 } 1183 1234 } // namespace ResolvExpr 1184 1235 -
src/ResolvExpr/AlternativeFinder.h
r9c951e3 rb1e63ac5 73 73 virtual void visit( UniqueExpr *unqExpr ); 74 74 virtual void visit( StmtExpr *stmtExpr ); 75 virtual void visit( UntypedInitExpr *initExpr ); 75 76 /// Runs a new alternative finder on each element in [begin, end) 76 77 /// and writes each alternative finder to out. -
src/ResolvExpr/CastCost.cc
r9c951e3 rb1e63ac5 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // CastCost.cc -- 7 // CastCost.cc -- 8 8 // 9 9 // Author : Richard C. Bilson … … 26 26 public: 27 27 CastCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env ); 28 28 29 29 virtual void visit( BasicType *basicType ); 30 30 virtual void visit( PointerType *pointerType ); … … 36 36 NamedTypeDecl *namedType; 37 37 if ( env.lookup( destAsTypeInst->get_name(), eqvClass ) ) { 38 return castCost( src, eqvClass.type, indexer, env ); 38 if ( eqvClass.type ) { 39 return castCost( src, eqvClass.type, indexer, env ); 40 } else { 41 return Cost::infinity; 42 } 39 43 } else if ( ( namedType = indexer.lookupType( destAsTypeInst->get_name() ) ) ) { 40 44 TypeDecl *type = dynamic_cast< TypeDecl* >( namedType ); -
src/ResolvExpr/CommonType.cc
r9c951e3 rb1e63ac5 43 43 44 44 void getCommonWithVoidPointer( PointerType* voidPointer, PointerType* otherPointer ); 45 template< typename RefType > void handleRefType( RefType *inst, Type *other );46 45 47 46 Type *result; … … 126 125 } 127 126 128 void CommonType::visit( VoidType *voidType ) { 129 } 127 void CommonType::visit( __attribute((unused)) VoidType *voidType ) {} 130 128 131 129 void CommonType::visit( BasicType *basicType ) { … … 159 157 void CommonType::visit( PointerType *pointerType ) { 160 158 if ( PointerType *otherPointer = dynamic_cast< PointerType* >( type2 ) ) { 161 if ( widenFirst && dynamic_cast< VoidType* >( otherPointer->get_base() ) && ! isFtype(pointerType->get_base() , indexer) ) {159 if ( widenFirst && dynamic_cast< VoidType* >( otherPointer->get_base() ) && ! isFtype(pointerType->get_base()) ) { 162 160 getCommonWithVoidPointer( otherPointer, pointerType ); 163 } else if ( widenSecond && dynamic_cast< VoidType* >( pointerType->get_base() ) && ! isFtype(otherPointer->get_base() , indexer) ) {161 } else if ( widenSecond && dynamic_cast< VoidType* >( pointerType->get_base() ) && ! isFtype(otherPointer->get_base()) ) { 164 162 getCommonWithVoidPointer( pointerType, otherPointer ); 165 163 } else if ( ( pointerType->get_base()->get_qualifiers() >= otherPointer->get_base()->get_qualifiers() || widenFirst ) … … 189 187 } 190 188 191 void CommonType::visit( ArrayType *arrayType ) { 192 } 193 194 void CommonType::visit( FunctionType *functionType ) { 195 } 196 197 template< typename RefType > void CommonType::handleRefType( RefType *inst, Type *other ) { 198 } 199 200 void CommonType::visit( StructInstType *aggregateUseType ) { 201 } 202 203 void CommonType::visit( UnionInstType *aggregateUseType ) { 204 } 189 void CommonType::visit( __attribute((unused)) ArrayType *arrayType ) {} 190 void CommonType::visit( __attribute((unused)) FunctionType *functionType ) {} 191 void CommonType::visit( __attribute((unused)) StructInstType *aggregateUseType ) {} 192 void CommonType::visit( __attribute((unused)) UnionInstType *aggregateUseType ) {} 205 193 206 194 void CommonType::visit( EnumInstType *enumInstType ) { … … 214 202 } 215 203 216 void CommonType::visit( TraitInstType *aggregateUseType ) {204 void CommonType::visit( __attribute((unused)) TraitInstType *aggregateUseType ) { 217 205 } 218 206 … … 239 227 } 240 228 241 void CommonType::visit( TupleType *tupleType ) { 242 } 243 244 void CommonType::visit( VarArgsType *varArgsType ) { 245 } 229 void CommonType::visit( __attribute((unused)) TupleType *tupleType ) {} 230 void CommonType::visit( __attribute((unused)) VarArgsType *varArgsType ) {} 246 231 247 232 void CommonType::visit( ZeroType *zeroType ) { -
src/ResolvExpr/ConversionCost.cc
r9c951e3 rb1e63ac5 30 30 /// std::cout << "type inst " << destAsTypeInst->get_name(); 31 31 if ( env.lookup( destAsTypeInst->get_name(), eqvClass ) ) { 32 return conversionCost( src, eqvClass.type, indexer, env ); 32 if ( eqvClass.type ) { 33 return conversionCost( src, eqvClass.type, indexer, env ); 34 } else { 35 return Cost::infinity; 36 } 33 37 } else if ( ( namedType = indexer.lookupType( destAsTypeInst->get_name() ) ) ) { 34 38 /// std::cout << " found" << std::endl; … … 145 149 }; 146 150 147 void ConversionCost::visit( VoidType *voidType) {151 void ConversionCost::visit( __attribute((unused)) VoidType *voidType ) { 148 152 cost = Cost::infinity; 149 153 } … … 182 186 } 183 187 184 void ConversionCost::visit(ArrayType *arrayType) { 185 } 186 187 void ConversionCost::visit(FunctionType *functionType) { 188 } 188 void ConversionCost::visit(__attribute((unused)) ArrayType *arrayType) {} 189 void ConversionCost::visit(__attribute((unused)) FunctionType *functionType) {} 189 190 190 191 void ConversionCost::visit(StructInstType *inst) { … … 204 205 } 205 206 206 void ConversionCost::visit( EnumInstType *inst) {207 void ConversionCost::visit( __attribute((unused)) EnumInstType *inst ) { 207 208 static Type::Qualifiers q; 208 209 static BasicType integer( q, BasicType::SignedInt ); … … 213 214 } 214 215 215 void ConversionCost::visit( TraitInstType *inst) {216 void ConversionCost::visit( __attribute((unused)) TraitInstType *inst) { 216 217 } 217 218 … … 235 236 } 236 237 237 void ConversionCost::visit( TupleType *tupleType) {238 void ConversionCost::visit( __attribute((unused)) TupleType *tupleType) { 238 239 Cost c; 239 240 if ( TupleType *destAsTuple = dynamic_cast< TupleType* >( dest ) ) { … … 255 256 } 256 257 257 void ConversionCost::visit( VarArgsType *varArgsType) {258 void ConversionCost::visit( __attribute((unused)) VarArgsType *varArgsType) { 258 259 if ( dynamic_cast< VarArgsType* >( dest ) ) { 259 260 cost = Cost::zero; … … 261 262 } 262 263 263 void ConversionCost::visit( ZeroType *zeroType) {264 void ConversionCost::visit( __attribute((unused)) ZeroType *zeroType) { 264 265 if ( dynamic_cast< ZeroType* >( dest ) ) { 265 266 cost = Cost::zero; … … 277 278 } 278 279 279 void ConversionCost::visit( OneType *oneType) {280 void ConversionCost::visit( __attribute((unused)) OneType *oneType) { 280 281 if ( dynamic_cast< OneType* >( dest ) ) { 281 282 cost = Cost::zero; -
src/ResolvExpr/PtrsAssignable.cc
r9c951e3 rb1e63ac5 63 63 } 64 64 65 PtrsAssignable::PtrsAssignable( Type *dest, const TypeEnvironment &env ) : dest( dest ), result( 0 ), env( env ) { 66 } 65 PtrsAssignable::PtrsAssignable( Type *dest, const TypeEnvironment &env ) : dest( dest ), result( 0 ), env( env ) {} 67 66 68 void PtrsAssignable::visit( VoidType *voidType ) {67 void PtrsAssignable::visit( __attribute((unused)) VoidType *voidType ) { 69 68 if ( dynamic_cast< FunctionType* >( dest ) ) { 70 69 result = 0; … … 74 73 } 75 74 76 void PtrsAssignable::visit( BasicType *basicType ) { 77 } 78 79 void PtrsAssignable::visit( PointerType *pointerType ) { 80 } 81 82 void PtrsAssignable::visit( ArrayType *arrayType ) { 83 } 84 85 void PtrsAssignable::visit( FunctionType *functionType ) { 75 void PtrsAssignable::visit( __attribute__((unused)) BasicType *basicType ) {} 76 void PtrsAssignable::visit( __attribute__((unused)) PointerType *pointerType ) {} 77 void PtrsAssignable::visit( __attribute__((unused)) ArrayType *arrayType ) {} 78 void PtrsAssignable::visit( __attribute__((unused)) FunctionType *functionType ) { 86 79 result = -1; 87 80 } 88 81 89 void PtrsAssignable::visit( StructInstType *inst ) { 90 // I don't think we should be doing anything here, but I'm willing to admit that I might be wrong 91 } 92 93 void PtrsAssignable::visit( UnionInstType *inst ) { 94 // I don't think we should be doing anything here, but I'm willing to admit that I might be wrong 95 } 82 void PtrsAssignable::visit( __attribute__((unused)) StructInstType *inst ) {} 83 void PtrsAssignable::visit( __attribute__((unused)) UnionInstType *inst ) {} 96 84 97 85 void PtrsAssignable::visit( EnumInstType *inst ) { … … 103 91 } 104 92 105 void PtrsAssignable::visit( TraitInstType *inst ) { 106 // I definitely don't think we should be doing anything here 107 } 108 93 void PtrsAssignable::visit( __attribute__((unused)) TraitInstType *inst ) {} 109 94 void PtrsAssignable::visit( TypeInstType *inst ) { 110 95 EqvClass eqvClass; … … 116 101 } 117 102 118 void PtrsAssignable::visit( TupleType *tupleType ) { 119 /// // This code doesn't belong here, but it might be useful somewhere else 120 /// if ( TupleType *destAsTuple = dynamic_cast< TupleType* >( dest ) ) { 121 /// int ret = 0; 122 /// std::list< Type* >::const_iterator srcIt = tupleType->get_types().begin(); 123 /// std::list< Type* >::const_iterator destIt = destAsTuple->get_types().begin(); 124 /// while ( srcIt != tupleType->get_types().end() && destIt != destAsTuple->get_types().end() ) { 125 /// int assignResult = ptrsAssignable( *srcIt++, *destIt++ ); 126 /// if ( assignResult == 0 ) { 127 /// result = assignResult; 128 /// return; 129 /// } else if ( assignResult < 0 ) { 130 /// ret = -1; 131 /// } else if ( ret > 0 ) { 132 /// ret += assignResult; 133 /// } 134 /// } 135 /// if ( srcIt == tupleType->get_types().end() && destIt == destAsTuple->get_types().end() ) { 136 /// result = ret; 137 /// } else { 138 /// result = 0; 139 /// } 140 /// } 141 } 142 143 void PtrsAssignable::visit( VarArgsType *varArgsType ) { 144 } 145 146 void PtrsAssignable::visit( ZeroType *zeroType ) { 147 } 148 149 void PtrsAssignable::visit( OneType *oneType ) { 150 } 103 void PtrsAssignable::visit( __attribute__((unused)) TupleType *tupleType ) {} 104 void PtrsAssignable::visit( __attribute__((unused)) VarArgsType *varArgsType ) {} 105 void PtrsAssignable::visit( __attribute__((unused)) ZeroType *zeroType ) {} 106 void PtrsAssignable::visit( __attribute__((unused)) OneType *oneType ) {} 151 107 152 108 } // namespace ResolvExpr -
src/ResolvExpr/PtrsCastable.cc
r9c951e3 rb1e63ac5 92 92 } 93 93 94 void PtrsCastable::visit( VoidType *voidType) {94 void PtrsCastable::visit( __attribute__((unused)) VoidType *voidType) { 95 95 result = objectCast( dest, env, indexer ); 96 96 } 97 97 98 void PtrsCastable::visit( BasicType *basicType) {98 void PtrsCastable::visit( __attribute__((unused)) BasicType *basicType) { 99 99 result = objectCast( dest, env, indexer ); 100 100 } 101 101 102 void PtrsCastable::visit( PointerType *pointerType) {102 void PtrsCastable::visit( __attribute__((unused)) PointerType *pointerType) { 103 103 result = objectCast( dest, env, indexer ); 104 104 } 105 105 106 void PtrsCastable::visit( ArrayType *arrayType) {106 void PtrsCastable::visit( __attribute__((unused)) ArrayType *arrayType) { 107 107 result = objectCast( dest, env, indexer ); 108 108 } 109 109 110 void PtrsCastable::visit( FunctionType *functionType) {110 void PtrsCastable::visit( __attribute__((unused)) FunctionType *functionType) { 111 111 // result = -1; 112 112 result = functionCast( dest, env, indexer ); 113 113 } 114 114 115 void PtrsCastable::visit( StructInstType *inst) {115 void PtrsCastable::visit( __attribute__((unused)) StructInstType *inst) { 116 116 result = objectCast( dest, env, indexer ); 117 117 } 118 118 119 void PtrsCastable::visit( UnionInstType *inst) {119 void PtrsCastable::visit( __attribute__((unused)) UnionInstType *inst) { 120 120 result = objectCast( dest, env, indexer ); 121 121 } 122 122 123 void PtrsCastable::visit( EnumInstType *inst) {123 void PtrsCastable::visit( __attribute__((unused)) EnumInstType *inst) { 124 124 if ( dynamic_cast< EnumInstType* >( dest ) ) { 125 125 result = 1; … … 135 135 } 136 136 137 void PtrsCastable::visit(TraitInstType *inst) { 138 // I definitely don't think we should be doing anything here 139 } 137 void PtrsCastable::visit( __attribute__((unused)) TraitInstType *inst ) {} 140 138 141 139 void PtrsCastable::visit(TypeInstType *inst) { … … 144 142 } 145 143 146 void PtrsCastable::visit( TupleType *tupleType) {144 void PtrsCastable::visit( __attribute__((unused)) TupleType *tupleType) { 147 145 result = objectCast( dest, env, indexer ); 148 146 } 149 147 150 void PtrsCastable::visit( VarArgsType *varArgsType) {148 void PtrsCastable::visit( __attribute__((unused)) VarArgsType *varArgsType) { 151 149 result = objectCast( dest, env, indexer ); 152 150 } 153 151 154 void PtrsCastable::visit( ZeroType *zeroType) {152 void PtrsCastable::visit( __attribute__((unused)) ZeroType *zeroType) { 155 153 result = objectCast( dest, env, indexer ); 156 154 } 157 155 158 void PtrsCastable::visit( OneType *oneType) {156 void PtrsCastable::visit( __attribute__((unused)) OneType *oneType) { 159 157 result = objectCast( dest, env, indexer ); 160 158 } -
src/ResolvExpr/Resolver.cc
r9c951e3 rb1e63ac5 14 14 // 15 15 16 #include <iostream> 17 18 #include "Alternative.h" 19 #include "AlternativeFinder.h" 20 #include "CurrentObject.h" 21 #include "RenameVars.h" 16 22 #include "Resolver.h" 17 #include "AlternativeFinder.h"18 #include "Alternative.h"19 #include "RenameVars.h"20 23 #include "ResolveTypeof.h" 21 24 #include "typeops.h" 25 26 #include "SynTree/Expression.h" 27 #include "SynTree/Initializer.h" 22 28 #include "SynTree/Statement.h" 23 29 #include "SynTree/Type.h" 24 #include "SynTree/Expression.h" 25 #include "Sy nTree/Initializer.h"30 31 #include "SymTab/Autogen.h" 26 32 #include "SymTab/Indexer.h" 27 #include "SymTab/Autogen.h" 33 28 34 #include "Common/utility.h" 35 29 36 #include "InitTweak/InitTweak.h" 30 37 31 #include <iostream>32 38 using namespace std; 33 39 … … 39 45 if ( const Resolver * res = dynamic_cast< const Resolver * >( &other ) ) { 40 46 functionReturn = res->functionReturn; 41 initContext = res->initContext;47 currentObject = res->currentObject; 42 48 inEnumDecl = res->inEnumDecl; 43 49 } … … 79 85 80 86 Type * functionReturn = nullptr; 81 Type *initContext = nullptr;87 CurrentObject currentObject = nullptr; 82 88 bool inEnumDecl = false; 83 89 }; … … 124 130 } // if 125 131 #endif 126 assert ( finder.get_alternatives().size() == 1);132 assertf( finder.get_alternatives().size() == 1, "findSingleExpression: must have exactly one alternative at the end." ); 127 133 Alternative &choice = finder.get_alternatives().front(); 128 134 Expression *newExpr = choice.expr->clone(); … … 186 192 // each value of initContext is retained, so the type on the first analysis is preserved and used for selecting 187 193 // the RHS. 188 Type *temp = initContext;189 initContext = new_type;190 if ( inEnumDecl && dynamic_cast< EnumInstType * >( initContext) ) {194 ValueGuard<CurrentObject> temp( currentObject ); 195 currentObject = CurrentObject( objectDecl->get_type() ); 196 if ( inEnumDecl && dynamic_cast< EnumInstType * >( objectDecl->get_type() ) ) { 191 197 // enumerator initializers should not use the enum type to initialize, since 192 198 // the enum type is still incomplete at this point. Use signed int instead. 193 initContext = new BasicType( Type::Qualifiers(), BasicType::SignedInt);199 currentObject = CurrentObject( new BasicType( Type::Qualifiers(), BasicType::SignedInt ) ); 194 200 } 195 201 Parent::visit( objectDecl ); 196 if ( inEnumDecl && dynamic_cast< EnumInstType * >( initContext) ) {202 if ( inEnumDecl && dynamic_cast< EnumInstType * >( objectDecl->get_type() ) ) { 197 203 // delete newly created signed int type 198 delete initContext; 199 } 200 initContext = temp; 204 // delete currentObject.getType(); 205 } 201 206 } 202 207 … … 315 320 316 321 void Resolver::visit( SwitchStmt *switchStmt ) { 317 ValueGuard< Type * > oldInitContext( initContext );322 ValueGuard< CurrentObject > oldCurrentObject( currentObject ); 318 323 Expression *newExpr; 319 324 newExpr = findIntegralExpression( switchStmt->get_condition(), *this ); … … 321 326 switchStmt->set_condition( newExpr ); 322 327 323 initContext = newExpr->get_result();328 currentObject = CurrentObject( newExpr->get_result() ); 324 329 Parent::visit( switchStmt ); 325 330 } … … 327 332 void Resolver::visit( CaseStmt *caseStmt ) { 328 333 if ( caseStmt->get_condition() ) { 329 assert( initContext ); 330 CastExpr * castExpr = new CastExpr( caseStmt->get_condition(), initContext->clone() ); 334 std::list< InitAlternative > initAlts = currentObject.getOptions(); 335 assertf( initAlts.size() == 1, "SwitchStmt did not correctly resolve an integral expression." ); 336 CastExpr * castExpr = new CastExpr( caseStmt->get_condition(), initAlts.front().type->clone() ); 331 337 Expression * newExpr = findSingleExpression( castExpr, *this ); 332 338 castExpr = safe_dynamic_cast< CastExpr * >( newExpr ); … … 370 376 371 377 void Resolver::visit( SingleInit *singleInit ) { 372 if ( singleInit->get_value() ) { 373 // // find all the d's 374 // std::list<Expression *> &designators = singleInit->get_designators(); 375 // std::list<Type *> types1{ initContext }, types2; 376 // for ( Expression * expr: designators ) { 377 // cerr << expr << endl; 378 // if ( NameExpr * nexpr = dynamic_cast<NameExpr *>( expr ) ) { 379 // for ( Type * type: types1 ) { 380 // cerr << type << endl; 381 // ReferenceToType * fred = dynamic_cast<ReferenceToType *>(type); 382 // std::list<Declaration *> members; 383 // if ( fred ) { 384 // fred->lookup( nexpr->get_name(), members ); // concatenate identical field name 385 // for ( Declaration * mem: members ) { 386 // if ( DeclarationWithType * dwt = dynamic_cast<DeclarationWithType *>(mem) ) { 387 // types2.push_back( dwt->get_type() ); 388 // } // if 389 // } // for 390 // } // if 391 // } // for 392 // types1 = types2; 393 // types2.clear(); 394 // } // if 395 // } // for 396 // // for ( Type * type: types1 ) { 397 // // cerr << type << endl; 398 // // } // for 399 400 // // O(N^2) checks of d-types with f-types 401 // // find the minimum cost 402 CastExpr *castExpr = new CastExpr( singleInit->get_value(), initContext->clone() ); 403 Expression *newExpr = findSingleExpression( castExpr, *this ); 404 delete castExpr; 405 singleInit->set_value( newExpr ); 406 407 // check if initializing type is char[] 408 if ( ArrayType * at = dynamic_cast< ArrayType * >( initContext ) ) { 409 if ( isCharType( at->get_base() ) ) { 410 // check if the resolved type is char * 411 if ( PointerType * pt = dynamic_cast< PointerType *>( newExpr->get_result() ) ) { 412 if ( isCharType( pt->get_base() ) ) { 413 // strip cast if we're initializing a char[] with a char *, e.g. char x[] = "hello"; 414 CastExpr *ce = dynamic_cast< CastExpr * >( newExpr ); 415 singleInit->set_value( ce->get_arg() ); 416 ce->set_arg( NULL ); 417 delete ce; 418 } 378 // resolve initialization using the possibilities as determined by the currentObject cursor 379 UntypedInitExpr * untyped = new UntypedInitExpr( singleInit->get_value(), currentObject.getOptions() ); 380 Expression * newExpr = findSingleExpression( untyped, *this ); 381 InitExpr * initExpr = safe_dynamic_cast< InitExpr * >( newExpr ); 382 383 // move cursor to the object that is actually initialized 384 currentObject.setNext( initExpr->get_designation() ); 385 386 // discard InitExpr wrapper and retain relevant pieces 387 newExpr = initExpr->get_expr(); 388 newExpr->set_env( initExpr->get_env() ); 389 initExpr->set_expr( nullptr ); 390 initExpr->set_env( nullptr ); 391 delete initExpr; 392 393 // get the actual object's type (may not exactly match what comes back from the resolver due to conversions) 394 Type * initContext = currentObject.getCurrentType(); 395 396 // check if actual object's type is char[] 397 if ( ArrayType * at = dynamic_cast< ArrayType * >( initContext ) ) { 398 if ( isCharType( at->get_base() ) ) { 399 // check if the resolved type is char * 400 if ( PointerType * pt = dynamic_cast< PointerType *>( newExpr->get_result() ) ) { 401 if ( isCharType( pt->get_base() ) ) { 402 // strip cast if we're initializing a char[] with a char *, e.g. char x[] = "hello"; 403 CastExpr *ce = safe_dynamic_cast< CastExpr * >( newExpr ); 404 newExpr = ce->get_arg(); 405 ce->set_arg( nullptr ); 406 delete ce; 419 407 } 420 408 } 421 409 } 422 } // if 423 } 424 425 template< typename AggrInst > 426 TypeSubstitution makeGenericSubstitutuion( AggrInst * inst ) { 427 assert( inst ); 428 assert( inst->get_baseParameters() ); 429 std::list< TypeDecl * > baseParams = *inst->get_baseParameters(); 430 std::list< Expression * > typeSubs = inst->get_parameters(); 431 TypeSubstitution subs( baseParams.begin(), baseParams.end(), typeSubs.begin() ); 432 return subs; 433 } 434 435 ReferenceToType * isStructOrUnion( Type * type ) { 436 if ( StructInstType * sit = dynamic_cast< StructInstType * >( type ) ) { 437 return sit; 438 } else if ( UnionInstType * uit = dynamic_cast< UnionInstType * >( type ) ) { 439 return uit; 440 } 441 return nullptr; 442 } 443 444 void Resolver::resolveSingleAggrInit( Declaration * dcl, InitIterator & init, InitIterator & initEnd, TypeSubstitution sub ) { 445 DeclarationWithType * dt = dynamic_cast< DeclarationWithType * >( dcl ); 446 assert( dt ); 447 // need to substitute for generic types, so that casts are to concrete types 448 initContext = dt->get_type()->clone(); 449 sub.apply( initContext ); 450 451 try { 452 if ( init == initEnd ) return; // stop when there are no more initializers 453 (*init)->accept( *this ); 454 ++init; // made it past an initializer 455 } catch( SemanticError & ) { 456 // need to delve deeper, if you can 457 if ( ReferenceToType * type = isStructOrUnion( initContext ) ) { 458 resolveAggrInit( type, init, initEnd ); 459 } else { 460 // member is not an aggregate type, so can't go any deeper 461 462 // might need to rethink what is being thrown 463 throw; 464 } // if 465 } 466 } 467 468 void Resolver::resolveAggrInit( ReferenceToType * inst, InitIterator & init, InitIterator & initEnd ) { 469 if ( StructInstType * sit = dynamic_cast< StructInstType * >( inst ) ) { 470 TypeSubstitution sub = makeGenericSubstitutuion( sit ); 471 StructDecl * st = sit->get_baseStruct(); 472 if(st->get_members().empty()) return; 473 // want to resolve each initializer to the members of the struct, 474 // but if there are more initializers than members we should stop 475 list< Declaration * >::iterator it = st->get_members().begin(); 476 for ( ; it != st->get_members().end(); ++it) { 477 resolveSingleAggrInit( *it, init, initEnd, sub ); 478 } 479 } else if ( UnionInstType * uit = dynamic_cast< UnionInstType * >( inst ) ) { 480 TypeSubstitution sub = makeGenericSubstitutuion( uit ); 481 UnionDecl * un = uit->get_baseUnion(); 482 if(un->get_members().empty()) return; 483 // only resolve to the first member of a union 484 resolveSingleAggrInit( *un->get_members().begin(), init, initEnd, sub ); 485 } // if 410 } 411 412 // set initializer expr to resolved express 413 singleInit->set_value( newExpr ); 414 415 // move cursor to next object in preparation for next initializer 416 currentObject.increment(); 486 417 } 487 418 488 419 void Resolver::visit( ListInit * listInit ) { 489 InitIterator iter = listInit->begin(); 490 InitIterator end = listInit->end(); 491 492 if ( ArrayType * at = dynamic_cast< ArrayType * >( initContext ) ) { 493 // resolve each member to the base type of the array 494 for ( ; iter != end; ++iter ) { 495 initContext = at->get_base(); 496 (*iter)->accept( *this ); 497 } // for 498 } else if ( TupleType * tt = dynamic_cast< TupleType * > ( initContext ) ) { 499 for ( Type * t : *tt ) { 500 if ( iter == end ) break; 501 initContext = t; 502 (*iter++)->accept( *this ); 503 } 504 } else if ( ReferenceToType * type = isStructOrUnion( initContext ) ) { 505 resolveAggrInit( type, iter, end ); 506 } else if ( TypeInstType * tt = dynamic_cast< TypeInstType * >( initContext ) ) { 507 Type * base = tt->get_baseType()->get_base(); 508 if ( base ) { 509 // know the implementation type, so try using that as the initContext 510 initContext = base; 511 visit( listInit ); 512 } else { 513 // missing implementation type -- might be an unknown type variable, so try proceeding with the current init context 514 Parent::visit( listInit ); 515 } 516 } else { 517 assert( dynamic_cast< BasicType * >( initContext ) || dynamic_cast< PointerType * >( initContext ) 518 || dynamic_cast< ZeroType * >( initContext ) || dynamic_cast< OneType * >( initContext ) || dynamic_cast < EnumInstType * > ( initContext ) ); 519 // basic types are handled here 520 Parent::visit( listInit ); 521 } 522 523 #if 0 524 if ( ArrayType *at = dynamic_cast<ArrayType*>(initContext) ) { 525 std::list<Initializer *>::iterator iter( listInit->begin_initializers() ); 526 for ( ; iter != listInit->end_initializers(); ++iter ) { 527 initContext = at->get_base(); 528 (*iter)->accept( *this ); 529 } // for 530 } else if ( StructInstType *st = dynamic_cast<StructInstType*>(initContext) ) { 531 StructDecl *baseStruct = st->get_baseStruct(); 532 std::list<Declaration *>::iterator iter1( baseStruct->get_members().begin() ); 533 std::list<Initializer *>::iterator iter2( listInit->begin_initializers() ); 534 for ( ; iter1 != baseStruct->get_members().end() && iter2 != listInit->end_initializers(); ++iter2 ) { 535 if ( (*iter2)->get_designators().empty() ) { 536 DeclarationWithType *dt = dynamic_cast<DeclarationWithType *>( *iter1 ); 537 initContext = dt->get_type(); 538 (*iter2)->accept( *this ); 539 ++iter1; 540 } else { 541 StructDecl *st = baseStruct; 542 iter1 = st->get_members().begin(); 543 std::list<Expression *>::iterator iter3( (*iter2)->get_designators().begin() ); 544 for ( ; iter3 != (*iter2)->get_designators().end(); ++iter3 ) { 545 NameExpr *key = dynamic_cast<NameExpr *>( *iter3 ); 546 assert( key ); 547 for ( ; iter1 != st->get_members().end(); ++iter1 ) { 548 if ( key->get_name() == (*iter1)->get_name() ) { 549 (*iter1)->print( cout ); 550 cout << key->get_name() << endl; 551 ObjectDecl *fred = dynamic_cast<ObjectDecl *>( *iter1 ); 552 assert( fred ); 553 StructInstType *mary = dynamic_cast<StructInstType*>( fred->get_type() ); 554 assert( mary ); 555 st = mary->get_baseStruct(); 556 iter1 = st->get_members().begin(); 557 break; 558 } // if 559 } // for 560 } // for 561 ObjectDecl *fred = dynamic_cast<ObjectDecl *>( *iter1 ); 562 assert( fred ); 563 initContext = fred->get_type(); 564 (*listInit->begin_initializers())->accept( *this ); 565 } // if 566 } // for 567 } else if ( UnionInstType *st = dynamic_cast<UnionInstType*>(initContext) ) { 568 DeclarationWithType *dt = dynamic_cast<DeclarationWithType *>( *st->get_baseUnion()->get_members().begin() ); 569 initContext = dt->get_type(); 570 (*listInit->begin_initializers())->accept( *this ); 571 } // if 572 #endif 420 // move cursor into brace-enclosed initializer-list 421 currentObject.enterListInit(); 422 // xxx - fix this so that the list isn't copied, iterator should be used to change current element 423 std::list<Designation *> newDesignations; 424 for ( auto p : group_iterate(listInit->get_designations(), listInit->get_initializers()) ) { 425 // iterate designations and initializers in pairs, moving the cursor to the current designated object and resolving 426 // the initializer against that object. 427 Designation * des = std::get<0>(p); 428 Initializer * init = std::get<1>(p); 429 newDesignations.push_back( currentObject.findNext( des ) ); 430 init->accept( *this ); 431 } 432 // set the set of 'resolved' designations and leave the brace-enclosed initializer-list 433 listInit->get_designations() = newDesignations; // xxx - memory management 434 currentObject.exitListInit(); 435 436 // xxx - this part has not be folded into CurrentObject yet 437 // } else if ( TypeInstType * tt = dynamic_cast< TypeInstType * >( initContext ) ) { 438 // Type * base = tt->get_baseType()->get_base(); 439 // if ( base ) { 440 // // know the implementation type, so try using that as the initContext 441 // ObjectDecl tmpObj( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, base->clone(), nullptr ); 442 // currentObject = &tmpObj; 443 // visit( listInit ); 444 // } else { 445 // // missing implementation type -- might be an unknown type variable, so try proceeding with the current init context 446 // Parent::visit( listInit ); 447 // } 448 // } else { 573 449 } 574 450 -
src/ResolvExpr/TypeMap.h
r9c951e3 rb1e63ac5 110 110 } 111 111 112 virtual void visit( VoidType *voidType ) {112 virtual void visit( __attribute__((unused)) VoidType *voidType ) { 113 113 findAndReplace( typeMap.voidValue ); 114 114 } … … 138 138 } 139 139 140 virtual void visit( FunctionType *functionType ) {140 virtual void visit( __attribute__((unused)) FunctionType *functionType ) { 141 141 findAndReplace( typeMap.functionPointerValue ); 142 142 } -
src/ResolvExpr/Unify.cc
r9c951e3 rb1e63ac5 115 115 } 116 116 117 bool isFtype( Type *type , const SymTab::Indexer &indexer) {117 bool isFtype( Type *type ) { 118 118 if ( dynamic_cast< FunctionType* >( type ) ) { 119 119 return true; … … 124 124 } 125 125 126 bool tyVarCompatible( const TypeDecl::Data & data, Type *type , const SymTab::Indexer &indexer) {126 bool tyVarCompatible( const TypeDecl::Data & data, Type *type ) { 127 127 switch ( data.kind ) { 128 128 case TypeDecl::Any: … … 132 132 // type must also be complete 133 133 // xxx - should this also check that type is not a tuple type and that it's not a ttype? 134 return ! isFtype( type , indexer) && (! data.isComplete || type->isComplete() );134 return ! isFtype( type ) && (! data.isComplete || type->isComplete() ); 135 135 case TypeDecl::Ftype: 136 return isFtype( type , indexer);136 return isFtype( type ); 137 137 case TypeDecl::Ttype: 138 138 // ttype unifies with any tuple type … … 145 145 OpenVarSet::const_iterator tyvar = openVars.find( typeInst->get_name() ); 146 146 assert( tyvar != openVars.end() ); 147 if ( ! tyVarCompatible( tyvar->second, other , indexer) ) {147 if ( ! tyVarCompatible( tyvar->second, other ) ) { 148 148 return false; 149 149 } // if … … 345 345 std::cerr << "unifyInexact type 1 is "; 346 346 type1->print( std::cerr ); 347 std::cerr << " type 2 is ";347 std::cerr << " type 2 is "; 348 348 type2->print( std::cerr ); 349 349 std::cerr << std::endl; … … 389 389 } 390 390 391 void Unify::visit( VoidType *voidType) {391 void Unify::visit( __attribute__((unused)) VoidType *voidType) { 392 392 result = dynamic_cast< VoidType* >( type2 ); 393 393 } … … 615 615 } else if ( tupleParam ) { 616 616 // bundle other parameters into tuple to match 617 TupleType* binder = new TupleType{ paramTy->get_qualifiers() };617 std::list< Type * > binderTypes; 618 618 619 619 do { 620 binder ->get_types().push_back( otherParam->get_type()->clone() );620 binderTypes.push_back( otherParam->get_type()->clone() ); 621 621 ++jt; 622 622 … … 627 627 } while (true); 628 628 629 otherParamTy = binder;629 otherParamTy = new TupleType{ paramTy->get_qualifiers(), binderTypes }; 630 630 ++it; // skip ttype parameter for break 631 631 } else if ( otherTupleParam ) { 632 632 // bundle parameters into tuple to match other 633 TupleType* binder = new TupleType{ otherParamTy->get_qualifiers() };633 std::list< Type * > binderTypes; 634 634 635 635 do { 636 binder ->get_types().push_back( param->get_type()->clone() );636 binderTypes.push_back( param->get_type()->clone() ); 637 637 ++it; 638 638 … … 643 643 } while (true); 644 644 645 paramTy = binder;645 paramTy = new TupleType{ otherParamTy->get_qualifiers(), binderTypes }; 646 646 ++jt; // skip ttype parameter for break 647 647 } … … 692 692 693 693 template< typename Iterator1, typename Iterator2 > 694 bool unifyList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode,const SymTab::Indexer &indexer ) {694 bool unifyList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, const SymTab::Indexer &indexer ) { 695 695 auto get_type = [](Type * t) { return t; }; 696 696 for ( ; list1Begin != list1End && list2Begin != list2End; ++list1Begin, ++list2Begin ) { … … 742 742 flatten( flat2.get(), back_inserter( types2 ) ); 743 743 744 result = unifyList( types1.begin(), types1.end(), types2.begin(), types2.end(), env, needAssertions, haveAssertions, openVars, widenMode,indexer );745 } // if 746 } 747 748 void Unify::visit( VarArgsType *varArgsType) {744 result = unifyList( types1.begin(), types1.end(), types2.begin(), types2.end(), env, needAssertions, haveAssertions, openVars, indexer ); 745 } // if 746 } 747 748 void Unify::visit( __attribute__((unused)) VarArgsType *varArgsType ) { 749 749 result = dynamic_cast< VarArgsType* >( type2 ); 750 750 } 751 751 752 void Unify::visit( ZeroType *zeroType) {752 void Unify::visit( __attribute__((unused)) ZeroType *zeroType ) { 753 753 result = dynamic_cast< ZeroType* >( type2 ); 754 754 } 755 755 756 void Unify::visit( OneType *oneType) {756 void Unify::visit( __attribute__((unused)) OneType *oneType ) { 757 757 result = dynamic_cast< OneType* >( type2 ); 758 758 } … … 765 765 return function->get_returnVals().front()->get_type()->clone(); 766 766 } else { 767 TupleType * tupleType = new TupleType( Type::Qualifiers() );767 std::list< Type * > types; 768 768 for ( DeclarationWithType * decl : function->get_returnVals() ) { 769 t upleType->get_types().push_back( decl->get_type()->clone() );769 types.push_back( decl->get_type()->clone() ); 770 770 } // for 771 return tupleType;771 return new TupleType( Type::Qualifiers(), types ); 772 772 } 773 773 } -
src/ResolvExpr/module.mk
r9c951e3 rb1e63ac5 6 6 ## file "LICENCE" distributed with Cforall. 7 7 ## 8 ## module.mk -- 8 ## module.mk -- 9 9 ## 10 10 ## Author : Richard C. Bilson … … 31 31 ResolvExpr/PolyCost.cc \ 32 32 ResolvExpr/Occurs.cc \ 33 ResolvExpr/TypeEnvironment.cc 33 ResolvExpr/TypeEnvironment.cc \ 34 ResolvExpr/CurrentObject.cc -
src/ResolvExpr/typeops.h
r9c951e3 rb1e63ac5 118 118 119 119 // in Unify.cc 120 bool isFtype( Type *type , const SymTab::Indexer &indexer);120 bool isFtype( Type *type ); 121 121 bool typesCompatible( Type *, Type *, const SymTab::Indexer &indexer, const TypeEnvironment &env ); 122 122 bool typesCompatibleIgnoreQualifiers( Type *, Type *, const SymTab::Indexer &indexer, const TypeEnvironment &env ); … … 130 130 TypeEnvironment env; 131 131 return typesCompatibleIgnoreQualifiers( t1, t2, indexer, env ); 132 }133 134 template< typename Container1, typename Container2 >135 bool typesCompatibleList( Container1 &c1, Container2 &c2, const SymTab::Indexer &indexer, const TypeEnvironment &env ) {136 typename Container1::iterator i1 = c1.begin();137 typename Container2::iterator i2 = c2.begin();138 for ( ; i1 != c1.end() && i2 != c2.end(); ++i1, ++i2 ) {139 if ( ! typesCompatible( *i1, *i2, indexer ) ) {140 return false;141 } // if142 }143 return ( i1 == c1.end() ) && ( i2 == c2.end() );144 132 } 145 133
Note: See TracChangeset
for help on using the changeset viewer.