Changes in src/GenPoly/Box.cc [974906e2:bd85400]
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/GenPoly/Box.cc
r974906e2 rbd85400 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Rob Schluntz12 // Last Modified On : Thu Jan 07 13:40:05201613 // Update Count : 2 1911 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Feb 5 16:45:07 2016 13 // Update Count : 286 14 14 // 15 15 … … 22 22 23 23 #include "Box.h" 24 #include "InstantiateGeneric.h" 24 25 #include "PolyMutator.h" 25 26 #include "FindFunction.h" 27 #include "ScopedMap.h" 26 28 #include "ScrubTyVars.h" 27 29 … … 39 41 #include "SymTab/Mangler.h" 40 42 41 #include " SemanticError.h"42 #include " UniqueName.h"43 #include " utility.h"43 #include "Common/SemanticError.h" 44 #include "Common/UniqueName.h" 45 #include "Common/utility.h" 44 46 45 47 #include <ext/functional> // temporary … … 69 71 virtual void doEndScope(); 70 72 private: 73 /// Makes a new temporary array holding the offsets of the fields of `type`, and returns a new variable expression referencing it 74 Expression *makeOffsetArray( StructInstType *type ); 75 /// passes extra type parameters into a polymorphic function application 71 76 void passTypeVars( ApplicationExpr *appExpr, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars ); 77 /// wraps a function application with a new temporary for the out-parameter return value 72 78 Expression *addRetParam( ApplicationExpr *appExpr, FunctionType *function, Type *retType, std::list< Expression *>::iterator &arg ); 73 Expression *addPolyRetParam( ApplicationExpr *appExpr, FunctionType *function, std::string typeName, std::list< Expression *>::iterator &arg ); 79 /// Replaces all the type parameters of a generic type with their concrete equivalents under the current environment 80 void replaceParametersWithConcrete( ApplicationExpr *appExpr, std::list< Expression* >& params ); 81 /// Replaces a polymorphic type with its concrete equivalant under the current environment (returns itself if concrete). 82 /// If `doClone` is set to false, will not clone interior types 83 Type *replaceWithConcrete( ApplicationExpr *appExpr, Type *type, bool doClone = true ); 84 /// wraps a function application returning a polymorphic type with a new temporary for the out-parameter return value 85 Expression *addPolyRetParam( ApplicationExpr *appExpr, FunctionType *function, ReferenceToType *polyType, std::list< Expression *>::iterator &arg ); 74 86 Expression *applyAdapter( ApplicationExpr *appExpr, FunctionType *function, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars ); 75 87 void boxParam( Type *formal, Expression *&arg, const TyVarMap &exprTyVars ); 76 88 void boxParams( ApplicationExpr *appExpr, FunctionType *function, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars ); 77 89 void addInferredParams( ApplicationExpr *appExpr, FunctionType *functionType, std::list< Expression *>::iterator &arg, const TyVarMap &tyVars ); 90 /// Stores assignment operators from assertion list in local map of assignment operations 78 91 void findAssignOps( const std::list< TypeDecl *> &forall ); 79 92 void passAdapters( ApplicationExpr *appExpr, FunctionType *functionType, const TyVarMap &exprTyVars ); 80 93 FunctionDecl *makeAdapter( FunctionType *adaptee, FunctionType *realType, const std::string &mangleName, const TyVarMap &tyVars ); 94 /// Replaces intrinsic operator functions with their arithmetic desugaring 81 95 Expression *handleIntrinsics( ApplicationExpr *appExpr ); 96 /// Inserts a new temporary variable into the current scope with an auto-generated name 82 97 ObjectDecl *makeTemporary( Type *type ); 83 98 84 99 typedef std::map< std::string, DeclarationWithType *> AdapterMap; 85 100 std::map< std::string, DeclarationWithType *> assignOps; 101 ScopedMap< std::string, DeclarationWithType *> scopedAssignOps; 86 102 std::stack< AdapterMap > adapters; 87 103 DeclarationWithType *retval; … … 107 123 }; 108 124 109 /// Replaces initialization of polymorphic values with alloca, declaration of dtype/ftype with appropriate void expression, and sizeof expressions of polymorphic types with the proper variable 110 class Pass3 : public PolyMutator { 125 /// Replaces member expressions for polymorphic types with calculated add-field-offset-and-dereference; 126 /// also fixes offsetof expressions. 127 class MemberExprFixer : public PolyMutator { 111 128 public: 112 129 template< typename DeclClass > … … 119 136 virtual Type *mutate( PointerType *pointerType ); 120 137 virtual Type *mutate( FunctionType *funcType ); 138 virtual Expression *mutate( MemberExpr *memberExpr ); 139 virtual Expression *mutate( OffsetofExpr *offsetofExpr ); 140 }; 141 142 /// Replaces initialization of polymorphic values with alloca, declaration of dtype/ftype with appropriate void expression, and sizeof expressions of polymorphic types with the proper variable 143 class Pass3 : public PolyMutator { 144 public: 145 template< typename DeclClass > 146 DeclClass *handleDecl( DeclClass *decl, Type *type ); 147 virtual DeclarationWithType *mutate( FunctionDecl *functionDecl ); 148 virtual ObjectDecl *mutate( ObjectDecl *objectDecl ); 149 virtual TypedefDecl *mutate( TypedefDecl *objectDecl ); 150 virtual TypeDecl *mutate( TypeDecl *objectDecl ); 151 virtual Type *mutate( PointerType *pointerType ); 152 virtual Type *mutate( FunctionType *funcType ); 121 153 private: 122 154 }; … … 133 165 } 134 166 167 /// version of mutateAll with special handling for translation unit so you can check the end of the prelude when debugging 168 template< typename MutatorType > 169 inline void mutateTranslationUnit( std::list< Declaration* > &translationUnit, MutatorType &mutator ) { 170 bool seenIntrinsic = false; 171 SemanticError errors; 172 for ( typename std::list< Declaration* >::iterator i = translationUnit.begin(); i != translationUnit.end(); ++i ) { 173 try { 174 if ( *i ) { 175 if ( (*i)->get_linkage() == LinkageSpec::Intrinsic ) { 176 seenIntrinsic = true; 177 } else if ( seenIntrinsic ) { 178 seenIntrinsic = false; // break on this line when debugging for end of prelude 179 } 180 181 *i = dynamic_cast< Declaration* >( (*i)->acceptMutator( mutator ) ); 182 assert( *i ); 183 } // if 184 } catch( SemanticError &e ) { 185 errors.append( e ); 186 } // try 187 } // for 188 if ( ! errors.isEmpty() ) { 189 throw errors; 190 } // if 191 } 192 135 193 void box( std::list< Declaration *>& translationUnit ) { 136 194 Pass1 pass1; 137 195 Pass2 pass2; 196 MemberExprFixer memberFixer; 138 197 Pass3 pass3; 139 mutateAll( translationUnit, pass1 ); 140 mutateAll( translationUnit, pass2 ); 141 mutateAll( translationUnit, pass3 ); 198 mutateTranslationUnit/*All*/( translationUnit, pass1 ); 199 mutateTranslationUnit/*All*/( translationUnit, pass2 ); 200 instantiateGeneric( translationUnit ); 201 mutateTranslationUnit/*All*/( translationUnit, memberFixer ); 202 mutateTranslationUnit/*All*/( translationUnit, pass3 ); 142 203 } 143 204 … … 185 246 } 186 247 187 // returns true if the given declaration is: (*?=?)(T *, T) for some T (return not checked, but maybe should be)188 bool checkAssignment( DeclarationWithType *decl, std::string &name) {248 /// returns T if the given declaration is: (*?=?)(T *, T) for some T (return not checked, but maybe should be), NULL otherwise 249 ReferenceToType *isAssignment( DeclarationWithType *decl ) { 189 250 if ( decl->get_name() == "?=?" ) { 190 if ( PointerType *ptrType = dynamic_cast< PointerType *>( decl->get_type() ) ) { 191 if ( FunctionType *funType = dynamic_cast< FunctionType *>( ptrType->get_base() ) ) { 192 if ( funType->get_parameters().size() == 2 ) { 193 if ( PointerType *pointer = dynamic_cast< PointerType *>( funType->get_parameters().front()->get_type() ) ) { 194 if ( TypeInstType *typeInst = dynamic_cast< TypeInstType *>( pointer->get_base() ) ) { 195 if ( TypeInstType *typeInst2 = dynamic_cast< TypeInstType *>( funType->get_parameters().back()->get_type() ) ) { 196 if ( typeInst->get_name() == typeInst2->get_name() ) { 197 name = typeInst->get_name(); 198 return true; 199 } // if 251 if ( FunctionType *funType = getFunctionType( decl->get_type() ) ) { 252 if ( funType->get_parameters().size() == 2 ) { 253 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() ) ) { 256 if ( refType->get_name() == refType2->get_name() ) { 257 return refType; 200 258 } // if 201 259 } // if … … 205 263 } // if 206 264 } // if 207 return false;265 return 0; 208 266 } 209 267 … … 214 272 for ( std::list< DeclarationWithType *>::const_iterator assert = (*i)->get_assertions().begin(); assert != (*i)->get_assertions().end(); ++assert ) { 215 273 std::string typeName; 216 if ( checkAssignment( *assert, typeName) ) {217 assignOps[ type Name] = *assert;274 if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( isAssignment( *assert ) ) ) { 275 assignOps[ typeInst->get_name() ] = *assert; 218 276 } // if 219 277 } // for … … 222 280 223 281 DeclarationWithType *Pass1::mutate( FunctionDecl *functionDecl ) { 282 // 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 ); 286 } 287 } 288 224 289 if ( functionDecl->get_statements() ) { // empty routine body ? 225 290 doBeginScope(); … … 231 296 // process polymorphic return value 232 297 retval = 0; 233 std::string typeName; 234 if ( isPolyRet( functionDecl->get_functionType(), typeName ) && functionDecl->get_linkage() == LinkageSpec::Cforall ) { 298 if ( isPolyRet( functionDecl->get_functionType() ) && functionDecl->get_linkage() == LinkageSpec::Cforall ) { 235 299 retval = functionDecl->get_functionType()->get_returnVals().front(); 236 300 … … 256 320 findFunction( (*arg)->get_type(), functions, scopeTyVars, needsAdapter ); 257 321 } // for 322 258 323 AdapterMap & adapters = Pass1::adapters.top(); 259 324 for ( std::list< FunctionType *>::iterator funType = functions.begin(); funType != functions.end(); ++funType ) { … … 304 369 return condExpr; 305 370 371 } 372 373 Expression *Pass1::makeOffsetArray( StructInstType *ty ) { 374 std::list< Declaration* > &baseMembers = ty->get_baseStruct()->get_members(); 375 376 // make a new temporary array 377 Type *offsetType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ); 378 std::stringstream lenGen; 379 lenGen << baseMembers.size(); 380 ConstantExpr *lenExpr = new ConstantExpr( Constant( offsetType->clone(), lenGen.str() ) ); 381 ObjectDecl *arrayTemp = makeTemporary( new ArrayType( Type::Qualifiers(), offsetType, lenExpr, false, false ) ); 382 383 // build initializer list for temporary 384 std::list< Initializer* > inits; 385 for ( std::list< Declaration* >::const_iterator member = baseMembers.begin(); member != baseMembers.end(); ++member ) { 386 DeclarationWithType *memberDecl; 387 if ( DeclarationWithType *origMember = dynamic_cast< DeclarationWithType* >( *member ) ) { 388 memberDecl = origMember->clone(); 389 } else { 390 memberDecl = new ObjectDecl( (*member)->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, offsetType->clone(), 0 ); 391 } 392 inits.push_back( new SingleInit( new OffsetofExpr( ty->clone(), memberDecl ) ) ); 393 } 394 arrayTemp->set_init( new ListInit( inits ) ); 395 396 // return variable pointing to temporary 397 return new VariableExpr( arrayTemp ); 306 398 } 307 399 … … 325 417 326 418 // add size/align for generic types to parameter list 327 //assert( ! appExpr->get_function()->get_results().empty() );328 419 if ( appExpr->get_function()->get_results().empty() ) return; 329 420 FunctionType *funcType = getFunctionType( appExpr->get_function()->get_results().front() ); … … 334 425 std::set< std::string > seenTypes; //< names for generic types we've seen 335 426 for ( ; fnParm != funcType->get_parameters().end() && fnArg != appExpr->get_args().end(); ++fnParm, ++fnArg ) { 336 Type *p armType = (*fnParm)->get_type();337 if ( ! dynamic_cast< TypeInstType* >( parmType ) && isPolyType( parmType, exprTyVars) ) {338 std::string sizeName = sizeofName( p armType );427 Type *polyBase = hasPolyBase( (*fnParm)->get_type(), exprTyVars ); 428 if ( polyBase && ! dynamic_cast< TypeInstType* >( polyBase ) ) { 429 std::string sizeName = sizeofName( polyBase ); 339 430 if ( seenTypes.count( sizeName ) ) continue; 340 431 341 assert( ! (*fnArg)->get_results().empty() ); 342 Type *argType = (*fnArg)->get_results().front(); 343 arg = appExpr->get_args().insert( arg, new SizeofExpr( argType->clone() ) ); 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() ) ); 344 436 arg++; 345 arg = appExpr->get_args().insert( arg, new AlignofExpr( arg Type->clone() ) );437 arg = appExpr->get_args().insert( arg, new AlignofExpr( argBaseType->clone() ) ); 346 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 } 347 447 348 448 seenTypes.insert( sizeName ); … … 386 486 } 387 487 388 Expression *Pass1::addPolyRetParam( ApplicationExpr *appExpr, FunctionType *function, std::string typeName, std::list< Expression *>::iterator &arg ) { 389 ResolvExpr::EqvClass eqvClass; 488 void Pass1::replaceParametersWithConcrete( ApplicationExpr *appExpr, std::list< Expression* >& params ) { 489 for ( std::list< Expression* >::iterator param = params.begin(); param != params.end(); ++param ) { 490 TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param ); 491 assert(paramType && "Aggregate parameters should be type expressions"); 492 paramType->set_type( replaceWithConcrete( appExpr, paramType->get_type(), false ) ); 493 } 494 } 495 496 Type *Pass1::replaceWithConcrete( ApplicationExpr *appExpr, Type *type, bool doClone ) { 497 if ( TypeInstType *typeInst = dynamic_cast< TypeInstType * >( type ) ) { 498 Type *concrete = env->lookup( typeInst->get_name() ); 499 if ( concrete == 0 ) { 500 throw SemanticError( "Unbound type variable " + typeInst->get_name() + " in ", appExpr ); 501 } // if 502 return concrete; 503 } else if ( StructInstType *structType = dynamic_cast< StructInstType* >( type ) ) { 504 if ( doClone ) { 505 structType = structType->clone(); 506 } 507 replaceParametersWithConcrete( appExpr, structType->get_parameters() ); 508 return structType; 509 } else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( type ) ) { 510 if ( doClone ) { 511 unionType = unionType->clone(); 512 } 513 replaceParametersWithConcrete( appExpr, unionType->get_parameters() ); 514 return unionType; 515 } 516 return type; 517 } 518 519 Expression *Pass1::addPolyRetParam( ApplicationExpr *appExpr, FunctionType *function, ReferenceToType *polyType, std::list< Expression *>::iterator &arg ) { 390 520 assert( env ); 391 Type *concrete = env->lookup( typeName ); 392 if ( concrete == 0 ) { 393 throw SemanticError( "Unbound type variable " + typeName + " in ", appExpr ); 394 } // if 521 Type *concrete = replaceWithConcrete( appExpr, polyType ); 395 522 return addRetParam( appExpr, function, concrete, arg ); 396 523 } … … 404 531 std::string adapterName = makeAdapterName( mangleName ); 405 532 406 appExpr->get_args().push_front( appExpr->get_function() ); 533 // cast adaptee to void (*)(), since it may have any type inside a polymorphic function 534 Type * adapteeType = new PointerType( Type::Qualifiers(), new FunctionType( Type::Qualifiers(), true ) ); 535 appExpr->get_args().push_front( new CastExpr( appExpr->get_function(), adapteeType ) ); 407 536 appExpr->set_function( new NameExpr( adapterName ) ); 408 537 … … 412 541 void Pass1::boxParam( Type *param, Expression *&arg, const TyVarMap &exprTyVars ) { 413 542 assert( ! arg->get_results().empty() ); 414 // if ( ! dynamic_cast< PointerType *>( arg->get_results().front() ) ) { 415 TypeInstType *typeInst = dynamic_cast< TypeInstType *>( param ); 416 if ( typeInst && exprTyVars.find( typeInst->get_name() ) != exprTyVars.end() ) { 543 if ( isPolyType( param, exprTyVars ) ) { 417 544 if ( dynamic_cast< TypeInstType *>( arg->get_results().front() ) ) { 418 545 // if the argument's type is a type parameter, we don't need to box again! … … 422 549 arg = new AddressExpr( arg ); 423 550 } else { 424 ObjectDecl *newObj = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, arg->get_results().front()->clone(), 0 ); 551 // use type computed in unification to declare boxed variables 552 Type * newType = param->clone(); 553 if ( env ) env->apply( newType ); 554 ObjectDecl *newObj = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, newType, 0 ); 425 555 newObj->get_type()->get_qualifiers() = Type::Qualifiers(); // TODO: is this right??? 426 556 stmtsToAdd.push_back( new DeclStmt( noLabels, newObj ) ); … … 432 562 } // if 433 563 } // if 434 // } 435 } 436 564 } 565 566 /// cast parameters to polymorphic functions so that types are replaced with 567 /// void * if they are type parameters in the formal type. 568 /// this gets rid of warnings from gcc. 437 569 void addCast( Expression *&actual, Type *formal, const TyVarMap &tyVars ) { 438 Type *newType = formal->clone(); 439 std::list< FunctionType *> functions; 440 // instead of functions needing adapters, this really ought to look for 441 // any function mentioning a polymorphic type 442 findAndReplaceFunction( newType, functions, tyVars, needsAdapter ); 443 if ( ! functions.empty() ) { 570 Type * newType = formal->clone(); 571 if ( getFunctionType( newType ) ) { 572 newType = ScrubTyVars::scrub( newType, tyVars ); 444 573 actual = new CastExpr( actual, newType ); 445 } else {446 delete newType;447 574 } // if 448 575 } … … 495 622 assert( arg ); 496 623 if ( isPolyType( realParam->get_type(), tyVars ) ) { 497 // if ( dynamic_cast< PointerType *>( arg->get_type() ) ) {498 // return new CastExpr( new VariableExpr( param ), arg->get_type()->clone() );499 // } else {500 624 if ( dynamic_cast<TypeInstType *>(arg->get_type()) == NULL ) { 501 625 UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) ); … … 504 628 return deref; 505 629 } // if 506 // }507 630 } // if 508 631 return new VariableExpr( param ); … … 794 917 std::list< Expression *>::iterator paramBegin = appExpr->get_args().begin(); 795 918 796 std::string typeName; 797 if ( isPolyRet( function, typeName ) ) { 798 ret = addPolyRetParam( appExpr, function, typeName, arg ); 919 if ( ReferenceToType *polyType = isPolyRet( function ) ) { 920 ret = addPolyRetParam( appExpr, function, polyType, arg ); 799 921 } else if ( needsAdapter( function, scopeTyVars ) ) { 800 922 // std::cerr << "needs adapter: "; … … 883 1005 delete castExpr; 884 1006 } //while 885 TypeInstType *typeInst = dynamic_cast< TypeInstType *>( retval->get_type() ); 886 assert( typeInst ); 887 std::map< std::string, DeclarationWithType *>::const_iterator assignIter = assignOps.find( typeInst->get_name() ); 888 if ( assignIter == assignOps.end() ) { 889 throw SemanticError( "Attempt to return dtype or ftype object in ", returnStmt->get_expr() ); 890 } // if 891 ApplicationExpr *assignExpr = new ApplicationExpr( new VariableExpr( assignIter->second ) ); 1007 1008 // find assignment operator for (polymorphic) return type 1009 DeclarationWithType *assignDecl = 0; 1010 if ( TypeInstType *typeInst = dynamic_cast< TypeInstType *>( retval->get_type() ) ) { 1011 std::map< std::string, DeclarationWithType *>::const_iterator assignIter = assignOps.find( typeInst->get_name() ); 1012 if ( assignIter == assignOps.end() ) { 1013 throw SemanticError( "Attempt to return dtype or ftype object in ", returnStmt->get_expr() ); 1014 } // if 1015 assignDecl = assignIter->second; 1016 } 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() ) { 1019 throw SemanticError( "Attempt to return dtype or ftype generic object in ", returnStmt->get_expr() ); 1020 } 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() ); 1026 } 1027 assert( assignDecl ); 1028 1029 // replace return statement with appropriate assignment to out parameter 1030 ApplicationExpr *assignExpr = new ApplicationExpr( new VariableExpr( assignDecl ) ); 892 1031 Expression *retParm = new NameExpr( retval->get_name() ); 893 1032 retParm->get_results().push_back( new PointerType( Type::Qualifiers(), retval->get_type()->clone() ) ); … … 930 1069 // push a copy of the current map 931 1070 adapters.push(adapters.top()); 1071 scopedAssignOps.beginScope(); 932 1072 } 933 1073 934 1074 void Pass1::doEndScope() { 935 1075 adapters.pop(); 1076 scopedAssignOps.endScope(); 936 1077 } 937 1078 … … 1001 1142 1002 1143 // move polymorphic return type to parameter list 1003 std::string typeName; 1004 if ( isPolyRet( funcType, typeName ) ) { 1144 if ( isPolyRet( funcType ) ) { 1005 1145 DeclarationWithType *ret = funcType->get_returnVals().front(); 1006 1146 ret->set_type( new PointerType( Type::Qualifiers(), ret->get_type() ) ); … … 1013 1153 std::list< DeclarationWithType *> inferredParams; 1014 1154 ObjectDecl newObj( "", DeclarationNode::NoStorageClass, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), 0 ); 1155 ObjectDecl newPtr( "", DeclarationNode::NoStorageClass, LinkageSpec::C, 0, 1156 new PointerType( Type::Qualifiers(), new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) ), 0 ); 1015 1157 // ObjectDecl *newFunPtr = new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), new FunctionType( Type::Qualifiers(), true ) ), 0 ); 1016 1158 for ( std::list< TypeDecl *>::const_iterator tyParm = funcType->get_forall().begin(); tyParm != funcType->get_forall().end(); ++tyParm ) { … … 1039 1181 1040 1182 // add size/align for generic types to parameter list 1041 std::set< std::string > seenTypes; // <sizeofName for generic types we've seen1183 std::set< std::string > seenTypes; // sizeofName for generic types we've seen 1042 1184 for ( std::list< DeclarationWithType* >::const_iterator fnParm = last; fnParm != funcType->get_parameters().end(); ++fnParm ) { 1043 Type *p armType = (*fnParm)->get_type();1044 if ( ! dynamic_cast< TypeInstType* >( parmType ) && isPolyType( parmType, scopeTyVars) ) {1045 std::string sizeName = sizeofName( p armType );1185 Type *polyBase = hasPolyBase( (*fnParm)->get_type(), scopeTyVars ); 1186 if ( polyBase && ! dynamic_cast< TypeInstType* >( polyBase ) ) { 1187 std::string sizeName = sizeofName( polyBase ); 1046 1188 if ( seenTypes.count( sizeName ) ) continue; 1047 1189 1048 ObjectDecl *sizeParm, *alignParm ;1190 ObjectDecl *sizeParm, *alignParm, *offsetParm; 1049 1191 sizeParm = newObj.clone(); 1050 1192 sizeParm->set_name( sizeName ); … … 1053 1195 1054 1196 alignParm = newObj.clone(); 1055 alignParm->set_name( alignofName( p armType ) );1197 alignParm->set_name( alignofName( polyBase ) ); 1056 1198 last = funcType->get_parameters().insert( last, alignParm ); 1057 1199 ++last; 1200 1201 if ( dynamic_cast< StructInstType* >( polyBase ) ) { 1202 offsetParm = newPtr.clone(); 1203 offsetParm->set_name( offsetofName( polyBase ) ); 1204 last = funcType->get_parameters().insert( last, offsetParm ); 1205 ++last; 1206 } 1058 1207 1059 1208 seenTypes.insert( sizeName ); … … 1069 1218 scopeTyVars = oldtyVars; 1070 1219 return funcType; 1220 } 1221 1222 ////////////////////////////////////////// MemberExprFixer //////////////////////////////////////////////////// 1223 1224 template< typename DeclClass > 1225 DeclClass * MemberExprFixer::handleDecl( DeclClass *decl, Type *type ) { 1226 TyVarMap oldtyVars = scopeTyVars; 1227 makeTyVarMap( type, scopeTyVars ); 1228 1229 DeclClass *ret = static_cast< DeclClass *>( Mutator::mutate( decl ) ); 1230 1231 scopeTyVars = oldtyVars; 1232 return ret; 1233 } 1234 1235 ObjectDecl * MemberExprFixer::mutate( ObjectDecl *objectDecl ) { 1236 return handleDecl( objectDecl, objectDecl->get_type() ); 1237 } 1238 1239 DeclarationWithType * MemberExprFixer::mutate( FunctionDecl *functionDecl ) { 1240 return handleDecl( functionDecl, functionDecl->get_functionType() ); 1241 } 1242 1243 TypedefDecl * MemberExprFixer::mutate( TypedefDecl *typedefDecl ) { 1244 return handleDecl( typedefDecl, typedefDecl->get_base() ); 1245 } 1246 1247 TypeDecl * MemberExprFixer::mutate( TypeDecl *typeDecl ) { 1248 scopeTyVars[ typeDecl->get_name() ] = typeDecl->get_kind(); 1249 return Mutator::mutate( typeDecl ); 1250 } 1251 1252 Type * MemberExprFixer::mutate( PointerType *pointerType ) { 1253 TyVarMap oldtyVars = scopeTyVars; 1254 makeTyVarMap( pointerType, scopeTyVars ); 1255 1256 Type *ret = Mutator::mutate( pointerType ); 1257 1258 scopeTyVars = oldtyVars; 1259 return ret; 1260 } 1261 1262 Type * MemberExprFixer::mutate( FunctionType *functionType ) { 1263 TyVarMap oldtyVars = scopeTyVars; 1264 makeTyVarMap( functionType, scopeTyVars ); 1265 1266 Type *ret = Mutator::mutate( functionType ); 1267 1268 scopeTyVars = oldtyVars; 1269 return ret; 1270 } 1271 1272 Statement *MemberExprFixer::mutate( DeclStmt *declStmt ) { 1273 if ( ObjectDecl *objectDecl = dynamic_cast< ObjectDecl *>( declStmt->get_decl() ) ) { 1274 if ( isPolyType( objectDecl->get_type(), scopeTyVars ) ) { 1275 // change initialization of a polymorphic value object 1276 // to allocate storage with alloca 1277 Type *declType = objectDecl->get_type(); 1278 UntypedExpr *alloc = new UntypedExpr( new NameExpr( "__builtin_alloca" ) ); 1279 alloc->get_args().push_back( new NameExpr( sizeofName( declType ) ) ); 1280 1281 delete objectDecl->get_init(); 1282 1283 std::list<Expression*> designators; 1284 objectDecl->set_init( new SingleInit( alloc, designators ) ); 1285 } 1286 } 1287 return Mutator::mutate( declStmt ); 1288 } 1289 1290 /// Finds the member in the base list that matches the given declaration; returns its index, or -1 if not present 1291 long findMember( DeclarationWithType *memberDecl, std::list< Declaration* > &baseDecls ) { 1292 long i = 0; 1293 for(std::list< Declaration* >::const_iterator decl = baseDecls.begin(); decl != baseDecls.end(); ++decl, ++i ) { 1294 if ( memberDecl->get_name() != (*decl)->get_name() ) continue; 1295 1296 if ( DeclarationWithType *declWithType = dynamic_cast< DeclarationWithType* >( *decl ) ) { 1297 if ( memberDecl->get_mangleName() == declWithType->get_mangleName() ) return i; 1298 else continue; 1299 } else return i; 1300 } 1301 return -1; 1302 } 1303 1304 /// Returns an index expression into the offset array for a type 1305 Expression *makeOffsetIndex( Type *objectType, long i ) { 1306 std::stringstream offset_namer; 1307 offset_namer << i; 1308 ConstantExpr *fieldIndex = new ConstantExpr( Constant( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), offset_namer.str() ) ); 1309 UntypedExpr *fieldOffset = new UntypedExpr( new NameExpr( "?[?]" ) ); 1310 fieldOffset->get_args().push_back( new NameExpr( offsetofName( objectType ) ) ); 1311 fieldOffset->get_args().push_back( fieldIndex ); 1312 return fieldOffset; 1313 } 1314 1315 /// Returns an expression dereferenced n times 1316 Expression *makeDerefdVar( Expression *derefdVar, long n ) { 1317 for ( int i = 1; i < n; ++i ) { 1318 UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) ); 1319 derefExpr->get_args().push_back( derefdVar ); 1320 derefdVar = derefExpr; 1321 } 1322 return derefdVar; 1323 } 1324 1325 Expression *MemberExprFixer::mutate( MemberExpr *memberExpr ) { 1326 // mutate, exiting early if no longer MemberExpr 1327 Expression *expr = Mutator::mutate( memberExpr ); 1328 memberExpr = dynamic_cast< MemberExpr* >( expr ); 1329 if ( ! memberExpr ) return expr; 1330 1331 // get declaration for base struct, exiting early if not found 1332 int varDepth; 1333 VariableExpr *varExpr = getBaseVar( memberExpr->get_aggregate(), &varDepth ); 1334 if ( ! varExpr ) return memberExpr; 1335 ObjectDecl *objectDecl = dynamic_cast< ObjectDecl* >( varExpr->get_var() ); 1336 if ( ! objectDecl ) return memberExpr; 1337 1338 // only mutate member expressions for polymorphic types 1339 int tyDepth; 1340 Type *objectType = hasPolyBase( objectDecl->get_type(), scopeTyVars, &tyDepth ); 1341 if ( ! objectType ) return memberExpr; 1342 1343 if ( StructInstType *structType = dynamic_cast< StructInstType* >( objectType ) ) { 1344 // look up offset index 1345 long i = findMember( memberExpr->get_member(), structType->get_baseStruct()->get_members() ); 1346 if ( i == -1 ) return memberExpr; 1347 1348 // replace member expression with pointer to base plus offset 1349 UntypedExpr *fieldLoc = new UntypedExpr( new NameExpr( "?+?" ) ); 1350 fieldLoc->get_args().push_back( makeDerefdVar( varExpr->clone(), varDepth ) ); 1351 fieldLoc->get_args().push_back( makeOffsetIndex( objectType, i ) ); 1352 1353 delete memberExpr; 1354 return fieldLoc; 1355 } else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( objectType ) ) { 1356 // 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; 1360 } else return memberExpr; 1361 } 1362 1363 Expression *MemberExprFixer::mutate( OffsetofExpr *offsetofExpr ) { 1364 // mutate, exiting early if no longer OffsetofExpr 1365 Expression *expr = Mutator::mutate( offsetofExpr ); 1366 offsetofExpr = dynamic_cast< OffsetofExpr* >( expr ); 1367 if ( ! offsetofExpr ) return expr; 1368 1369 // only mutate expressions for polymorphic structs/unions 1370 Type *ty = isPolyType( offsetofExpr->get_type(), scopeTyVars ); 1371 if ( ! ty ) return offsetofExpr; 1372 1373 if ( StructInstType *structType = dynamic_cast< StructInstType* >( ty ) ) { 1374 // replace offsetof expression by index into offset array 1375 long i = findMember( offsetofExpr->get_member(), structType->get_baseStruct()->get_members() ); 1376 if ( i == -1 ) return offsetofExpr; 1377 1378 Expression *offsetInd = makeOffsetIndex( ty, i ); 1379 delete offsetofExpr; 1380 return offsetInd; 1381 } else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( ty ) ) { 1382 // all union members are at offset zero 1383 delete offsetofExpr; 1384 return new ConstantExpr( Constant( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), std::string("0") ) ); 1385 } else return offsetofExpr; 1071 1386 } 1072 1387 … … 1129 1444 return ret; 1130 1445 } 1131 1132 Statement *Pass3::mutate( DeclStmt *declStmt ) {1133 if ( ObjectDecl *objectDecl = dynamic_cast< ObjectDecl *>( declStmt->get_decl() ) ) {1134 if ( isPolyType( objectDecl->get_type(), scopeTyVars ) ) {1135 // change initialization of a polymorphic value object1136 // to allocate storage with alloca1137 Type *declType = objectDecl->get_type();1138 UntypedExpr *alloc = new UntypedExpr( new NameExpr( "__builtin_alloca" ) );1139 alloc->get_args().push_back( new NameExpr( sizeofName( declType ) ) );1140 1141 delete objectDecl->get_init();1142 1143 std::list<Expression*> designators;1144 objectDecl->set_init( new SingleInit( alloc, designators, false ) ); // not constructed1145 }1146 }1147 return Mutator::mutate( declStmt );1148 }1149 1446 } // anonymous namespace 1150 1447 } // namespace GenPoly
Note:
See TracChangeset
for help on using the changeset viewer.