Changes in src/GenPoly/Box.cc [bd85400:4067aa8]
- File:
-
- 1 edited
-
src/GenPoly/Box.cc (modified) (23 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/GenPoly/Box.cc
rbd85400 r4067aa8 25 25 #include "PolyMutator.h" 26 26 #include "FindFunction.h" 27 #include "ScopedMap.h"28 27 #include "ScrubTyVars.h" 29 28 … … 38 37 39 38 #include "ResolvExpr/TypeEnvironment.h" 39 #include "ResolvExpr/TypeMap.h" 40 #include "ResolvExpr/typeops.h" 40 41 41 42 #include "SymTab/Mangler.h" … … 73 74 /// Makes a new temporary array holding the offsets of the fields of `type`, and returns a new variable expression referencing it 74 75 Expression *makeOffsetArray( StructInstType *type ); 76 /// Pass the extra type parameters from polymorphic generic arguments or return types into a function application 77 void passArgTypeVars( ApplicationExpr *appExpr, Type *parmType, Type *argBaseType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars, std::set< std::string > &seenTypes ); 75 78 /// passes extra type parameters into a polymorphic function application 76 void passTypeVars( ApplicationExpr *appExpr, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars );79 void passTypeVars( ApplicationExpr *appExpr, ReferenceToType *polyRetType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars ); 77 80 /// wraps a function application with a new temporary for the out-parameter return value 78 81 Expression *addRetParam( ApplicationExpr *appExpr, FunctionType *function, Type *retType, std::list< Expression *>::iterator &arg ); … … 99 102 typedef std::map< std::string, DeclarationWithType *> AdapterMap; 100 103 std::map< std::string, DeclarationWithType *> assignOps; 101 ScopedMap< std::string, DeclarationWithType *> scopedAssignOps;104 ResolvExpr::TypeMap< DeclarationWithType > scopedAssignOps; 102 105 std::stack< AdapterMap > adapters; 103 106 DeclarationWithType *retval; … … 246 249 } 247 250 248 /// returns T if the given declaration is: (*?=?)(T *, T) for some T (return not checked, but maybe should be), NULL otherwise249 ReferenceToType *isAssignment( DeclarationWithType *decl ) {251 /// Returns T if the given declaration is (*?=?)(T *, T) for some TypeInstType T (return not checked, but maybe should be), NULL otherwise 252 TypeInstType *isTypeInstAssignment( DeclarationWithType *decl ) { 250 253 if ( decl->get_name() == "?=?" ) { 251 254 if ( FunctionType *funType = getFunctionType( decl->get_type() ) ) { 252 255 if ( funType->get_parameters().size() == 2 ) { 253 256 if ( PointerType *pointer = dynamic_cast< PointerType *>( funType->get_parameters().front()->get_type() ) ) { 254 if ( ReferenceToType *refType = dynamic_cast< ReferenceToType *>( pointer->get_base() ) ) {255 if ( ReferenceToType *refType2 = dynamic_cast< ReferenceToType *>( funType->get_parameters().back()->get_type() ) ) {257 if ( TypeInstType *refType = dynamic_cast< TypeInstType *>( pointer->get_base() ) ) { 258 if ( TypeInstType *refType2 = dynamic_cast< TypeInstType *>( funType->get_parameters().back()->get_type() ) ) { 256 259 if ( refType->get_name() == refType2->get_name() ) { 257 260 return refType; … … 265 268 return 0; 266 269 } 270 271 /// returns T if the given declaration is: (*?=?)(T *, T) for some type T (return not checked, but maybe should be), NULL otherwise 272 /// Only picks assignments where neither parameter is cv-qualified 273 Type *isAssignment( DeclarationWithType *decl ) { 274 if ( decl->get_name() == "?=?" ) { 275 if ( FunctionType *funType = getFunctionType( decl->get_type() ) ) { 276 if ( funType->get_parameters().size() == 2 ) { 277 Type::Qualifiers defaultQualifiers; 278 Type *paramType1 = funType->get_parameters().front()->get_type(); 279 if ( paramType1->get_qualifiers() != defaultQualifiers ) return 0; 280 Type *paramType2 = funType->get_parameters().back()->get_type(); 281 if ( paramType2->get_qualifiers() != defaultQualifiers ) return 0; 282 283 if ( PointerType *pointerType = dynamic_cast< PointerType* >( paramType1 ) ) { 284 Type *baseType1 = pointerType->get_base(); 285 if ( baseType1->get_qualifiers() != defaultQualifiers ) return 0; 286 SymTab::Indexer dummy; 287 if ( ResolvExpr::typesCompatible( baseType1, paramType2, dummy ) ) { 288 return baseType1; 289 } // if 290 } // if 291 } // if 292 } // if 293 } // if 294 return 0; 295 } 267 296 268 297 void Pass1::findAssignOps( const std::list< TypeDecl *> &forall ) { … … 272 301 for ( std::list< DeclarationWithType *>::const_iterator assert = (*i)->get_assertions().begin(); assert != (*i)->get_assertions().end(); ++assert ) { 273 302 std::string typeName; 274 if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( isAssignment( *assert )) ) {303 if ( TypeInstType *typeInst = isTypeInstAssignment( *assert ) ) { 275 304 assignOps[ typeInst->get_name() ] = *assert; 276 305 } // if … … 281 310 DeclarationWithType *Pass1::mutate( FunctionDecl *functionDecl ) { 282 311 // if this is a polymorphic assignment function, put it in the map for this scope 283 if ( ReferenceToType *refType = isAssignment( functionDecl ) ) {284 if ( ! dynamic_cast< TypeInstType* >( refType ) ) {285 scopedAssignOps.insert( refType->get_name(), functionDecl );312 if ( Type *assignedType = isAssignment( functionDecl ) ) { 313 if ( ! dynamic_cast< TypeInstType* >( assignedType ) ) { 314 scopedAssignOps.insert( assignedType, functionDecl ); 286 315 } 287 316 } … … 398 427 } 399 428 400 void Pass1::passTypeVars( ApplicationExpr *appExpr, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars ) { 429 void Pass1::passArgTypeVars( ApplicationExpr *appExpr, Type *parmType, Type *argBaseType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars, std::set< std::string > &seenTypes ) { 430 Type *polyBase = hasPolyBase( parmType, exprTyVars ); 431 if ( polyBase && ! dynamic_cast< TypeInstType* >( polyBase ) ) { 432 std::string sizeName = sizeofName( polyBase ); 433 if ( seenTypes.count( sizeName ) ) return; 434 435 arg = appExpr->get_args().insert( arg, new SizeofExpr( argBaseType->clone() ) ); 436 arg++; 437 arg = appExpr->get_args().insert( arg, new AlignofExpr( argBaseType->clone() ) ); 438 arg++; 439 if ( dynamic_cast< StructInstType* >( polyBase ) ) { 440 if ( StructInstType *argBaseStructType = dynamic_cast< StructInstType* >( argBaseType ) ) { 441 arg = appExpr->get_args().insert( arg, makeOffsetArray( argBaseStructType ) ); 442 arg++; 443 } else { 444 throw SemanticError( "Cannot pass non-struct type for generic struct" ); 445 } 446 } 447 448 seenTypes.insert( sizeName ); 449 } 450 } 451 452 void Pass1::passTypeVars( ApplicationExpr *appExpr, ReferenceToType *polyRetType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars ) { 401 453 // pass size/align for type variables 402 454 for ( TyVarMap::const_iterator tyParm = exprTyVars.begin(); tyParm != exprTyVars.end(); ++tyParm ) { … … 424 476 std::list< Expression* >::const_iterator fnArg = arg; 425 477 std::set< std::string > seenTypes; //< names for generic types we've seen 478 479 // a polymorphic return type may need to be added to the argument list 480 if ( polyRetType ) { 481 Type *concRetType = replaceWithConcrete( appExpr, polyRetType ); 482 passArgTypeVars( appExpr, polyRetType, concRetType, arg, exprTyVars, seenTypes ); 483 } 484 485 // add type information args for presently unseen types in parameter list 426 486 for ( ; fnParm != funcType->get_parameters().end() && fnArg != appExpr->get_args().end(); ++fnParm, ++fnArg ) { 427 Type *polyBase = hasPolyBase( (*fnParm)->get_type(), exprTyVars ); 428 if ( polyBase && ! dynamic_cast< TypeInstType* >( polyBase ) ) { 429 std::string sizeName = sizeofName( polyBase ); 430 if ( seenTypes.count( sizeName ) ) continue; 431 432 VariableExpr *fnArgBase = getBaseVar( *fnArg ); 433 assert( fnArgBase && ! fnArgBase->get_results().empty() ); 434 Type *argBaseType = fnArgBase->get_results().front(); 435 arg = appExpr->get_args().insert( arg, new SizeofExpr( argBaseType->clone() ) ); 436 arg++; 437 arg = appExpr->get_args().insert( arg, new AlignofExpr( argBaseType->clone() ) ); 438 arg++; 439 if ( dynamic_cast< StructInstType* >( polyBase ) ) { 440 if ( StructInstType *argBaseStructType = dynamic_cast< StructInstType* >( argBaseType ) ) { 441 arg = appExpr->get_args().insert( arg, makeOffsetArray( argBaseStructType ) ); 442 arg++; 443 } else { 444 throw SemanticError( "Cannot pass non-struct type for generic struct" ); 445 } 446 } 447 448 seenTypes.insert( sizeName ); 449 } 487 VariableExpr *fnArgBase = getBaseVar( *fnArg ); 488 if ( ! fnArgBase || fnArgBase->get_results().empty() ) continue; 489 passArgTypeVars( appExpr, (*fnParm)->get_type(), fnArgBase->get_results().front(), arg, exprTyVars, seenTypes ); 450 490 } 451 491 } … … 470 510 ObjectDecl *newObj = makeTemporary( retType->clone() ); 471 511 Expression *paramExpr = new VariableExpr( newObj ); 472 // If the type of the temporary is not polymorphic, box temporary by taking its address; otherwise the 473 // temporary is already boxed and can be used directly. 512 513 // If the type of the temporary is not polymorphic, box temporary by taking its address; 514 // otherwise the temporary is already boxed and can be used directly. 474 515 if ( ! isPolyType( newObj->get_type(), scopeTyVars, env ) ) { 475 516 paramExpr = new AddressExpr( paramExpr ); … … 520 561 assert( env ); 521 562 Type *concrete = replaceWithConcrete( appExpr, polyType ); 563 // add out-parameter for return value 522 564 return addRetParam( appExpr, function, concrete, arg ); 523 565 } … … 542 584 assert( ! arg->get_results().empty() ); 543 585 if ( isPolyType( param, exprTyVars ) ) { 544 if ( dynamic_cast< TypeInstType *>( arg->get_results().front() ) ) {545 // if the argument's type is a type parameter, we don't need to box again!586 if ( isPolyType( arg->get_results().front() ) ) { 587 // if the argument's type is polymorphic, we don't need to box again! 546 588 return; 547 589 } else if ( arg->get_results().front()->get_isLvalue() ) { … … 622 664 assert( arg ); 623 665 if ( isPolyType( realParam->get_type(), tyVars ) ) { 624 if ( dynamic_cast<TypeInstType *>(arg->get_type()) == NULL) {666 if ( ! isPolyType( arg->get_type() ) ) { 625 667 UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) ); 626 668 deref->get_args().push_back( new CastExpr( new VariableExpr( param ), new PointerType( Type::Qualifiers(), arg->get_type()->clone() ) ) ); … … 917 959 std::list< Expression *>::iterator paramBegin = appExpr->get_args().begin(); 918 960 919 if ( ReferenceToType *polyType = isPolyRet( function ) ) { 920 ret = addPolyRetParam( appExpr, function, polyType, arg ); 961 TyVarMap exprTyVars; 962 makeTyVarMap( function, exprTyVars ); 963 ReferenceToType *polyRetType = isPolyRet( function ); 964 965 if ( polyRetType ) { 966 ret = addPolyRetParam( appExpr, function, polyRetType, arg ); 921 967 } else if ( needsAdapter( function, scopeTyVars ) ) { 922 968 // std::cerr << "needs adapter: "; … … 930 976 arg = appExpr->get_args().begin(); 931 977 932 TyVarMap exprTyVars; 933 makeTyVarMap( function, exprTyVars ); 934 935 passTypeVars( appExpr, arg, exprTyVars ); 978 passTypeVars( appExpr, polyRetType, arg, exprTyVars ); 936 979 addInferredParams( appExpr, function, arg, exprTyVars ); 937 980 … … 992 1035 } 993 1036 1037 /// Wraps a function declaration in a new pointer-to-function variable expression 1038 VariableExpr *wrapFunctionDecl( DeclarationWithType *functionDecl ) { 1039 // line below cloned from FixFunction.cc 1040 ObjectDecl *functionObj = new ObjectDecl( functionDecl->get_name(), functionDecl->get_storageClass(), functionDecl->get_linkage(), 0, 1041 new PointerType( Type::Qualifiers(), functionDecl->get_type()->clone() ), 0 ); 1042 functionObj->set_mangleName( functionDecl->get_mangleName() ); 1043 return new VariableExpr( functionObj ); 1044 } 1045 994 1046 Statement * Pass1::mutate( ReturnStmt *returnStmt ) { 995 1047 if ( retval && returnStmt->get_expr() ) { … … 1007 1059 1008 1060 // find assignment operator for (polymorphic) return type 1009 DeclarationWithType *assignDecl= 0;1061 ApplicationExpr *assignExpr = 0; 1010 1062 if ( TypeInstType *typeInst = dynamic_cast< TypeInstType *>( retval->get_type() ) ) { 1063 // find assignment operator for type variable 1011 1064 std::map< std::string, DeclarationWithType *>::const_iterator assignIter = assignOps.find( typeInst->get_name() ); 1012 1065 if ( assignIter == assignOps.end() ) { 1013 1066 throw SemanticError( "Attempt to return dtype or ftype object in ", returnStmt->get_expr() ); 1014 1067 } // if 1015 assign Decl = assignIter->second;1068 assignExpr = new ApplicationExpr( new VariableExpr( assignIter->second ) ); 1016 1069 } else if ( ReferenceToType *refType = dynamic_cast< ReferenceToType *>( retval->get_type() ) ) { 1017 ScopedMap< std::string, DeclarationWithType *>::const_iterator assignIter = scopedAssignOps.find( refType->get_name() ); 1018 if ( assignIter == scopedAssignOps.end() ) { 1070 // find assignment operator for generic type 1071 DeclarationWithType *functionDecl = scopedAssignOps.find( refType ); 1072 if ( ! functionDecl ) { 1019 1073 throw SemanticError( "Attempt to return dtype or ftype generic object in ", returnStmt->get_expr() ); 1020 1074 } 1021 DeclarationWithType *functionDecl = assignIter->second; 1022 // line below cloned from FixFunction.cc 1023 assignDecl = new ObjectDecl( functionDecl->get_name(), functionDecl->get_storageClass(), functionDecl->get_linkage(), 0, 1024 new PointerType( Type::Qualifiers(), functionDecl->get_type()->clone() ), 0 ); 1025 assignDecl->set_mangleName( functionDecl->get_mangleName() ); 1075 1076 // wrap it up in an application expression 1077 assignExpr = new ApplicationExpr( wrapFunctionDecl( functionDecl ) ); 1078 assignExpr->set_env( env->clone() ); 1079 1080 // find each of its needed secondary assignment operators 1081 std::list< Expression* > &tyParams = refType->get_parameters(); 1082 std::list< TypeDecl* > &forallParams = functionDecl->get_type()->get_forall(); 1083 std::list< Expression* >::const_iterator tyIt = tyParams.begin(); 1084 std::list< TypeDecl* >::const_iterator forallIt = forallParams.begin(); 1085 for ( ; tyIt != tyParams.end() && forallIt != forallParams.end(); ++tyIt, ++forallIt ) { 1086 if ( (*forallIt)->get_kind() != TypeDecl::Any ) continue; // skip types with no assign op (ftype/dtype) 1087 1088 std::list< DeclarationWithType* > &asserts = (*forallIt)->get_assertions(); 1089 assert( ! asserts.empty() && "Type param needs assignment operator assertion" ); 1090 DeclarationWithType *actualDecl = asserts.front(); 1091 TypeInstType *actualType = isTypeInstAssignment( actualDecl ); 1092 assert( actualType && "First assertion of type with assertions should be assignment operator" ); 1093 TypeExpr *formalTypeExpr = dynamic_cast< TypeExpr* >( *tyIt ); 1094 assert( formalTypeExpr && "type parameters must be type expressions" ); 1095 Type *formalType = formalTypeExpr->get_type(); 1096 assignExpr->get_env()->add( actualType->get_name(), formalType ); 1097 1098 DeclarationWithType *assertAssign = 0; 1099 if ( TypeInstType *formalTypeInstType = dynamic_cast< TypeInstType* >( formalType ) ) { 1100 std::map< std::string, DeclarationWithType *>::const_iterator assertAssignIt = assignOps.find( formalTypeInstType->get_name() ); 1101 if ( assertAssignIt == assignOps.end() ) { 1102 throw SemanticError( "No assignment operation found for ", formalTypeInstType ); 1103 } 1104 assertAssign = assertAssignIt->second; 1105 } else { 1106 assertAssign = scopedAssignOps.find( formalType ); 1107 if ( ! assertAssign ) { 1108 throw SemanticError( "No assignment operation found for ", formalType ); 1109 } 1110 } 1111 1112 1113 assignExpr->get_inferParams()[ actualDecl->get_uniqueId() ] 1114 = ParamEntry( assertAssign->get_uniqueId(), assertAssign->get_type()->clone(), actualDecl->get_type()->clone(), wrapFunctionDecl( assertAssign ) ); 1115 } 1026 1116 } 1027 assert( assign Decl);1117 assert( assignExpr ); 1028 1118 1029 1119 // replace return statement with appropriate assignment to out parameter 1030 ApplicationExpr *assignExpr = new ApplicationExpr( new VariableExpr( assignDecl ) );1031 1120 Expression *retParm = new NameExpr( retval->get_name() ); 1032 1121 retParm->get_results().push_back( new PointerType( Type::Qualifiers(), retval->get_type()->clone() ) ); … … 1180 1269 } 1181 1270 1182 // add size/align for generic types to parameter list1271 // add size/align for generic parameter types to parameter list 1183 1272 std::set< std::string > seenTypes; // sizeofName for generic types we've seen 1184 1273 for ( std::list< DeclarationWithType* >::const_iterator fnParm = last; fnParm != funcType->get_parameters().end(); ++fnParm ) { … … 1295 1384 1296 1385 if ( DeclarationWithType *declWithType = dynamic_cast< DeclarationWithType* >( *decl ) ) { 1297 if ( memberDecl->get_mangleName() == declWithType->get_mangleName() ) return i; 1386 if ( memberDecl->get_mangleName().empty() || declWithType->get_mangleName().empty() 1387 || memberDecl->get_mangleName() == declWithType->get_mangleName() ) return i; 1298 1388 else continue; 1299 1389 } else return i; … … 1341 1431 if ( ! objectType ) return memberExpr; 1342 1432 1433 Expression *newMemberExpr = 0; 1343 1434 if ( StructInstType *structType = dynamic_cast< StructInstType* >( objectType ) ) { 1344 1435 // look up offset index … … 1350 1441 fieldLoc->get_args().push_back( makeDerefdVar( varExpr->clone(), varDepth ) ); 1351 1442 fieldLoc->get_args().push_back( makeOffsetIndex( objectType, i ) ); 1352 1353 delete memberExpr; 1354 return fieldLoc; 1355 } else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( objectType ) ) { 1443 newMemberExpr = fieldLoc; 1444 } else if ( dynamic_cast< UnionInstType* >( objectType ) ) { 1356 1445 // union members are all at offset zero, so build appropriately-dereferenced variable 1357 Expression *derefdVar = makeDerefdVar( varExpr->clone(), varDepth ); 1358 delete memberExpr; 1359 return derefdVar; 1446 newMemberExpr = makeDerefdVar( varExpr->clone(), varDepth ); 1360 1447 } else return memberExpr; 1448 assert( newMemberExpr ); 1449 1450 Type *memberType = memberExpr->get_member()->get_type(); 1451 if ( ! isPolyType( memberType, scopeTyVars ) ) { 1452 // Not all members of a polymorphic type are themselves of polymorphic type; in this case the member expression should be wrapped and dereferenced to form an lvalue 1453 CastExpr *ptrCastExpr = new CastExpr( newMemberExpr, new PointerType( Type::Qualifiers(), memberType->clone() ) ); 1454 UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) ); 1455 derefExpr->get_args().push_back( ptrCastExpr ); 1456 newMemberExpr = derefExpr; 1457 } 1458 1459 delete memberExpr; 1460 return newMemberExpr; 1361 1461 } 1362 1462 … … 1379 1479 delete offsetofExpr; 1380 1480 return offsetInd; 1381 } else if ( UnionInstType *unionType =dynamic_cast< UnionInstType* >( ty ) ) {1481 } else if ( dynamic_cast< UnionInstType* >( ty ) ) { 1382 1482 // all union members are at offset zero 1383 1483 delete offsetofExpr;
Note:
See TracChangeset
for help on using the changeset viewer.