Changes in src/GenPoly/Box.cc [aa19ccf:4067aa8]
- File:
-
- 1 edited
-
src/GenPoly/Box.cc (modified) (48 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/GenPoly/Box.cc
raa19ccf r4067aa8 14 14 // 15 15 16 #include <algorithm>17 #include <iterator>18 #include <list>19 #include <map>20 16 #include <set> 21 17 #include <stack> 22 18 #include <string> 23 #include < utility>24 #include < vector>19 #include <iterator> 20 #include <algorithm> 25 21 #include <cassert> 26 22 27 23 #include "Box.h" 28 #include " DeclMutator.h"24 #include "InstantiateGeneric.h" 29 25 #include "PolyMutator.h" 30 26 #include "FindFunction.h" 31 #include "ScopedMap.h"32 #include "ScopedSet.h"33 27 #include "ScrubTyVars.h" 34 28 … … 36 30 37 31 #include "SynTree/Constant.h" 38 #include "SynTree/ Declaration.h"32 #include "SynTree/Type.h" 39 33 #include "SynTree/Expression.h" 40 34 #include "SynTree/Initializer.h" 35 #include "SynTree/Statement.h" 41 36 #include "SynTree/Mutator.h" 42 #include "SynTree/Statement.h"43 #include "SynTree/Type.h"44 #include "SynTree/TypeSubstitution.h"45 37 46 38 #include "ResolvExpr/TypeEnvironment.h" … … 48 40 #include "ResolvExpr/typeops.h" 49 41 50 #include "SymTab/Indexer.h"51 42 #include "SymTab/Mangler.h" 52 43 … … 63 54 FunctionType *makeAdapterType( FunctionType *adaptee, const TyVarMap &tyVars ); 64 55 65 /// Abstracts type equality for a list of parameter types66 struct TypeList {67 TypeList() : params() {}68 TypeList( const std::list< Type* > &_params ) : params() { cloneAll(_params, params); }69 TypeList( std::list< Type* > &&_params ) : params( _params ) {}70 71 TypeList( const TypeList &that ) : params() { cloneAll(that.params, params); }72 TypeList( TypeList &&that ) : params( std::move( that.params ) ) {}73 74 /// Extracts types from a list of TypeExpr*75 TypeList( const std::list< TypeExpr* >& _params ) : params() {76 for ( std::list< TypeExpr* >::const_iterator param = _params.begin(); param != _params.end(); ++param ) {77 params.push_back( (*param)->get_type()->clone() );78 }79 }80 81 TypeList& operator= ( const TypeList &that ) {82 deleteAll( params );83 84 params.clear();85 cloneAll( that.params, params );86 87 return *this;88 }89 90 TypeList& operator= ( TypeList &&that ) {91 deleteAll( params );92 93 params = std::move( that.params );94 95 return *this;96 }97 98 ~TypeList() { deleteAll( params ); }99 100 bool operator== ( const TypeList& that ) const {101 if ( params.size() != that.params.size() ) return false;102 103 SymTab::Indexer dummy;104 for ( std::list< Type* >::const_iterator it = params.begin(), jt = that.params.begin(); it != params.end(); ++it, ++jt ) {105 if ( ! ResolvExpr::typesCompatible( *it, *jt, dummy ) ) return false;106 }107 return true;108 }109 110 std::list< Type* > params; ///< Instantiation parameters111 };112 113 /// Maps a key and a TypeList to the some value, accounting for scope114 template< typename Key, typename Value >115 class InstantiationMap {116 /// Wraps value for a specific (Key, TypeList) combination117 typedef std::pair< TypeList, Value* > Instantiation;118 /// List of TypeLists paired with their appropriate values119 typedef std::vector< Instantiation > ValueList;120 /// Underlying map type; maps keys to a linear list of corresponding TypeLists and values121 typedef ScopedMap< Key*, ValueList > InnerMap;122 123 InnerMap instantiations; ///< instantiations124 125 public:126 /// Starts a new scope127 void beginScope() { instantiations.beginScope(); }128 129 /// Ends a scope130 void endScope() { instantiations.endScope(); }131 132 /// Gets the value for the (key, typeList) pair, returns NULL on none such.133 Value *lookup( Key *key, const std::list< TypeExpr* >& params ) const {134 TypeList typeList( params );135 136 // scan scopes for matches to the key137 for ( typename InnerMap::const_iterator insts = instantiations.find( key ); insts != instantiations.end(); insts = instantiations.findNext( insts, key ) ) {138 for ( typename ValueList::const_reverse_iterator inst = insts->second.rbegin(); inst != insts->second.rend(); ++inst ) {139 if ( inst->first == typeList ) return inst->second;140 }141 }142 // no matching instantiations found143 return 0;144 }145 146 /// Adds a value for a (key, typeList) pair to the current scope147 void insert( Key *key, const std::list< TypeExpr* > ¶ms, Value *value ) {148 instantiations[ key ].push_back( Instantiation( TypeList( params ), value ) );149 }150 };151 152 /// Adds layout-generation functions to polymorphic types153 class LayoutFunctionBuilder : public DeclMutator {154 unsigned int functionNesting; // current level of nested functions155 public:156 LayoutFunctionBuilder() : functionNesting( 0 ) {}157 158 virtual DeclarationWithType *mutate( FunctionDecl *functionDecl );159 virtual Declaration *mutate( StructDecl *structDecl );160 virtual Declaration *mutate( UnionDecl *unionDecl );161 };162 163 56 /// Replaces polymorphic return types with out-parameters, replaces calls to polymorphic functions with adapter calls as needed, and adds appropriate type variables to the function call 164 57 class Pass1 : public PolyMutator { … … 179 72 virtual void doEndScope(); 180 73 private: 74 /// Makes a new temporary array holding the offsets of the fields of `type`, and returns a new variable expression referencing it 75 Expression *makeOffsetArray( StructInstType *type ); 181 76 /// Pass the extra type parameters from polymorphic generic arguments or return types into a function application 182 77 void passArgTypeVars( ApplicationExpr *appExpr, Type *parmType, Type *argBaseType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars, std::set< std::string > &seenTypes ); … … 205 100 ObjectDecl *makeTemporary( Type *type ); 206 101 207 ScopedMap< std::string, DeclarationWithType *> assignOps; ///< Currently known type variable assignment operators208 ResolvExpr::TypeMap< DeclarationWithType > scopedAssignOps; ///< Currently known assignment operators209 ScopedMap< std::string, DeclarationWithType* > adapters; ///< Set of adapter functions in the current scope210 102 typedef std::map< std::string, DeclarationWithType *> AdapterMap; 103 std::map< std::string, DeclarationWithType *> assignOps; 104 ResolvExpr::TypeMap< DeclarationWithType > scopedAssignOps; 105 std::stack< AdapterMap > adapters; 211 106 DeclarationWithType *retval; 212 107 bool useRetval; … … 214 109 }; 215 110 216 /// * Moves polymorphic returns in function types to pointer-type parameters 217 /// * adds type size and assertion parameters to parameter lists 111 /// Moves polymorphic returns in function types to pointer-type parameters, adds type size and assertion parameters to parameter lists as well 218 112 class Pass2 : public PolyMutator { 219 113 public: … … 226 120 virtual Type *mutate( PointerType *pointerType ); 227 121 virtual Type *mutate( FunctionType *funcType ); 228 229 122 private: 230 123 void addAdapters( FunctionType *functionType ); … … 233 126 }; 234 127 235 /// Mutator pass that replaces concrete instantiations of generic types with actual struct declarations, scoped appropriately 236 class GenericInstantiator : public DeclMutator { 237 /// Map of (generic type, parameter list) pairs to concrete type instantiations 238 InstantiationMap< AggregateDecl, AggregateDecl > instantiations; 239 /// Namer for concrete types 240 UniqueName typeNamer; 241 242 public: 243 GenericInstantiator() : DeclMutator(), instantiations(), typeNamer("_conc_") {} 244 245 virtual Type* mutate( StructInstType *inst ); 246 virtual Type* mutate( UnionInstType *inst ); 247 248 // virtual Expression* mutate( MemberExpr *memberExpr ); 249 250 virtual void doBeginScope(); 251 virtual void doEndScope(); 252 private: 253 /// Wrap instantiation lookup for structs 254 StructDecl* lookup( StructInstType *inst, const std::list< TypeExpr* > &typeSubs ) { return (StructDecl*)instantiations.lookup( inst->get_baseStruct(), typeSubs ); } 255 /// Wrap instantiation lookup for unions 256 UnionDecl* lookup( UnionInstType *inst, const std::list< TypeExpr* > &typeSubs ) { return (UnionDecl*)instantiations.lookup( inst->get_baseUnion(), typeSubs ); } 257 /// Wrap instantiation insertion for structs 258 void insert( StructInstType *inst, const std::list< TypeExpr* > &typeSubs, StructDecl *decl ) { instantiations.insert( inst->get_baseStruct(), typeSubs, decl ); } 259 /// Wrap instantiation insertion for unions 260 void insert( UnionInstType *inst, const std::list< TypeExpr* > &typeSubs, UnionDecl *decl ) { instantiations.insert( inst->get_baseUnion(), typeSubs, decl ); } 261 }; 262 263 /// Replaces member and size/align/offsetof expressions on polymorphic generic types with calculated expressions. 264 /// * Replaces member expressions for polymorphic types with calculated add-field-offset-and-dereference 265 /// * Calculates polymorphic offsetof expressions from offset array 266 /// * Inserts dynamic calculation of polymorphic type layouts where needed 267 class PolyGenericCalculator : public PolyMutator { 268 public: 128 /// Replaces member expressions for polymorphic types with calculated add-field-offset-and-dereference; 129 /// also fixes offsetof expressions. 130 class MemberExprFixer : public PolyMutator { 131 public: 269 132 template< typename DeclClass > 270 133 DeclClass *handleDecl( DeclClass *decl, Type *type ); … … 277 140 virtual Type *mutate( FunctionType *funcType ); 278 141 virtual Expression *mutate( MemberExpr *memberExpr ); 279 virtual Expression *mutate( SizeofExpr *sizeofExpr );280 virtual Expression *mutate( AlignofExpr *alignofExpr );281 142 virtual Expression *mutate( OffsetofExpr *offsetofExpr ); 282 virtual Expression *mutate( OffsetPackExpr *offsetPackExpr );283 284 virtual void doBeginScope();285 virtual void doEndScope();286 287 private:288 /// Makes a new variable in the current scope with the given name, type & optional initializer289 ObjectDecl *makeVar( const std::string &name, Type *type, Initializer *init = 0 );290 /// returns true if the type has a dynamic layout; such a layout will be stored in appropriately-named local variables when the function returns291 bool findGeneric( Type *ty );292 /// adds type parameters to the layout call; will generate the appropriate parameters if needed293 void addOtypeParamsToLayoutCall( UntypedExpr *layoutCall, const std::list< Type* > &otypeParams );294 295 /// Enters a new scope for type-variables, adding the type variables from ty296 void beginTypeScope( Type *ty );297 /// Exits the type-variable scope298 void endTypeScope();299 300 ScopedSet< std::string > knownLayouts; ///< Set of generic type layouts known in the current scope, indexed by sizeofName301 ScopedSet< std::string > knownOffsets; ///< Set of non-generic types for which the offset array exists in the current scope, indexed by offsetofName302 143 }; 303 144 … … 318 159 } // anonymous namespace 319 160 161 void printAllNotBuiltin( const std::list< Declaration *>& translationUnit, std::ostream &os ) { 162 for ( std::list< Declaration *>::const_iterator i = translationUnit.begin(); i != translationUnit.end(); ++i ) { 163 if ( ! LinkageSpec::isBuiltin( (*i)->get_linkage() ) ) { 164 (*i)->print( os ); 165 os << std::endl; 166 } // if 167 } // for 168 } 169 320 170 /// version of mutateAll with special handling for translation unit so you can check the end of the prelude when debugging 321 171 template< typename MutatorType > … … 345 195 346 196 void box( std::list< Declaration *>& translationUnit ) { 347 LayoutFunctionBuilder layoutBuilder;348 197 Pass1 pass1; 349 198 Pass2 pass2; 350 GenericInstantiator instantiator; 351 PolyGenericCalculator polyCalculator; 199 MemberExprFixer memberFixer; 352 200 Pass3 pass3; 353 354 layoutBuilder.mutateDeclarationList( translationUnit );355 201 mutateTranslationUnit/*All*/( translationUnit, pass1 ); 356 202 mutateTranslationUnit/*All*/( translationUnit, pass2 ); 357 instantiat or.mutateDeclarationList( translationUnit );358 mutateTranslationUnit/*All*/( translationUnit, polyCalculator );203 instantiateGeneric( translationUnit ); 204 mutateTranslationUnit/*All*/( translationUnit, memberFixer ); 359 205 mutateTranslationUnit/*All*/( translationUnit, pass3 ); 360 206 } 361 207 362 ////////////////////////////////// LayoutFunctionBuilder ////////////////////////////////////////////363 364 DeclarationWithType *LayoutFunctionBuilder::mutate( FunctionDecl *functionDecl ) {365 functionDecl->set_functionType( maybeMutate( functionDecl->get_functionType(), *this ) );366 mutateAll( functionDecl->get_oldDecls(), *this );367 ++functionNesting;368 functionDecl->set_statements( maybeMutate( functionDecl->get_statements(), *this ) );369 --functionNesting;370 return functionDecl;371 }372 373 /// Get a list of type declarations that will affect a layout function374 std::list< TypeDecl* > takeOtypeOnly( std::list< TypeDecl* > &decls ) {375 std::list< TypeDecl * > otypeDecls;376 377 for ( std::list< TypeDecl* >::const_iterator decl = decls.begin(); decl != decls.end(); ++decl ) {378 if ( (*decl)->get_kind() == TypeDecl::Any ) {379 otypeDecls.push_back( *decl );380 }381 }382 383 return otypeDecls;384 }385 386 /// Adds parameters for otype layout to a function type387 void addOtypeParams( FunctionType *layoutFnType, std::list< TypeDecl* > &otypeParams ) {388 BasicType sizeAlignType( Type::Qualifiers(), BasicType::LongUnsignedInt );389 390 for ( std::list< TypeDecl* >::const_iterator param = otypeParams.begin(); param != otypeParams.end(); ++param ) {391 TypeInstType paramType( Type::Qualifiers(), (*param)->get_name(), *param );392 std::string paramName = mangleType( ¶mType );393 layoutFnType->get_parameters().push_back( new ObjectDecl( sizeofName( paramName ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignType.clone(), 0 ) );394 layoutFnType->get_parameters().push_back( new ObjectDecl( alignofName( paramName ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignType.clone(), 0 ) );395 }396 }397 398 /// Builds a layout function declaration399 FunctionDecl *buildLayoutFunctionDecl( AggregateDecl *typeDecl, unsigned int functionNesting, FunctionType *layoutFnType ) {400 // Routines at global scope marked "static" to prevent multiple definitions is separate translation units401 // because each unit generates copies of the default routines for each aggregate.402 FunctionDecl *layoutDecl = new FunctionDecl(403 layoutofName( typeDecl ), functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, layoutFnType, new CompoundStmt( noLabels ), true, false );404 layoutDecl->fixUniqueId();405 return layoutDecl;406 }407 408 /// Makes a unary operation409 Expression *makeOp( const std::string &name, Expression *arg ) {410 UntypedExpr *expr = new UntypedExpr( new NameExpr( name ) );411 expr->get_args().push_back( arg );412 return expr;413 }414 415 /// Makes a binary operation416 Expression *makeOp( const std::string &name, Expression *lhs, Expression *rhs ) {417 UntypedExpr *expr = new UntypedExpr( new NameExpr( name ) );418 expr->get_args().push_back( lhs );419 expr->get_args().push_back( rhs );420 return expr;421 }422 423 /// Returns the dereference of a local pointer variable424 Expression *derefVar( ObjectDecl *var ) {425 return makeOp( "*?", new VariableExpr( var ) );426 }427 428 /// makes an if-statement with a single-expression if-block and no then block429 Statement *makeCond( Expression *cond, Expression *ifPart ) {430 return new IfStmt( noLabels, cond, new ExprStmt( noLabels, ifPart ), 0 );431 }432 433 /// makes a statement that assigns rhs to lhs if lhs < rhs434 Statement *makeAssignMax( Expression *lhs, Expression *rhs ) {435 return makeCond( makeOp( "?<?", lhs, rhs ), makeOp( "?=?", lhs->clone(), rhs->clone() ) );436 }437 438 /// makes a statement that aligns lhs to rhs (rhs should be an integer power of two)439 Statement *makeAlignTo( Expression *lhs, Expression *rhs ) {440 // check that the lhs is zeroed out to the level of rhs441 Expression *ifCond = makeOp( "?&?", lhs, makeOp( "?-?", rhs, new ConstantExpr( Constant( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), "1" ) ) ) );442 // if not aligned, increment to alignment443 Expression *ifExpr = makeOp( "?+=?", lhs->clone(), makeOp( "?-?", rhs->clone(), ifCond->clone() ) );444 return makeCond( ifCond, ifExpr );445 }446 447 /// adds an expression to a compound statement448 void addExpr( CompoundStmt *stmts, Expression *expr ) {449 stmts->get_kids().push_back( new ExprStmt( noLabels, expr ) );450 }451 452 /// adds a statement to a compound statement453 void addStmt( CompoundStmt *stmts, Statement *stmt ) {454 stmts->get_kids().push_back( stmt );455 }456 457 Declaration *LayoutFunctionBuilder::mutate( StructDecl *structDecl ) {458 // do not generate layout function for "empty" tag structs459 if ( structDecl->get_members().empty() ) return structDecl;460 461 // get parameters that can change layout, exiting early if none462 std::list< TypeDecl* > otypeParams = takeOtypeOnly( structDecl->get_parameters() );463 if ( otypeParams.empty() ) return structDecl;464 465 // build layout function signature466 FunctionType *layoutFnType = new FunctionType( Type::Qualifiers(), false );467 BasicType *sizeAlignType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );468 PointerType *sizeAlignOutType = new PointerType( Type::Qualifiers(), sizeAlignType );469 470 ObjectDecl *sizeParam = new ObjectDecl( sizeofName( structDecl->get_name() ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType, 0 );471 layoutFnType->get_parameters().push_back( sizeParam );472 ObjectDecl *alignParam = new ObjectDecl( alignofName( structDecl->get_name() ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType->clone(), 0 );473 layoutFnType->get_parameters().push_back( alignParam );474 ObjectDecl *offsetParam = new ObjectDecl( offsetofName( structDecl->get_name() ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType->clone(), 0 );475 layoutFnType->get_parameters().push_back( offsetParam );476 addOtypeParams( layoutFnType, otypeParams );477 478 // build function decl479 FunctionDecl *layoutDecl = buildLayoutFunctionDecl( structDecl, functionNesting, layoutFnType );480 481 // calculate struct layout in function body482 483 // initialize size and alignment to 0 and 1 (will have at least one member to re-edit size484 addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( sizeParam ), new ConstantExpr( Constant( sizeAlignType->clone(), "0" ) ) ) );485 addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( alignParam ), new ConstantExpr( Constant( sizeAlignType->clone(), "1" ) ) ) );486 unsigned long n_members = 0;487 bool firstMember = true;488 for ( std::list< Declaration* >::const_iterator member = structDecl->get_members().begin(); member != structDecl->get_members().end(); ++member ) {489 DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( *member );490 assert( dwt );491 Type *memberType = dwt->get_type();492 493 if ( firstMember ) {494 firstMember = false;495 } else {496 // make sure all members after the first (automatically aligned at 0) are properly padded for alignment497 addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), new AlignofExpr( memberType->clone() ) ) );498 }499 500 // place current size in the current offset index501 addExpr( layoutDecl->get_statements(), makeOp( "?=?", makeOp( "?[?]", new VariableExpr( offsetParam ), new ConstantExpr( Constant::from( n_members ) ) ),502 derefVar( sizeParam ) ) );503 ++n_members;504 505 // add member size to current size506 addExpr( layoutDecl->get_statements(), makeOp( "?+=?", derefVar( sizeParam ), new SizeofExpr( memberType->clone() ) ) );507 508 // take max of member alignment and global alignment509 addStmt( layoutDecl->get_statements(), makeAssignMax( derefVar( alignParam ), new AlignofExpr( memberType->clone() ) ) );510 }511 // make sure the type is end-padded to a multiple of its alignment512 addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), derefVar( alignParam ) ) );513 514 addDeclarationAfter( layoutDecl );515 return structDecl;516 }517 518 Declaration *LayoutFunctionBuilder::mutate( UnionDecl *unionDecl ) {519 // do not generate layout function for "empty" tag unions520 if ( unionDecl->get_members().empty() ) return unionDecl;521 522 // get parameters that can change layout, exiting early if none523 std::list< TypeDecl* > otypeParams = takeOtypeOnly( unionDecl->get_parameters() );524 if ( otypeParams.empty() ) return unionDecl;525 526 // build layout function signature527 FunctionType *layoutFnType = new FunctionType( Type::Qualifiers(), false );528 BasicType *sizeAlignType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );529 PointerType *sizeAlignOutType = new PointerType( Type::Qualifiers(), sizeAlignType );530 531 ObjectDecl *sizeParam = new ObjectDecl( sizeofName( unionDecl->get_name() ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType, 0 );532 layoutFnType->get_parameters().push_back( sizeParam );533 ObjectDecl *alignParam = new ObjectDecl( alignofName( unionDecl->get_name() ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType->clone(), 0 );534 layoutFnType->get_parameters().push_back( alignParam );535 addOtypeParams( layoutFnType, otypeParams );536 537 // build function decl538 FunctionDecl *layoutDecl = buildLayoutFunctionDecl( unionDecl, functionNesting, layoutFnType );539 540 // calculate union layout in function body541 addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( sizeParam ), new ConstantExpr( Constant( sizeAlignType->clone(), "1" ) ) ) );542 addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( alignParam ), new ConstantExpr( Constant( sizeAlignType->clone(), "1" ) ) ) );543 for ( std::list< Declaration* >::const_iterator member = unionDecl->get_members().begin(); member != unionDecl->get_members().end(); ++member ) {544 DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( *member );545 assert( dwt );546 Type *memberType = dwt->get_type();547 548 // take max member size and global size549 addStmt( layoutDecl->get_statements(), makeAssignMax( derefVar( sizeParam ), new SizeofExpr( memberType->clone() ) ) );550 551 // take max of member alignment and global alignment552 addStmt( layoutDecl->get_statements(), makeAssignMax( derefVar( alignParam ), new AlignofExpr( memberType->clone() ) ) );553 }554 // make sure the type is end-padded to a multiple of its alignment555 addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), derefVar( alignParam ) ) );556 557 addDeclarationAfter( layoutDecl );558 return unionDecl;559 }560 561 208 ////////////////////////////////////////// Pass1 //////////////////////////////////////////////////// 562 209 … … 598 245 } 599 246 600 Pass1::Pass1() : useRetval( false ), tempNamer( "_temp" ) {} 247 Pass1::Pass1() : useRetval( false ), tempNamer( "_temp" ) { 248 adapters.push(AdapterMap()); 249 } 601 250 602 251 /// Returns T if the given declaration is (*?=?)(T *, T) for some TypeInstType T (return not checked, but maybe should be), NULL otherwise … … 660 309 661 310 DeclarationWithType *Pass1::mutate( FunctionDecl *functionDecl ) { 662 // if this is a assignment function, put it in the map for this scope311 // if this is a polymorphic assignment function, put it in the map for this scope 663 312 if ( Type *assignedType = isAssignment( functionDecl ) ) { 664 313 if ( ! dynamic_cast< TypeInstType* >( assignedType ) ) { … … 669 318 if ( functionDecl->get_statements() ) { // empty routine body ? 670 319 doBeginScope(); 671 scopeTyVars.beginScope();672 assignOps.beginScope();320 TyVarMap oldtyVars = scopeTyVars; 321 std::map< std::string, DeclarationWithType *> oldassignOps = assignOps; 673 322 DeclarationWithType *oldRetval = retval; 674 323 bool oldUseRetval = useRetval; … … 701 350 } // for 702 351 352 AdapterMap & adapters = Pass1::adapters.top(); 703 353 for ( std::list< FunctionType *>::iterator funType = functions.begin(); funType != functions.end(); ++funType ) { 704 354 std::string mangleName = mangleAdapterName( *funType, scopeTyVars ); … … 711 361 functionDecl->set_statements( functionDecl->get_statements()->acceptMutator( *this ) ); 712 362 713 scopeTyVars.endScope(); 714 assignOps.endScope(); 363 scopeTyVars = oldtyVars; 364 assignOps = oldassignOps; 365 // std::cerr << "end FunctionDecl: "; 366 // for ( TyVarMap::iterator i = scopeTyVars.begin(); i != scopeTyVars.end(); ++i ) { 367 // std::cerr << i->first << " "; 368 // } 369 // std::cerr << "\n"; 715 370 retval = oldRetval; 716 371 useRetval = oldUseRetval; … … 745 400 } 746 401 402 Expression *Pass1::makeOffsetArray( StructInstType *ty ) { 403 std::list< Declaration* > &baseMembers = ty->get_baseStruct()->get_members(); 404 405 // make a new temporary array 406 Type *offsetType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ); 407 std::stringstream lenGen; 408 lenGen << baseMembers.size(); 409 ConstantExpr *lenExpr = new ConstantExpr( Constant( offsetType->clone(), lenGen.str() ) ); 410 ObjectDecl *arrayTemp = makeTemporary( new ArrayType( Type::Qualifiers(), offsetType, lenExpr, false, false ) ); 411 412 // build initializer list for temporary 413 std::list< Initializer* > inits; 414 for ( std::list< Declaration* >::const_iterator member = baseMembers.begin(); member != baseMembers.end(); ++member ) { 415 DeclarationWithType *memberDecl; 416 if ( DeclarationWithType *origMember = dynamic_cast< DeclarationWithType* >( *member ) ) { 417 memberDecl = origMember->clone(); 418 } else { 419 memberDecl = new ObjectDecl( (*member)->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, offsetType->clone(), 0 ); 420 } 421 inits.push_back( new SingleInit( new OffsetofExpr( ty->clone(), memberDecl ) ) ); 422 } 423 arrayTemp->set_init( new ListInit( inits ) ); 424 425 // return variable pointing to temporary 426 return new VariableExpr( arrayTemp ); 427 } 428 747 429 void Pass1::passArgTypeVars( ApplicationExpr *appExpr, Type *parmType, Type *argBaseType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars, std::set< std::string > &seenTypes ) { 748 Type *poly Type = isPolyType( parmType, exprTyVars );749 if ( poly Type && ! dynamic_cast< TypeInstType* >( polyType ) ) {750 std::string typeName = mangleType( polyType );751 if ( seenTypes.count( typeName ) ) return;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; 752 434 753 435 arg = appExpr->get_args().insert( arg, new SizeofExpr( argBaseType->clone() ) ); … … 755 437 arg = appExpr->get_args().insert( arg, new AlignofExpr( argBaseType->clone() ) ); 756 438 arg++; 757 if ( dynamic_cast< StructInstType* >( poly Type ) ) {439 if ( dynamic_cast< StructInstType* >( polyBase ) ) { 758 440 if ( StructInstType *argBaseStructType = dynamic_cast< StructInstType* >( argBaseType ) ) { 759 // zero-length arrays are forbidden by C, so don't pass offset for empty struct 760 if ( ! argBaseStructType->get_baseStruct()->get_members().empty() ) { 761 arg = appExpr->get_args().insert( arg, new OffsetPackExpr( argBaseStructType->clone() ) ); 762 arg++; 763 } 441 arg = appExpr->get_args().insert( arg, makeOffsetArray( argBaseStructType ) ); 442 arg++; 764 443 } else { 765 444 throw SemanticError( "Cannot pass non-struct type for generic struct" ); … … 767 446 } 768 447 769 seenTypes.insert( typeName );448 seenTypes.insert( sizeName ); 770 449 } 771 450 } … … 909 588 return; 910 589 } else if ( arg->get_results().front()->get_isLvalue() ) { 911 // VariableExpr and MemberExpr are lvalues; need to check this isn't coming from the second arg of a comma expression though (not an lvalue) 912 if ( CommaExpr *commaArg = dynamic_cast< CommaExpr* >( arg ) ) { 913 commaArg->set_arg2( new AddressExpr( commaArg->get_arg2() ) ); 914 } else { 915 arg = new AddressExpr( arg ); 916 } 590 // VariableExpr and MemberExpr are lvalues 591 arg = new AddressExpr( arg ); 917 592 } else { 918 593 // use type computed in unification to declare boxed variables … … 1009 684 } // for 1010 685 } 686 687 1011 688 1012 689 FunctionDecl *Pass1::makeAdapter( FunctionType *adaptee, FunctionType *realType, const std::string &mangleName, const TyVarMap &tyVars ) { … … 1095 772 mangleName += makePolyMonoSuffix( originalFunction, exprTyVars ); 1096 773 1097 typedef ScopedMap< std::string, DeclarationWithType* >::iterator AdapterIter;1098 Adapter Iter adapter = adapters.find( mangleName );774 AdapterMap & adapters = Pass1::adapters.top(); 775 AdapterMap::iterator adapter = adapters.find( mangleName ); 1099 776 if ( adapter == adapters.end() ) { 1100 777 // adapter has not been created yet in the current scope, so define it 1101 778 FunctionDecl *newAdapter = makeAdapter( *funType, realFunction, mangleName, exprTyVars ); 1102 std::pair< AdapterIter, bool > answer = adapters.insert( std::pair< std::string, DeclarationWithType *>( mangleName, newAdapter ) ); 1103 adapter = answer.first; 779 adapter = adapters.insert( adapters.begin(), std::pair< std::string, DeclarationWithType *>( mangleName, newAdapter ) ); 1104 780 stmtsToAdd.push_back( new DeclStmt( noLabels, newAdapter ) ); 1105 781 } // if … … 1125 801 addAssign->get_args().push_back( appExpr->get_args().front() ); 1126 802 } // if 1127 addAssign->get_args().push_back( new NameExpr( sizeofName( mangleType( polyType )) ) );803 addAssign->get_args().push_back( new NameExpr( sizeofName( polyType ) ) ); 1128 804 addAssign->get_results().front() = appExpr->get_results().front()->clone(); 1129 805 if ( appExpr->get_env() ) { … … 1152 828 UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) ); 1153 829 multiply->get_args().push_back( appExpr->get_args().back() ); 1154 multiply->get_args().push_back( new SizeofExpr( baseType1->clone() ) );830 multiply->get_args().push_back( new NameExpr( sizeofName( baseType1 ) ) ); 1155 831 ret->get_args().push_back( appExpr->get_args().front() ); 1156 832 ret->get_args().push_back( multiply ); … … 1158 834 UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) ); 1159 835 multiply->get_args().push_back( appExpr->get_args().front() ); 1160 multiply->get_args().push_back( new SizeofExpr( baseType2->clone() ) );836 multiply->get_args().push_back( new NameExpr( sizeofName( baseType2 ) ) ); 1161 837 ret->get_args().push_back( multiply ); 1162 838 ret->get_args().push_back( appExpr->get_args().back() ); … … 1221 897 UntypedExpr *divide = new UntypedExpr( new NameExpr( "?/?" ) ); 1222 898 divide->get_args().push_back( appExpr ); 1223 divide->get_args().push_back( new SizeofExpr( baseType1->clone() ) );899 divide->get_args().push_back( new NameExpr( sizeofName( baseType1 ) ) ); 1224 900 divide->get_results().push_front( appExpr->get_results().front()->clone() ); 1225 901 if ( appExpr->get_env() ) { … … 1231 907 UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) ); 1232 908 multiply->get_args().push_back( appExpr->get_args().back() ); 1233 multiply->get_args().push_back( new SizeofExpr( baseType1->clone() ) );909 multiply->get_args().push_back( new NameExpr( sizeofName( baseType1 ) ) ); 1234 910 appExpr->get_args().back() = multiply; 1235 911 } else if ( baseType2 ) { 1236 912 UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) ); 1237 913 multiply->get_args().push_back( appExpr->get_args().front() ); 1238 multiply->get_args().push_back( new SizeofExpr( baseType2->clone() ) );914 multiply->get_args().push_back( new NameExpr( sizeofName( baseType2 ) ) ); 1239 915 appExpr->get_args().front() = multiply; 1240 916 } // if … … 1246 922 UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) ); 1247 923 multiply->get_args().push_back( appExpr->get_args().back() ); 1248 multiply->get_args().push_back( new SizeofExpr( baseType->clone() ) );924 multiply->get_args().push_back( new NameExpr( sizeofName( baseType ) ) ); 1249 925 appExpr->get_args().back() = multiply; 1250 926 } // if … … 1283 959 std::list< Expression *>::iterator paramBegin = appExpr->get_args().begin(); 1284 960 1285 TyVarMap exprTyVars ( (TypeDecl::Kind)-1 );961 TyVarMap exprTyVars; 1286 962 makeTyVarMap( function, exprTyVars ); 1287 963 ReferenceToType *polyRetType = isPolyRet( function ); … … 1306 982 1307 983 boxParams( appExpr, function, arg, exprTyVars ); 984 1308 985 passAdapters( appExpr, function, exprTyVars ); 1309 986 … … 1385 1062 if ( TypeInstType *typeInst = dynamic_cast< TypeInstType *>( retval->get_type() ) ) { 1386 1063 // find assignment operator for type variable 1387 ScopedMap< std::string, DeclarationWithType *>::const_iterator assignIter = assignOps.find( typeInst->get_name() );1064 std::map< std::string, DeclarationWithType *>::const_iterator assignIter = assignOps.find( typeInst->get_name() ); 1388 1065 if ( assignIter == assignOps.end() ) { 1389 1066 throw SemanticError( "Attempt to return dtype or ftype object in ", returnStmt->get_expr() ); … … 1407 1084 std::list< TypeDecl* >::const_iterator forallIt = forallParams.begin(); 1408 1085 for ( ; tyIt != tyParams.end() && forallIt != forallParams.end(); ++tyIt, ++forallIt ) { 1409 // Add appropriate mapping to assignment expression environment 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" ); 1410 1093 TypeExpr *formalTypeExpr = dynamic_cast< TypeExpr* >( *tyIt ); 1411 1094 assert( formalTypeExpr && "type parameters must be type expressions" ); 1412 1095 Type *formalType = formalTypeExpr->get_type(); 1413 assignExpr->get_env()->add( (*forallIt)->get_name(), formalType ); 1414 1415 // skip types with no assign op (ftype/dtype) 1416 if ( (*forallIt)->get_kind() != TypeDecl::Any ) continue; 1417 1418 // find assignment operator for formal type 1096 assignExpr->get_env()->add( actualType->get_name(), formalType ); 1097 1419 1098 DeclarationWithType *assertAssign = 0; 1420 1099 if ( TypeInstType *formalTypeInstType = dynamic_cast< TypeInstType* >( formalType ) ) { 1421 ScopedMap< std::string, DeclarationWithType *>::const_iterator assertAssignIt = assignOps.find( formalTypeInstType->get_name() );1100 std::map< std::string, DeclarationWithType *>::const_iterator assertAssignIt = assignOps.find( formalTypeInstType->get_name() ); 1422 1101 if ( assertAssignIt == assignOps.end() ) { 1423 1102 throw SemanticError( "No assignment operation found for ", formalTypeInstType ); … … 1430 1109 } 1431 1110 } 1432 1433 // add inferred parameter for field assignment operator to assignment expression 1434 std::list< DeclarationWithType* > &asserts = (*forallIt)->get_assertions(); 1435 assert( ! asserts.empty() && "Type param needs assignment operator assertion" ); 1436 DeclarationWithType *actualDecl = asserts.front(); 1111 1112 1437 1113 assignExpr->get_inferParams()[ actualDecl->get_uniqueId() ] 1438 1114 = ParamEntry( assertAssign->get_uniqueId(), assertAssign->get_type()->clone(), actualDecl->get_type()->clone(), wrapFunctionDecl( assertAssign ) ); … … 1460 1136 1461 1137 Type * Pass1::mutate( PointerType *pointerType ) { 1462 scopeTyVars.beginScope();1138 TyVarMap oldtyVars = scopeTyVars; 1463 1139 makeTyVarMap( pointerType, scopeTyVars ); 1464 1140 1465 1141 Type *ret = Mutator::mutate( pointerType ); 1466 1142 1467 scopeTyVars .endScope();1143 scopeTyVars = oldtyVars; 1468 1144 return ret; 1469 1145 } 1470 1146 1471 1147 Type * Pass1::mutate( FunctionType *functionType ) { 1472 scopeTyVars.beginScope();1148 TyVarMap oldtyVars = scopeTyVars; 1473 1149 makeTyVarMap( functionType, scopeTyVars ); 1474 1150 1475 1151 Type *ret = Mutator::mutate( functionType ); 1476 1152 1477 scopeTyVars .endScope();1153 scopeTyVars = oldtyVars; 1478 1154 return ret; 1479 1155 } 1480 1156 1481 1157 void Pass1::doBeginScope() { 1482 adapters.beginScope(); 1158 // push a copy of the current map 1159 adapters.push(adapters.top()); 1483 1160 scopedAssignOps.beginScope(); 1484 1161 } 1485 1162 1486 1163 void Pass1::doEndScope() { 1487 adapters. endScope();1164 adapters.pop(); 1488 1165 scopedAssignOps.endScope(); 1489 1166 } … … 1540 1217 1541 1218 Type * Pass2::mutate( PointerType *pointerType ) { 1542 scopeTyVars.beginScope();1219 TyVarMap oldtyVars = scopeTyVars; 1543 1220 makeTyVarMap( pointerType, scopeTyVars ); 1544 1221 1545 1222 Type *ret = Mutator::mutate( pointerType ); 1546 1223 1547 scopeTyVars .endScope();1224 scopeTyVars = oldtyVars; 1548 1225 return ret; 1549 1226 } 1550 1227 1551 1228 Type *Pass2::mutate( FunctionType *funcType ) { 1552 scopeTyVars.beginScope();1229 TyVarMap oldtyVars = scopeTyVars; 1553 1230 makeTyVarMap( funcType, scopeTyVars ); 1554 1231 … … 1567 1244 ObjectDecl newPtr( "", DeclarationNode::NoStorageClass, LinkageSpec::C, 0, 1568 1245 new PointerType( Type::Qualifiers(), new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) ), 0 ); 1246 // ObjectDecl *newFunPtr = new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), new FunctionType( Type::Qualifiers(), true ) ), 0 ); 1569 1247 for ( std::list< TypeDecl *>::const_iterator tyParm = funcType->get_forall().begin(); tyParm != funcType->get_forall().end(); ++tyParm ) { 1570 1248 ObjectDecl *sizeParm, *alignParm; … … 1572 1250 if ( (*tyParm)->get_kind() == TypeDecl::Any ) { 1573 1251 TypeInstType parmType( Type::Qualifiers(), (*tyParm)->get_name(), *tyParm ); 1574 std::string parmName = mangleType( &parmType );1575 1252 1576 1253 sizeParm = newObj.clone(); 1577 sizeParm->set_name( sizeofName( parmName ) );1254 sizeParm->set_name( sizeofName( &parmType ) ); 1578 1255 last = funcType->get_parameters().insert( last, sizeParm ); 1579 1256 ++last; 1580 1257 1581 1258 alignParm = newObj.clone(); 1582 alignParm->set_name( alignofName( parmName ) );1259 alignParm->set_name( alignofName( &parmType ) ); 1583 1260 last = funcType->get_parameters().insert( last, alignParm ); 1584 1261 ++last; … … 1595 1272 std::set< std::string > seenTypes; // sizeofName for generic types we've seen 1596 1273 for ( std::list< DeclarationWithType* >::const_iterator fnParm = last; fnParm != funcType->get_parameters().end(); ++fnParm ) { 1597 Type *poly Type = isPolyType( (*fnParm)->get_type(), scopeTyVars );1598 if ( poly Type && ! dynamic_cast< TypeInstType* >( polyType ) ) {1599 std::string typeName = mangleType( polyType );1600 if ( seenTypes.count( typeName ) ) continue;1274 Type *polyBase = hasPolyBase( (*fnParm)->get_type(), scopeTyVars ); 1275 if ( polyBase && ! dynamic_cast< TypeInstType* >( polyBase ) ) { 1276 std::string sizeName = sizeofName( polyBase ); 1277 if ( seenTypes.count( sizeName ) ) continue; 1601 1278 1602 1279 ObjectDecl *sizeParm, *alignParm, *offsetParm; 1603 1280 sizeParm = newObj.clone(); 1604 sizeParm->set_name( size ofName( typeName ));1281 sizeParm->set_name( sizeName ); 1605 1282 last = funcType->get_parameters().insert( last, sizeParm ); 1606 1283 ++last; 1607 1284 1608 1285 alignParm = newObj.clone(); 1609 alignParm->set_name( alignofName( typeName ) );1286 alignParm->set_name( alignofName( polyBase ) ); 1610 1287 last = funcType->get_parameters().insert( last, alignParm ); 1611 1288 ++last; 1612 1289 1613 if ( StructInstType *polyBaseStruct = dynamic_cast< StructInstType* >( polyType ) ) { 1614 // NOTE zero-length arrays are illegal in C, so empty structs have no offset array 1615 if ( ! polyBaseStruct->get_baseStruct()->get_members().empty() ) { 1616 offsetParm = newPtr.clone(); 1617 offsetParm->set_name( offsetofName( typeName ) ); 1618 last = funcType->get_parameters().insert( last, offsetParm ); 1619 ++last; 1620 } 1290 if ( dynamic_cast< StructInstType* >( polyBase ) ) { 1291 offsetParm = newPtr.clone(); 1292 offsetParm->set_name( offsetofName( polyBase ) ); 1293 last = funcType->get_parameters().insert( last, offsetParm ); 1294 ++last; 1621 1295 } 1622 1296 1623 seenTypes.insert( typeName );1297 seenTypes.insert( sizeName ); 1624 1298 } 1625 1299 } … … 1631 1305 mutateAll( funcType->get_parameters(), *this ); 1632 1306 1633 scopeTyVars .endScope();1307 scopeTyVars = oldtyVars; 1634 1308 return funcType; 1635 1309 } 1636 1310 1637 //////////////////////////////////////// GenericInstantiator ////////////////////////////////////////////////// 1638 1639 /// Makes substitutions of params into baseParams; returns true if all parameters substituted for a concrete type 1640 bool makeSubstitutions( const std::list< TypeDecl* >& baseParams, const std::list< Expression* >& params, std::list< TypeExpr* >& out ) { 1641 bool allConcrete = true; // will finish the substitution list even if they're not all concrete 1642 1643 // substitute concrete types for given parameters, and incomplete types for placeholders 1644 std::list< TypeDecl* >::const_iterator baseParam = baseParams.begin(); 1645 std::list< Expression* >::const_iterator param = params.begin(); 1646 for ( ; baseParam != baseParams.end() && param != params.end(); ++baseParam, ++param ) { 1647 // switch ( (*baseParam)->get_kind() ) { 1648 // case TypeDecl::Any: { // any type is a valid substitution here; complete types can be used to instantiate generics 1649 TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param ); 1650 assert(paramType && "Aggregate parameters should be type expressions"); 1651 out.push_back( paramType->clone() ); 1652 // check that the substituted type isn't a type variable itself 1653 if ( dynamic_cast< TypeInstType* >( paramType->get_type() ) ) { 1654 allConcrete = false; 1655 } 1656 // break; 1657 // } 1658 // case TypeDecl::Dtype: // dtype can be consistently replaced with void [only pointers, which become void*] 1659 // out.push_back( new TypeExpr( new VoidType( Type::Qualifiers() ) ) ); 1660 // break; 1661 // case TypeDecl::Ftype: // pointer-to-ftype can be consistently replaced with void (*)(void) [similar to dtype] 1662 // out.push_back( new TypeExpr( new FunctionType( Type::Qualifiers(), false ) ) ); 1663 // break; 1664 // } 1665 } 1666 1667 // if any parameters left over, not done 1668 if ( baseParam != baseParams.end() ) return false; 1669 // // if not enough parameters given, substitute remaining incomplete types for placeholders 1670 // for ( ; baseParam != baseParams.end(); ++baseParam ) { 1671 // switch ( (*baseParam)->get_kind() ) { 1672 // case TypeDecl::Any: // no more substitutions here, fail early 1673 // return false; 1674 // case TypeDecl::Dtype: // dtype can be consistently replaced with void [only pointers, which become void*] 1675 // out.push_back( new TypeExpr( new VoidType( Type::Qualifiers() ) ) ); 1676 // break; 1677 // case TypeDecl::Ftype: // pointer-to-ftype can be consistently replaced with void (*)(void) [similar to dtype] 1678 // out.push_back( new TypeExpr( new FunctionType( Type::Qualifiers(), false ) ) ); 1679 // break; 1680 // } 1681 // } 1682 1683 return allConcrete; 1684 } 1685 1686 /// Substitutes types of members of in according to baseParams => typeSubs, appending the result to out 1687 void substituteMembers( const std::list< Declaration* >& in, const std::list< TypeDecl* >& baseParams, const std::list< TypeExpr* >& typeSubs, 1688 std::list< Declaration* >& out ) { 1689 // substitute types into new members 1690 TypeSubstitution subs( baseParams.begin(), baseParams.end(), typeSubs.begin() ); 1691 for ( std::list< Declaration* >::const_iterator member = in.begin(); member != in.end(); ++member ) { 1692 Declaration *newMember = (*member)->clone(); 1693 subs.apply(newMember); 1694 out.push_back( newMember ); 1695 } 1696 } 1697 1698 Type* GenericInstantiator::mutate( StructInstType *inst ) { 1699 // mutate subtypes 1700 Type *mutated = Mutator::mutate( inst ); 1701 inst = dynamic_cast< StructInstType* >( mutated ); 1702 if ( ! inst ) return mutated; 1703 1704 // exit early if no need for further mutation 1705 if ( inst->get_parameters().empty() ) return inst; 1706 assert( inst->get_baseParameters() && "Base struct has parameters" ); 1707 1708 // check if type can be concretely instantiated; put substitutions into typeSubs 1709 std::list< TypeExpr* > typeSubs; 1710 if ( ! makeSubstitutions( *inst->get_baseParameters(), inst->get_parameters(), typeSubs ) ) { 1711 deleteAll( typeSubs ); 1712 return inst; 1713 } 1714 1715 // make concrete instantiation of generic type 1716 StructDecl *concDecl = lookup( inst, typeSubs ); 1717 if ( ! concDecl ) { 1718 // set concDecl to new type, insert type declaration into statements to add 1719 concDecl = new StructDecl( typeNamer.newName( inst->get_name() ) ); 1720 substituteMembers( inst->get_baseStruct()->get_members(), *inst->get_baseParameters(), typeSubs, concDecl->get_members() ); 1721 DeclMutator::addDeclaration( concDecl ); 1722 insert( inst, typeSubs, concDecl ); 1723 } 1724 StructInstType *newInst = new StructInstType( inst->get_qualifiers(), concDecl->get_name() ); 1725 newInst->set_baseStruct( concDecl ); 1726 1727 deleteAll( typeSubs ); 1728 delete inst; 1729 return newInst; 1730 } 1731 1732 Type* GenericInstantiator::mutate( UnionInstType *inst ) { 1733 // mutate subtypes 1734 Type *mutated = Mutator::mutate( inst ); 1735 inst = dynamic_cast< UnionInstType* >( mutated ); 1736 if ( ! inst ) return mutated; 1737 1738 // exit early if no need for further mutation 1739 if ( inst->get_parameters().empty() ) return inst; 1740 assert( inst->get_baseParameters() && "Base union has parameters" ); 1741 1742 // check if type can be concretely instantiated; put substitutions into typeSubs 1743 std::list< TypeExpr* > typeSubs; 1744 if ( ! makeSubstitutions( *inst->get_baseParameters(), inst->get_parameters(), typeSubs ) ) { 1745 deleteAll( typeSubs ); 1746 return inst; 1747 } 1748 1749 // make concrete instantiation of generic type 1750 UnionDecl *concDecl = lookup( inst, typeSubs ); 1751 if ( ! concDecl ) { 1752 // set concDecl to new type, insert type declaration into statements to add 1753 concDecl = new UnionDecl( typeNamer.newName( inst->get_name() ) ); 1754 substituteMembers( inst->get_baseUnion()->get_members(), *inst->get_baseParameters(), typeSubs, concDecl->get_members() ); 1755 DeclMutator::addDeclaration( concDecl ); 1756 insert( inst, typeSubs, concDecl ); 1757 } 1758 UnionInstType *newInst = new UnionInstType( inst->get_qualifiers(), concDecl->get_name() ); 1759 newInst->set_baseUnion( concDecl ); 1760 1761 deleteAll( typeSubs ); 1762 delete inst; 1763 return newInst; 1764 } 1765 1766 // /// Gets the base struct or union declaration for a member expression; NULL if not applicable 1767 // AggregateDecl* getMemberBaseDecl( MemberExpr *memberExpr ) { 1768 // // get variable for member aggregate 1769 // VariableExpr *varExpr = dynamic_cast< VariableExpr* >( memberExpr->get_aggregate() ); 1770 // if ( ! varExpr ) return NULL; 1771 // 1772 // // get object for variable 1773 // ObjectDecl *objectDecl = dynamic_cast< ObjectDecl* >( varExpr->get_var() ); 1774 // if ( ! objectDecl ) return NULL; 1775 // 1776 // // get base declaration from object type 1777 // Type *objectType = objectDecl->get_type(); 1778 // StructInstType *structType = dynamic_cast< StructInstType* >( objectType ); 1779 // if ( structType ) return structType->get_baseStruct(); 1780 // UnionInstType *unionType = dynamic_cast< UnionInstType* >( objectType ); 1781 // if ( unionType ) return unionType->get_baseUnion(); 1782 // 1783 // return NULL; 1784 // } 1785 // 1786 // /// Finds the declaration with the given name, returning decls.end() if none such 1787 // std::list< Declaration* >::const_iterator findDeclNamed( const std::list< Declaration* > &decls, const std::string &name ) { 1788 // for( std::list< Declaration* >::const_iterator decl = decls.begin(); decl != decls.end(); ++decl ) { 1789 // if ( (*decl)->get_name() == name ) return decl; 1790 // } 1791 // return decls.end(); 1792 // } 1793 // 1794 // Expression* Instantiate::mutate( MemberExpr *memberExpr ) { 1795 // // mutate, exiting early if no longer MemberExpr 1796 // Expression *expr = Mutator::mutate( memberExpr ); 1797 // memberExpr = dynamic_cast< MemberExpr* >( expr ); 1798 // if ( ! memberExpr ) return expr; 1799 // 1800 // // get declaration of member and base declaration of member, exiting early if not found 1801 // AggregateDecl *memberBase = getMemberBaseDecl( memberExpr ); 1802 // if ( ! memberBase ) return memberExpr; 1803 // DeclarationWithType *memberDecl = memberExpr->get_member(); 1804 // std::list< Declaration* >::const_iterator baseIt = findDeclNamed( memberBase->get_members(), memberDecl->get_name() ); 1805 // if ( baseIt == memberBase->get_members().end() ) return memberExpr; 1806 // DeclarationWithType *baseDecl = dynamic_cast< DeclarationWithType* >( *baseIt ); 1807 // if ( ! baseDecl ) return memberExpr; 1808 // 1809 // // check if stated type of the member is not the type of the member's declaration; if so, need a cast 1810 // // this *SHOULD* be safe, I don't think anything but the void-replacements I put in for dtypes would make it past the typechecker 1811 // SymTab::Indexer dummy; 1812 // if ( ResolvExpr::typesCompatible( memberDecl->get_type(), baseDecl->get_type(), dummy ) ) return memberExpr; 1813 // else return new CastExpr( memberExpr, memberDecl->get_type() ); 1814 // } 1815 1816 void GenericInstantiator::doBeginScope() { 1817 DeclMutator::doBeginScope(); 1818 instantiations.beginScope(); 1819 } 1820 1821 void GenericInstantiator::doEndScope() { 1822 DeclMutator::doEndScope(); 1823 instantiations.endScope(); 1824 } 1825 1826 ////////////////////////////////////////// PolyGenericCalculator //////////////////////////////////////////////////// 1827 1828 void PolyGenericCalculator::beginTypeScope( Type *ty ) { 1829 scopeTyVars.beginScope(); 1830 makeTyVarMap( ty, scopeTyVars ); 1831 } 1832 1833 void PolyGenericCalculator::endTypeScope() { 1834 scopeTyVars.endScope(); 1835 } 1311 ////////////////////////////////////////// MemberExprFixer //////////////////////////////////////////////////// 1836 1312 1837 1313 template< typename DeclClass > 1838 DeclClass * PolyGenericCalculator::handleDecl( DeclClass *decl, Type *type ) { 1839 beginTypeScope( type ); 1840 knownLayouts.beginScope(); 1841 knownOffsets.beginScope(); 1314 DeclClass * MemberExprFixer::handleDecl( DeclClass *decl, Type *type ) { 1315 TyVarMap oldtyVars = scopeTyVars; 1316 makeTyVarMap( type, scopeTyVars ); 1842 1317 1843 1318 DeclClass *ret = static_cast< DeclClass *>( Mutator::mutate( decl ) ); 1844 1319 1845 knownOffsets.endScope(); 1846 knownLayouts.endScope(); 1847 endTypeScope(); 1320 scopeTyVars = oldtyVars; 1848 1321 return ret; 1849 1322 } 1850 1323 1851 ObjectDecl * PolyGenericCalculator::mutate( ObjectDecl *objectDecl ) {1324 ObjectDecl * MemberExprFixer::mutate( ObjectDecl *objectDecl ) { 1852 1325 return handleDecl( objectDecl, objectDecl->get_type() ); 1853 1326 } 1854 1327 1855 DeclarationWithType * PolyGenericCalculator::mutate( FunctionDecl *functionDecl ) {1328 DeclarationWithType * MemberExprFixer::mutate( FunctionDecl *functionDecl ) { 1856 1329 return handleDecl( functionDecl, functionDecl->get_functionType() ); 1857 1330 } 1858 1331 1859 TypedefDecl * PolyGenericCalculator::mutate( TypedefDecl *typedefDecl ) {1332 TypedefDecl * MemberExprFixer::mutate( TypedefDecl *typedefDecl ) { 1860 1333 return handleDecl( typedefDecl, typedefDecl->get_base() ); 1861 1334 } 1862 1335 1863 TypeDecl * PolyGenericCalculator::mutate( TypeDecl *typeDecl ) {1336 TypeDecl * MemberExprFixer::mutate( TypeDecl *typeDecl ) { 1864 1337 scopeTyVars[ typeDecl->get_name() ] = typeDecl->get_kind(); 1865 1338 return Mutator::mutate( typeDecl ); 1866 1339 } 1867 1340 1868 Type * PolyGenericCalculator::mutate( PointerType *pointerType ) { 1869 beginTypeScope( pointerType ); 1341 Type * MemberExprFixer::mutate( PointerType *pointerType ) { 1342 TyVarMap oldtyVars = scopeTyVars; 1343 makeTyVarMap( pointerType, scopeTyVars ); 1870 1344 1871 1345 Type *ret = Mutator::mutate( pointerType ); 1872 1346 1873 endTypeScope();1347 scopeTyVars = oldtyVars; 1874 1348 return ret; 1875 1349 } 1876 1350 1877 Type * PolyGenericCalculator::mutate( FunctionType *funcType ) { 1878 beginTypeScope( funcType ); 1879 1880 // make sure that any type information passed into the function is accounted for 1881 for ( std::list< DeclarationWithType* >::const_iterator fnParm = funcType->get_parameters().begin(); fnParm != funcType->get_parameters().end(); ++fnParm ) { 1882 // condition here duplicates that in Pass2::mutate( FunctionType* ) 1883 Type *polyType = isPolyType( (*fnParm)->get_type(), scopeTyVars ); 1884 if ( polyType && ! dynamic_cast< TypeInstType* >( polyType ) ) { 1885 knownLayouts.insert( mangleType( polyType ) ); 1886 } 1887 } 1888 1889 Type *ret = Mutator::mutate( funcType ); 1890 1891 endTypeScope(); 1351 Type * MemberExprFixer::mutate( FunctionType *functionType ) { 1352 TyVarMap oldtyVars = scopeTyVars; 1353 makeTyVarMap( functionType, scopeTyVars ); 1354 1355 Type *ret = Mutator::mutate( functionType ); 1356 1357 scopeTyVars = oldtyVars; 1892 1358 return ret; 1893 1359 } 1894 1360 1895 Statement * PolyGenericCalculator::mutate( DeclStmt *declStmt ) {1361 Statement *MemberExprFixer::mutate( DeclStmt *declStmt ) { 1896 1362 if ( ObjectDecl *objectDecl = dynamic_cast< ObjectDecl *>( declStmt->get_decl() ) ) { 1897 if ( findGeneric( objectDecl->get_type()) ) {1363 if ( isPolyType( objectDecl->get_type(), scopeTyVars ) ) { 1898 1364 // change initialization of a polymorphic value object 1899 1365 // to allocate storage with alloca 1900 1366 Type *declType = objectDecl->get_type(); 1901 1367 UntypedExpr *alloc = new UntypedExpr( new NameExpr( "__builtin_alloca" ) ); 1902 alloc->get_args().push_back( new NameExpr( sizeofName( mangleType( declType )) ) );1368 alloc->get_args().push_back( new NameExpr( sizeofName( declType ) ) ); 1903 1369 1904 1370 delete objectDecl->get_init(); … … 1932 1398 ConstantExpr *fieldIndex = new ConstantExpr( Constant( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), offset_namer.str() ) ); 1933 1399 UntypedExpr *fieldOffset = new UntypedExpr( new NameExpr( "?[?]" ) ); 1934 fieldOffset->get_args().push_back( new NameExpr( offsetofName( mangleType( objectType )) ) );1400 fieldOffset->get_args().push_back( new NameExpr( offsetofName( objectType ) ) ); 1935 1401 fieldOffset->get_args().push_back( fieldIndex ); 1936 1402 return fieldOffset; … … 1947 1413 } 1948 1414 1949 Expression * PolyGenericCalculator::mutate( MemberExpr *memberExpr ) {1415 Expression *MemberExprFixer::mutate( MemberExpr *memberExpr ) { 1950 1416 // mutate, exiting early if no longer MemberExpr 1951 1417 Expression *expr = Mutator::mutate( memberExpr ); … … 1964 1430 Type *objectType = hasPolyBase( objectDecl->get_type(), scopeTyVars, &tyDepth ); 1965 1431 if ( ! objectType ) return memberExpr; 1966 findGeneric( objectType ); // ensure layout for this type is available1967 1432 1968 1433 Expression *newMemberExpr = 0; … … 1996 1461 } 1997 1462 1998 ObjectDecl *PolyGenericCalculator::makeVar( const std::string &name, Type *type, Initializer *init ) { 1999 ObjectDecl *newObj = new ObjectDecl( name, DeclarationNode::NoStorageClass, LinkageSpec::C, 0, type, init ); 2000 stmtsToAdd.push_back( new DeclStmt( noLabels, newObj ) ); 2001 return newObj; 2002 } 2003 2004 void PolyGenericCalculator::addOtypeParamsToLayoutCall( UntypedExpr *layoutCall, const std::list< Type* > &otypeParams ) { 2005 for ( std::list< Type* >::const_iterator param = otypeParams.begin(); param != otypeParams.end(); ++param ) { 2006 if ( findGeneric( *param ) ) { 2007 // push size/align vars for a generic parameter back 2008 std::string paramName = mangleType( *param ); 2009 layoutCall->get_args().push_back( new NameExpr( sizeofName( paramName ) ) ); 2010 layoutCall->get_args().push_back( new NameExpr( alignofName( paramName ) ) ); 2011 } else { 2012 layoutCall->get_args().push_back( new SizeofExpr( (*param)->clone() ) ); 2013 layoutCall->get_args().push_back( new AlignofExpr( (*param)->clone() ) ); 2014 } 2015 } 2016 } 2017 2018 /// returns true if any of the otype parameters have a dynamic layout and puts all otype parameters in the output list 2019 bool findGenericParams( std::list< TypeDecl* > &baseParams, std::list< Expression* > &typeParams, std::list< Type* > &out ) { 2020 bool hasDynamicLayout = false; 2021 2022 std::list< TypeDecl* >::const_iterator baseParam = baseParams.begin(); 2023 std::list< Expression* >::const_iterator typeParam = typeParams.begin(); 2024 for ( ; baseParam != baseParams.end() && typeParam != typeParams.end(); ++baseParam, ++typeParam ) { 2025 // skip non-otype parameters 2026 if ( (*baseParam)->get_kind() != TypeDecl::Any ) continue; 2027 TypeExpr *typeExpr = dynamic_cast< TypeExpr* >( *typeParam ); 2028 assert( typeExpr && "all otype parameters should be type expressions" ); 2029 2030 Type *type = typeExpr->get_type(); 2031 out.push_back( type ); 2032 if ( isPolyType( type ) ) hasDynamicLayout = true; 2033 } 2034 assert( baseParam == baseParams.end() && typeParam == typeParams.end() ); 2035 2036 return hasDynamicLayout; 2037 } 2038 2039 bool PolyGenericCalculator::findGeneric( Type *ty ) { 2040 if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( ty ) ) { 2041 // duplicate logic from isPolyType() 2042 if ( env ) { 2043 if ( Type *newType = env->lookup( typeInst->get_name() ) ) { 2044 return findGeneric( newType ); 2045 } // if 2046 } // if 2047 if ( scopeTyVars.find( typeInst->get_name() ) != scopeTyVars.end() ) { 2048 // NOTE assumes here that getting put in the scopeTyVars included having the layout variables set 2049 return true; 2050 } 2051 return false; 2052 } else if ( StructInstType *structTy = dynamic_cast< StructInstType* >( ty ) ) { 2053 // check if this type already has a layout generated for it 2054 std::string typeName = mangleType( ty ); 2055 if ( knownLayouts.find( typeName ) != knownLayouts.end() ) return true; 2056 2057 // check if any of the type parameters have dynamic layout; if none do, this type is (or will be) monomorphized 2058 std::list< Type* > otypeParams; 2059 if ( ! findGenericParams( *structTy->get_baseParameters(), structTy->get_parameters(), otypeParams ) ) return false; 2060 2061 // insert local variables for layout and generate call to layout function 2062 knownLayouts.insert( typeName ); // done early so as not to interfere with the later addition of parameters to the layout call 2063 Type *layoutType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ); 2064 2065 int n_members = structTy->get_baseStruct()->get_members().size(); 2066 if ( n_members == 0 ) { 2067 // all empty structs have the same layout - size 1, align 1 2068 makeVar( sizeofName( typeName ), layoutType, new SingleInit( new ConstantExpr( Constant::from( (unsigned long)1 ) ) ) ); 2069 makeVar( alignofName( typeName ), layoutType->clone(), new SingleInit( new ConstantExpr( Constant::from( (unsigned long)1 ) ) ) ); 2070 // NOTE zero-length arrays are forbidden in C, so empty structs have no offsetof array 2071 } else { 2072 ObjectDecl *sizeVar = makeVar( sizeofName( typeName ), layoutType ); 2073 ObjectDecl *alignVar = makeVar( alignofName( typeName ), layoutType->clone() ); 2074 ObjectDecl *offsetVar = makeVar( offsetofName( typeName ), new ArrayType( Type::Qualifiers(), layoutType->clone(), new ConstantExpr( Constant::from( n_members ) ), false, false ) ); 2075 2076 // generate call to layout function 2077 UntypedExpr *layoutCall = new UntypedExpr( new NameExpr( layoutofName( structTy->get_baseStruct() ) ) ); 2078 layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( sizeVar ) ) ); 2079 layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( alignVar ) ) ); 2080 layoutCall->get_args().push_back( new VariableExpr( offsetVar ) ); 2081 addOtypeParamsToLayoutCall( layoutCall, otypeParams ); 2082 2083 stmtsToAdd.push_back( new ExprStmt( noLabels, layoutCall ) ); 2084 } 2085 2086 return true; 2087 } else if ( UnionInstType *unionTy = dynamic_cast< UnionInstType* >( ty ) ) { 2088 // check if this type already has a layout generated for it 2089 std::string typeName = mangleType( ty ); 2090 if ( knownLayouts.find( typeName ) != knownLayouts.end() ) return true; 2091 2092 // check if any of the type parameters have dynamic layout; if none do, this type is (or will be) monomorphized 2093 std::list< Type* > otypeParams; 2094 if ( ! findGenericParams( *unionTy->get_baseParameters(), unionTy->get_parameters(), otypeParams ) ) return false; 2095 2096 // insert local variables for layout and generate call to layout function 2097 knownLayouts.insert( typeName ); // done early so as not to interfere with the later addition of parameters to the layout call 2098 Type *layoutType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ); 2099 2100 ObjectDecl *sizeVar = makeVar( sizeofName( typeName ), layoutType ); 2101 ObjectDecl *alignVar = makeVar( alignofName( typeName ), layoutType->clone() ); 2102 2103 // generate call to layout function 2104 UntypedExpr *layoutCall = new UntypedExpr( new NameExpr( layoutofName( unionTy->get_baseUnion() ) ) ); 2105 layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( sizeVar ) ) ); 2106 layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( alignVar ) ) ); 2107 addOtypeParamsToLayoutCall( layoutCall, otypeParams ); 2108 2109 stmtsToAdd.push_back( new ExprStmt( noLabels, layoutCall ) ); 2110 2111 return true; 2112 } 2113 2114 return false; 2115 } 2116 2117 Expression *PolyGenericCalculator::mutate( SizeofExpr *sizeofExpr ) { 2118 Type *ty = sizeofExpr->get_type(); 2119 if ( findGeneric( ty ) ) { 2120 Expression *ret = new NameExpr( sizeofName( mangleType( ty ) ) ); 2121 delete sizeofExpr; 2122 return ret; 2123 } 2124 return sizeofExpr; 2125 } 2126 2127 Expression *PolyGenericCalculator::mutate( AlignofExpr *alignofExpr ) { 2128 Type *ty = alignofExpr->get_type(); 2129 if ( findGeneric( ty ) ) { 2130 Expression *ret = new NameExpr( alignofName( mangleType( ty ) ) ); 2131 delete alignofExpr; 2132 return ret; 2133 } 2134 return alignofExpr; 2135 } 2136 2137 Expression *PolyGenericCalculator::mutate( OffsetofExpr *offsetofExpr ) { 1463 Expression *MemberExprFixer::mutate( OffsetofExpr *offsetofExpr ) { 2138 1464 // mutate, exiting early if no longer OffsetofExpr 2139 1465 Expression *expr = Mutator::mutate( offsetofExpr ); … … 2142 1468 2143 1469 // only mutate expressions for polymorphic structs/unions 2144 Type *ty = offsetofExpr->get_type();2145 if ( ! findGeneric( ty )) return offsetofExpr;2146 1470 Type *ty = isPolyType( offsetofExpr->get_type(), scopeTyVars ); 1471 if ( ! ty ) return offsetofExpr; 1472 2147 1473 if ( StructInstType *structType = dynamic_cast< StructInstType* >( ty ) ) { 2148 1474 // replace offsetof expression by index into offset array … … 2160 1486 } 2161 1487 2162 Expression *PolyGenericCalculator::mutate( OffsetPackExpr *offsetPackExpr ) {2163 StructInstType *ty = offsetPackExpr->get_type();2164 2165 Expression *ret = 0;2166 if ( findGeneric( ty ) ) {2167 // pull offset back from generated type information2168 ret = new NameExpr( offsetofName( mangleType( ty ) ) );2169 } else {2170 std::string offsetName = offsetofName( mangleType( ty ) );2171 if ( knownOffsets.find( offsetName ) != knownOffsets.end() ) {2172 // use the already-generated offsets for this type2173 ret = new NameExpr( offsetName );2174 } else {2175 knownOffsets.insert( offsetName );2176 2177 std::list< Declaration* > &baseMembers = ty->get_baseStruct()->get_members();2178 Type *offsetType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );2179 2180 // build initializer list for offset array2181 std::list< Initializer* > inits;2182 for ( std::list< Declaration* >::const_iterator member = baseMembers.begin(); member != baseMembers.end(); ++member ) {2183 DeclarationWithType *memberDecl;2184 if ( DeclarationWithType *origMember = dynamic_cast< DeclarationWithType* >( *member ) ) {2185 memberDecl = origMember->clone();2186 } else {2187 memberDecl = new ObjectDecl( (*member)->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, offsetType->clone(), 0 );2188 }2189 inits.push_back( new SingleInit( new OffsetofExpr( ty->clone(), memberDecl ) ) );2190 }2191 2192 // build the offset array and replace the pack with a reference to it2193 ObjectDecl *offsetArray = makeVar( offsetName, new ArrayType( Type::Qualifiers(), offsetType, new ConstantExpr( Constant::from( baseMembers.size() ) ), false, false ),2194 new ListInit( inits ) );2195 ret = new VariableExpr( offsetArray );2196 }2197 }2198 2199 delete offsetPackExpr;2200 return ret;2201 }2202 2203 void PolyGenericCalculator::doBeginScope() {2204 knownLayouts.beginScope();2205 knownOffsets.beginScope();2206 }2207 2208 void PolyGenericCalculator::doEndScope() {2209 knownLayouts.endScope();2210 knownOffsets.endScope();2211 }2212 2213 1488 ////////////////////////////////////////// Pass3 //////////////////////////////////////////////////// 2214 1489 2215 1490 template< typename DeclClass > 2216 1491 DeclClass * Pass3::handleDecl( DeclClass *decl, Type *type ) { 2217 scopeTyVars.beginScope();1492 TyVarMap oldtyVars = scopeTyVars; 2218 1493 makeTyVarMap( type, scopeTyVars ); 2219 1494 … … 2221 1496 ScrubTyVars::scrub( decl, scopeTyVars ); 2222 1497 2223 scopeTyVars .endScope();1498 scopeTyVars = oldtyVars; 2224 1499 return ret; 2225 1500 } … … 2251 1526 2252 1527 Type * Pass3::mutate( PointerType *pointerType ) { 2253 scopeTyVars.beginScope();1528 TyVarMap oldtyVars = scopeTyVars; 2254 1529 makeTyVarMap( pointerType, scopeTyVars ); 2255 1530 2256 1531 Type *ret = Mutator::mutate( pointerType ); 2257 1532 2258 scopeTyVars .endScope();1533 scopeTyVars = oldtyVars; 2259 1534 return ret; 2260 1535 } 2261 1536 2262 1537 Type * Pass3::mutate( FunctionType *functionType ) { 2263 scopeTyVars.beginScope();1538 TyVarMap oldtyVars = scopeTyVars; 2264 1539 makeTyVarMap( functionType, scopeTyVars ); 2265 1540 2266 1541 Type *ret = Mutator::mutate( functionType ); 2267 1542 2268 scopeTyVars .endScope();1543 scopeTyVars = oldtyVars; 2269 1544 return ret; 2270 1545 }
Note:
See TracChangeset
for help on using the changeset viewer.