Changes in src/GenPoly/Box.cc [05d47278:1cced28]
- File:
-
- 1 edited
-
src/GenPoly/Box.cc (modified) (27 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/GenPoly/Box.cc
r05d47278 r1cced28 22 22 23 23 #include "Box.h" 24 #include "InstantiateGeneric.h"25 24 #include "PolyMutator.h" 26 25 #include "FindFunction.h" 27 #include "ScopedMap.h"28 26 #include "ScrubTyVars.h" 29 27 … … 71 69 virtual void doEndScope(); 72 70 private: 73 /// Makes a new temporary array holding the offsets of the fields of `type`, and returns a new variable expression referencing it74 Expression *makeOffsetArray( StructInstType *type );75 /// passes extra type parameters into a polymorphic function application76 71 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 value78 72 Expression *addRetParam( ApplicationExpr *appExpr, FunctionType *function, Type *retType, 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 ); 73 Expression *addPolyRetParam( ApplicationExpr *appExpr, FunctionType *function, std::string typeName, std::list< Expression *>::iterator &arg ); 86 74 Expression *applyAdapter( ApplicationExpr *appExpr, FunctionType *function, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars ); 87 75 void boxParam( Type *formal, Expression *&arg, const TyVarMap &exprTyVars ); 88 76 void boxParams( ApplicationExpr *appExpr, FunctionType *function, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars ); 89 77 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 operations91 78 void findAssignOps( const std::list< TypeDecl *> &forall ); 92 79 void passAdapters( ApplicationExpr *appExpr, FunctionType *functionType, const TyVarMap &exprTyVars ); 93 80 FunctionDecl *makeAdapter( FunctionType *adaptee, FunctionType *realType, const std::string &mangleName, const TyVarMap &tyVars ); 94 /// Replaces intrinsic operator functions with their arithmetic desugaring95 81 Expression *handleIntrinsics( ApplicationExpr *appExpr ); 96 /// Inserts a new temporary variable into the current scope with an auto-generated name97 82 ObjectDecl *makeTemporary( Type *type ); 98 83 99 84 typedef std::map< std::string, DeclarationWithType *> AdapterMap; 100 85 std::map< std::string, DeclarationWithType *> assignOps; 101 ScopedMap< std::string, DeclarationWithType *> scopedAssignOps;102 86 std::stack< AdapterMap > adapters; 103 87 DeclarationWithType *retval; … … 123 107 }; 124 108 125 /// Replaces member expressions for polymorphic types with calculated add-field-offset-and-dereference126 class MemberExprFixer: public PolyMutator {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 { 127 111 public: 128 112 template< typename DeclClass > … … 135 119 virtual Type *mutate( PointerType *pointerType ); 136 120 virtual Type *mutate( FunctionType *funcType ); 137 virtual Expression *mutate( MemberExpr *memberExpr );138 };139 140 /// Replaces initialization of polymorphic values with alloca, declaration of dtype/ftype with appropriate void expression, and sizeof expressions of polymorphic types with the proper variable141 class Pass3 : public PolyMutator {142 public:143 template< typename DeclClass >144 DeclClass *handleDecl( DeclClass *decl, Type *type );145 virtual DeclarationWithType *mutate( FunctionDecl *functionDecl );146 virtual ObjectDecl *mutate( ObjectDecl *objectDecl );147 virtual TypedefDecl *mutate( TypedefDecl *objectDecl );148 virtual TypeDecl *mutate( TypeDecl *objectDecl );149 virtual Type *mutate( PointerType *pointerType );150 virtual Type *mutate( FunctionType *funcType );151 121 private: 152 122 }; … … 163 133 } 164 134 165 /// version of mutateAll with special handling for translation unit so you can check the end of the prelude when debugging166 template< typename MutatorType >167 inline void mutateTranslationUnit( std::list< Declaration* > &translationUnit, MutatorType &mutator ) {168 bool seenIntrinsic = false;169 SemanticError errors;170 for ( typename std::list< Declaration* >::iterator i = translationUnit.begin(); i != translationUnit.end(); ++i ) {171 try {172 if ( *i ) {173 if ( (*i)->get_linkage() == LinkageSpec::Intrinsic ) {174 seenIntrinsic = true;175 } else if ( seenIntrinsic ) {176 seenIntrinsic = false; // break on this line when debugging for end of prelude177 }178 179 *i = dynamic_cast< Declaration* >( (*i)->acceptMutator( mutator ) );180 assert( *i );181 } // if182 } catch( SemanticError &e ) {183 errors.append( e );184 } // try185 } // for186 if ( ! errors.isEmpty() ) {187 throw errors;188 } // if189 }190 191 135 void box( std::list< Declaration *>& translationUnit ) { 192 136 Pass1 pass1; 193 137 Pass2 pass2; 194 MemberExprFixer memberFixer;195 138 Pass3 pass3; 196 mutateTranslationUnit/*All*/( translationUnit, pass1 ); 197 mutateTranslationUnit/*All*/( translationUnit, pass2 ); 198 instantiateGeneric( translationUnit ); 199 mutateTranslationUnit/*All*/( translationUnit, memberFixer ); 200 mutateTranslationUnit/*All*/( translationUnit, pass3 ); 139 mutateAll( translationUnit, pass1 ); 140 mutateAll( translationUnit, pass2 ); 141 mutateAll( translationUnit, pass3 ); 201 142 } 202 143 … … 244 185 } 245 186 246 // / returns T if the given declaration is: (*?=?)(T *, T) for some T (return not checked, but maybe should be), NULL otherwise247 ReferenceToType *isAssignment( DeclarationWithType *decl) {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 189 if ( decl->get_name() == "?=?" ) { 249 if ( FunctionType *funType = getFunctionType( decl->get_type() ) ) { 250 if ( funType->get_parameters().size() == 2 ) { 251 if ( PointerType *pointer = dynamic_cast< PointerType *>( funType->get_parameters().front()->get_type() ) ) { 252 if ( ReferenceToType *refType = dynamic_cast< ReferenceToType *>( pointer->get_base() ) ) { 253 if ( ReferenceToType *refType2 = dynamic_cast< ReferenceToType *>( funType->get_parameters().back()->get_type() ) ) { 254 if ( refType->get_name() == refType2->get_name() ) { 255 return refType; 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 256 200 } // if 257 201 } // if … … 261 205 } // if 262 206 } // if 263 return 0;207 return false; 264 208 } 265 209 … … 270 214 for ( std::list< DeclarationWithType *>::const_iterator assert = (*i)->get_assertions().begin(); assert != (*i)->get_assertions().end(); ++assert ) { 271 215 std::string typeName; 272 if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( isAssignment( *assert )) ) {273 assignOps[ type Inst->get_name()] = *assert;216 if ( checkAssignment( *assert, typeName ) ) { 217 assignOps[ typeName ] = *assert; 274 218 } // if 275 219 } // for … … 278 222 279 223 DeclarationWithType *Pass1::mutate( FunctionDecl *functionDecl ) { 280 // if this is a polymorphic assignment function, put it in the map for this scope281 if ( ReferenceToType *refType = isAssignment( functionDecl ) ) {282 if ( ! dynamic_cast< TypeInstType* >( refType ) ) {283 scopedAssignOps.insert( refType->get_name(), functionDecl );284 }285 }286 287 224 if ( functionDecl->get_statements() ) { // empty routine body ? 288 225 doBeginScope(); … … 294 231 // process polymorphic return value 295 232 retval = 0; 296 if ( isPolyRet( functionDecl->get_functionType() ) && functionDecl->get_linkage() == LinkageSpec::Cforall ) { 233 std::string typeName; 234 if ( isPolyRet( functionDecl->get_functionType(), typeName ) && functionDecl->get_linkage() == LinkageSpec::Cforall ) { 297 235 retval = functionDecl->get_functionType()->get_returnVals().front(); 298 236 … … 318 256 findFunction( (*arg)->get_type(), functions, scopeTyVars, needsAdapter ); 319 257 } // for 320 321 258 AdapterMap & adapters = Pass1::adapters.top(); 322 259 for ( std::list< FunctionType *>::iterator funType = functions.begin(); funType != functions.end(); ++funType ) { … … 369 306 } 370 307 371 Expression *Pass1::makeOffsetArray( StructInstType *ty ) {372 // make a new temporary array373 Type *offsetType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );374 ObjectDecl *arrayTemp = makeTemporary( new PointerType( Type::Qualifiers(), offsetType ) );375 376 // build initializer list for temporary377 std::list< Initializer* > inits;378 StructDecl *tyBase = ty->get_baseStruct();379 for ( std::list< Declaration* >::const_iterator member = tyBase->get_members().begin(); member != tyBase->get_members().end(); ++member ) {380 DeclarationWithType *memberDecl;381 if ( DeclarationWithType *origMember = dynamic_cast< DeclarationWithType* >( *member ) ) {382 memberDecl = origMember->clone();383 } else {384 memberDecl = new ObjectDecl( (*member)->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, offsetType->clone(), 0 );385 }386 inits.push_back( new SingleInit( new OffsetofExpr( ty->clone(), memberDecl ) ) );387 }388 arrayTemp->set_init( new ListInit( inits ) );389 390 // return variable pointing to temporary391 return new VariableExpr( arrayTemp );392 }393 394 308 void Pass1::passTypeVars( ApplicationExpr *appExpr, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars ) { 395 309 // pass size/align for type variables … … 411 325 412 326 // add size/align for generic types to parameter list 327 //assert( ! appExpr->get_function()->get_results().empty() ); 413 328 if ( appExpr->get_function()->get_results().empty() ) return; 414 329 FunctionType *funcType = getFunctionType( appExpr->get_function()->get_results().front() ); … … 430 345 arg = appExpr->get_args().insert( arg, new AlignofExpr( argType->clone() ) ); 431 346 arg++; 432 if ( dynamic_cast< StructInstType* >( parmType ) ) {433 if ( StructInstType *argStructType = dynamic_cast< StructInstType* >( argType ) ) {434 arg = appExpr->get_args().insert( arg, makeOffsetArray( argStructType ) );435 arg++;436 } else {437 throw SemanticError( "Cannot pass non-struct type for generic struct" );438 }439 }440 347 441 348 seenTypes.insert( sizeName ); … … 479 386 } 480 387 481 void Pass1::replaceParametersWithConcrete( ApplicationExpr *appExpr, std::list< Expression* >& params ) { 482 for ( std::list< Expression* >::iterator param = params.begin(); param != params.end(); ++param ) { 483 TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param ); 484 assert(paramType && "Aggregate parameters should be type expressions"); 485 paramType->set_type( replaceWithConcrete( appExpr, paramType->get_type(), false ) ); 486 } 487 } 488 489 Type *Pass1::replaceWithConcrete( ApplicationExpr *appExpr, Type *type, bool doClone ) { 490 if ( TypeInstType *typeInst = dynamic_cast< TypeInstType * >( type ) ) { 491 Type *concrete = env->lookup( typeInst->get_name() ); 492 if ( concrete == 0 ) { 493 throw SemanticError( "Unbound type variable " + typeInst->get_name() + " in ", appExpr ); 494 } // if 495 return concrete; 496 } else if ( StructInstType *structType = dynamic_cast< StructInstType* >( type ) ) { 497 if ( doClone ) { 498 structType = structType->clone(); 499 } 500 replaceParametersWithConcrete( appExpr, structType->get_parameters() ); 501 return structType; 502 } else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( type ) ) { 503 if ( doClone ) { 504 unionType = unionType->clone(); 505 } 506 replaceParametersWithConcrete( appExpr, unionType->get_parameters() ); 507 return unionType; 508 } 509 return type; 510 } 511 512 Expression *Pass1::addPolyRetParam( ApplicationExpr *appExpr, FunctionType *function, ReferenceToType *polyType, std::list< Expression *>::iterator &arg ) { 388 Expression *Pass1::addPolyRetParam( ApplicationExpr *appExpr, FunctionType *function, std::string typeName, std::list< Expression *>::iterator &arg ) { 389 ResolvExpr::EqvClass eqvClass; 513 390 assert( env ); 514 Type *concrete = replaceWithConcrete( appExpr, polyType ); 391 Type *concrete = env->lookup( typeName ); 392 if ( concrete == 0 ) { 393 throw SemanticError( "Unbound type variable " + typeName + " in ", appExpr ); 394 } // if 515 395 return addRetParam( appExpr, function, concrete, arg ); 516 396 } … … 612 492 assert( arg ); 613 493 if ( isPolyType( realParam->get_type(), tyVars ) ) { 494 // if ( dynamic_cast< PointerType *>( arg->get_type() ) ) { 495 // return new CastExpr( new VariableExpr( param ), arg->get_type()->clone() ); 496 // } else { 614 497 if ( dynamic_cast<TypeInstType *>(arg->get_type()) == NULL ) { 615 498 UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) ); … … 618 501 return deref; 619 502 } // if 503 // } 620 504 } // if 621 505 return new VariableExpr( param ); … … 907 791 std::list< Expression *>::iterator paramBegin = appExpr->get_args().begin(); 908 792 909 if ( ReferenceToType *polyType = isPolyRet( function ) ) { 910 ret = addPolyRetParam( appExpr, function, polyType, arg ); 793 std::string typeName; 794 if ( isPolyRet( function, typeName ) ) { 795 ret = addPolyRetParam( appExpr, function, typeName, arg ); 911 796 } else if ( needsAdapter( function, scopeTyVars ) ) { 912 797 // std::cerr << "needs adapter: "; … … 995 880 delete castExpr; 996 881 } //while 997 998 // find assignment operator for (polymorphic) return type 999 DeclarationWithType *assignDecl = 0; 1000 if ( TypeInstType *typeInst = dynamic_cast< TypeInstType *>( retval->get_type() ) ) { 1001 std::map< std::string, DeclarationWithType *>::const_iterator assignIter = assignOps.find( typeInst->get_name() ); 1002 if ( assignIter == assignOps.end() ) { 1003 throw SemanticError( "Attempt to return dtype or ftype object in ", returnStmt->get_expr() ); 1004 } // if 1005 assignDecl = assignIter->second; 1006 } else if ( ReferenceToType *refType = dynamic_cast< ReferenceToType *>( retval->get_type() ) ) { 1007 ScopedMap< std::string, DeclarationWithType *>::const_iterator assignIter = scopedAssignOps.find( refType->get_name() ); 1008 if ( assignIter == scopedAssignOps.end() ) { 1009 throw SemanticError( "Attempt to return dtype or ftype generic object in ", returnStmt->get_expr() ); 1010 } 1011 DeclarationWithType *functionDecl = assignIter->second; 1012 // line below cloned from FixFunction.cc 1013 assignDecl = new ObjectDecl( functionDecl->get_name(), functionDecl->get_storageClass(), functionDecl->get_linkage(), 0, 1014 new PointerType( Type::Qualifiers(), functionDecl->get_type()->clone() ), 0 ); 1015 assignDecl->set_mangleName( functionDecl->get_mangleName() ); 1016 } 1017 assert( assignDecl ); 1018 1019 // replace return statement with appropriate assignment to out parameter 1020 ApplicationExpr *assignExpr = new ApplicationExpr( new VariableExpr( assignDecl ) ); 882 TypeInstType *typeInst = dynamic_cast< TypeInstType *>( retval->get_type() ); 883 assert( typeInst ); 884 std::map< std::string, DeclarationWithType *>::const_iterator assignIter = assignOps.find( typeInst->get_name() ); 885 if ( assignIter == assignOps.end() ) { 886 throw SemanticError( "Attempt to return dtype or ftype object in ", returnStmt->get_expr() ); 887 } // if 888 ApplicationExpr *assignExpr = new ApplicationExpr( new VariableExpr( assignIter->second ) ); 1021 889 Expression *retParm = new NameExpr( retval->get_name() ); 1022 890 retParm->get_results().push_back( new PointerType( Type::Qualifiers(), retval->get_type()->clone() ) ); … … 1059 927 // push a copy of the current map 1060 928 adapters.push(adapters.top()); 1061 scopedAssignOps.beginScope();1062 929 } 1063 930 1064 931 void Pass1::doEndScope() { 1065 932 adapters.pop(); 1066 scopedAssignOps.endScope();1067 933 } 1068 934 … … 1132 998 1133 999 // move polymorphic return type to parameter list 1134 if ( isPolyRet( funcType ) ) { 1000 std::string typeName; 1001 if ( isPolyRet( funcType, typeName ) ) { 1135 1002 DeclarationWithType *ret = funcType->get_returnVals().front(); 1136 1003 ret->set_type( new PointerType( Type::Qualifiers(), ret->get_type() ) ); … … 1143 1010 std::list< DeclarationWithType *> inferredParams; 1144 1011 ObjectDecl newObj( "", DeclarationNode::NoStorageClass, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), 0 ); 1145 ObjectDecl newPtr( "", DeclarationNode::NoStorageClass, LinkageSpec::C, 0,1146 new PointerType( Type::Qualifiers(), new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) ), 0 );1147 1012 // ObjectDecl *newFunPtr = new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), new FunctionType( Type::Qualifiers(), true ) ), 0 ); 1148 1013 for ( std::list< TypeDecl *>::const_iterator tyParm = funcType->get_forall().begin(); tyParm != funcType->get_forall().end(); ++tyParm ) { … … 1171 1036 1172 1037 // add size/align for generic types to parameter list 1173 std::set< std::string > seenTypes; // sizeofName for generic types we've seen1038 std::set< std::string > seenTypes; //< sizeofName for generic types we've seen 1174 1039 for ( std::list< DeclarationWithType* >::const_iterator fnParm = last; fnParm != funcType->get_parameters().end(); ++fnParm ) { 1175 1040 Type *parmType = (*fnParm)->get_type(); … … 1178 1043 if ( seenTypes.count( sizeName ) ) continue; 1179 1044 1180 ObjectDecl *sizeParm, *alignParm , *offsetParm;1045 ObjectDecl *sizeParm, *alignParm; 1181 1046 sizeParm = newObj.clone(); 1182 1047 sizeParm->set_name( sizeName ); … … 1188 1053 last = funcType->get_parameters().insert( last, alignParm ); 1189 1054 ++last; 1190 1191 if ( dynamic_cast< StructInstType* >( parmType ) ) {1192 offsetParm = newPtr.clone();1193 offsetParm->set_name( offsetofName( parmType ) );1194 last = funcType->get_parameters().insert( last, offsetParm );1195 ++last;1196 }1197 1055 1198 1056 seenTypes.insert( sizeName ); … … 1208 1066 scopeTyVars = oldtyVars; 1209 1067 return funcType; 1210 }1211 1212 ////////////////////////////////////////// MemberExprFixer ////////////////////////////////////////////////////1213 1214 template< typename DeclClass >1215 DeclClass * MemberExprFixer::handleDecl( DeclClass *decl, Type *type ) {1216 TyVarMap oldtyVars = scopeTyVars;1217 makeTyVarMap( type, scopeTyVars );1218 1219 DeclClass *ret = static_cast< DeclClass *>( Mutator::mutate( decl ) );1220 1221 scopeTyVars = oldtyVars;1222 return ret;1223 }1224 1225 ObjectDecl * MemberExprFixer::mutate( ObjectDecl *objectDecl ) {1226 return handleDecl( objectDecl, objectDecl->get_type() );1227 }1228 1229 DeclarationWithType * MemberExprFixer::mutate( FunctionDecl *functionDecl ) {1230 return handleDecl( functionDecl, functionDecl->get_functionType() );1231 }1232 1233 TypedefDecl * MemberExprFixer::mutate( TypedefDecl *typedefDecl ) {1234 return handleDecl( typedefDecl, typedefDecl->get_base() );1235 }1236 1237 TypeDecl * MemberExprFixer::mutate( TypeDecl *typeDecl ) {1238 scopeTyVars[ typeDecl->get_name() ] = typeDecl->get_kind();1239 return Mutator::mutate( typeDecl );1240 }1241 1242 Type * MemberExprFixer::mutate( PointerType *pointerType ) {1243 TyVarMap oldtyVars = scopeTyVars;1244 makeTyVarMap( pointerType, scopeTyVars );1245 1246 Type *ret = Mutator::mutate( pointerType );1247 1248 scopeTyVars = oldtyVars;1249 return ret;1250 }1251 1252 Type * MemberExprFixer::mutate( FunctionType *functionType ) {1253 TyVarMap oldtyVars = scopeTyVars;1254 makeTyVarMap( functionType, scopeTyVars );1255 1256 Type *ret = Mutator::mutate( functionType );1257 1258 scopeTyVars = oldtyVars;1259 return ret;1260 }1261 1262 Statement *MemberExprFixer::mutate( DeclStmt *declStmt ) {1263 if ( ObjectDecl *objectDecl = dynamic_cast< ObjectDecl *>( declStmt->get_decl() ) ) {1264 if ( isPolyType( objectDecl->get_type(), scopeTyVars ) ) {1265 // change initialization of a polymorphic value object1266 // to allocate storage with alloca1267 Type *declType = objectDecl->get_type();1268 UntypedExpr *alloc = new UntypedExpr( new NameExpr( "__builtin_alloca" ) );1269 alloc->get_args().push_back( new NameExpr( sizeofName( declType ) ) );1270 1271 delete objectDecl->get_init();1272 1273 std::list<Expression*> designators;1274 objectDecl->set_init( new SingleInit( alloc, designators ) );1275 }1276 }1277 return Mutator::mutate( declStmt );1278 }1279 1280 Expression *MemberExprFixer::mutate( MemberExpr *memberExpr ) {1281 // mutate, exiting early if no longer MemberExpr1282 Expression *expr = Mutator::mutate( memberExpr );1283 memberExpr = dynamic_cast< MemberExpr* >( expr );1284 if ( ! memberExpr ) return expr;1285 1286 // get declaration for base struct, exiting early if not found1287 VariableExpr *varExpr = getBaseVar( memberExpr->get_aggregate() );1288 if ( ! varExpr ) return memberExpr;1289 ObjectDecl *objectDecl = dynamic_cast< ObjectDecl* >( varExpr->get_var() );1290 if ( ! objectDecl ) return memberExpr;1291 1292 // only mutate member expressions for polymorphic types1293 Type *objectType = hasPolyBase( objectDecl->get_type(), scopeTyVars );1294 if ( ! objectType ) return memberExpr;1295 1296 // get base aggregate for type so members can be looked up1297 AggregateDecl *memberBase = 0;1298 if ( StructInstType *structType = dynamic_cast< StructInstType* >( objectType ) ) {1299 memberBase = structType->get_baseStruct();1300 } else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( objectType ) ) {1301 memberBase = unionType->get_baseUnion();1302 } else return memberExpr;1303 1304 // look up numeric index of member in base aggregate1305 DeclarationWithType *memberDecl = memberExpr->get_member();1306 std::list< Declaration* > &baseDecls = memberBase->get_members();1307 std::list< Declaration* >::const_iterator decl = baseDecls.begin();1308 unsigned long i = 0;1309 for( ; decl != baseDecls.end(); ++decl, ++i ) {1310 if ( memberDecl->get_name() != (*decl)->get_name() ) continue;1311 1312 if ( DeclarationWithType *declWithType = dynamic_cast< DeclarationWithType* >( *decl ) ) {1313 if ( memberDecl->get_mangleName() == declWithType->get_mangleName() ) break;1314 else continue;1315 } else break;1316 }1317 if ( decl == baseDecls.end() ) return memberExpr;1318 1319 // replace member expression with dereference of pointer offset1320 std::stringstream offset_namer;1321 offset_namer << i;1322 ConstantExpr *fieldIndex = new ConstantExpr( Constant( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), offset_namer.str() ) );1323 UntypedExpr *fieldOffset = new UntypedExpr( new NameExpr( "?[?]" ) );1324 fieldOffset->get_args().push_back( new NameExpr( offsetofName( objectType ) ) );1325 fieldOffset->get_args().push_back( fieldIndex );1326 UntypedExpr *fieldLoc = new UntypedExpr( new NameExpr( "?+?" ) );1327 fieldLoc->get_args().push_back( memberExpr->get_aggregate() );1328 fieldLoc->get_args().push_back( fieldOffset );1329 UntypedExpr *ret = new UntypedExpr( new NameExpr( "*?" ) );1330 ret->get_args().push_back( fieldLoc );1331 1332 memberExpr->set_aggregate( 0 );1333 delete memberExpr;1334 return ret;1335 1068 } 1336 1069 … … 1393 1126 return ret; 1394 1127 } 1128 1129 Statement *Pass3::mutate( DeclStmt *declStmt ) { 1130 if ( ObjectDecl *objectDecl = dynamic_cast< ObjectDecl *>( declStmt->get_decl() ) ) { 1131 if ( isPolyType( objectDecl->get_type(), scopeTyVars ) ) { 1132 // change initialization of a polymorphic value object 1133 // to allocate storage with alloca 1134 Type *declType = objectDecl->get_type(); 1135 UntypedExpr *alloc = new UntypedExpr( new NameExpr( "__builtin_alloca" ) ); 1136 alloc->get_args().push_back( new NameExpr( sizeofName( declType ) ) ); 1137 1138 delete objectDecl->get_init(); 1139 1140 std::list<Expression*> designators; 1141 objectDecl->set_init( new SingleInit( alloc, designators ) ); 1142 } 1143 } 1144 return Mutator::mutate( declStmt ); 1145 } 1395 1146 } // anonymous namespace 1396 1147 } // namespace GenPoly
Note:
See TracChangeset
for help on using the changeset viewer.