Changeset 70a06f6 for src/GenPoly
- Timestamp:
- Apr 14, 2016, 4:13:10 PM (9 years ago)
- Branches:
- ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, ctor, deferred_resn, demangler, enum, forall-pointer-decay, gc_noraii, jacob/cs343-translation, jenkins-sandbox, master, memory, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
- Children:
- 356189a
- Parents:
- db4ecc5 (diff), 37f0da8 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - Location:
- src/GenPoly
- Files:
-
- 2 added
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
src/GenPoly/Box.cc
rdb4ecc5 r70a06f6 10 10 // Created On : Mon May 18 07:44:20 2015 11 11 // Last Modified By : Rob Schluntz 12 // Last Modified On : T ue Feb 09 14:39:52201612 // Last Modified On : Thu Apr 14 15:57:46 2016 13 13 // Update Count : 295 14 14 // … … 30 30 #include "FindFunction.h" 31 31 #include "ScopedMap.h" 32 #include "ScopedSet.h" 32 33 #include "ScrubTyVars.h" 33 34 … … 62 63 FunctionType *makeAdapterType( FunctionType *adaptee, const TyVarMap &tyVars ); 63 64 64 /// Key for a unique concrete type; generic base type paired with type parameter list 65 struct ConcreteType { 66 ConcreteType() : base(NULL), params() {} 67 68 ConcreteType(AggregateDecl *_base, const std::list< Type* >& _params) : base(_base), params() { cloneAll(_params, params); } 69 70 ConcreteType(const ConcreteType& that) : base(that.base), params() { cloneAll(that.params, params); } 65 /// Abstracts type equality for a list of parameter types 66 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 ) ) {} 71 73 72 74 /// Extracts types from a list of TypeExpr* 73 ConcreteType(AggregateDecl *_base, const std::list< TypeExpr* >& _params) : base(_base),params() {75 TypeList( const std::list< TypeExpr* >& _params ) : params() { 74 76 for ( std::list< TypeExpr* >::const_iterator param = _params.begin(); param != _params.end(); ++param ) { 75 77 params.push_back( (*param)->get_type()->clone() ); … … 77 79 } 78 80 79 ConcreteType& operator= (const ConcreteType& that) {81 TypeList& operator= ( const TypeList &that ) { 80 82 deleteAll( params ); 83 81 84 params.clear(); 82 83 base = that.base;84 85 cloneAll( that.params, params ); 85 86 … … 87 88 } 88 89 89 ~ConcreteType() { deleteAll( params ); } 90 91 bool operator== (const ConcreteType& that) const { 92 if ( base != that.base ) return false; 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; 93 102 94 103 SymTab::Indexer dummy; 95 if ( params.size() != that.params.size() ) return false;96 104 for ( std::list< Type* >::const_iterator it = params.begin(), jt = that.params.begin(); it != params.end(); ++it, ++jt ) { 97 105 if ( ! ResolvExpr::typesCompatible( *it, *jt, dummy ) ) return false; … … 100 108 } 101 109 102 AggregateDecl *base; ///< Base generic type103 110 std::list< Type* > params; ///< Instantiation parameters 104 111 }; 105 112 106 /// Maps a concrete typeto the some value, accounting for scope107 template< typename Value >113 /// Maps a key and a TypeList to the some value, accounting for scope 114 template< typename Key, typename Value > 108 115 class InstantiationMap { 109 /// Information about a specific instantiation of a generic type 110 struct Instantiation { 111 ConcreteType key; ///< Instantiation parameters for this type 112 Value *value; ///< Value for this instantiation 113 114 Instantiation() : key(), value(0) {} 115 Instantiation(const ConcreteType &_key, Value *_value) : key(_key), value(_value) {} 116 }; 117 /// Map of generic types to instantiations of them 118 typedef std::map< AggregateDecl*, std::vector< Instantiation > > Scope; 119 120 std::vector< Scope > scopes; ///< list of scopes, from outermost to innermost 116 /// Wraps value for a specific (Key, TypeList) combination 117 typedef std::pair< TypeList, Value* > Instantiation; 118 /// List of TypeLists paired with their appropriate values 119 typedef std::vector< Instantiation > ValueList; 120 /// Underlying map type; maps keys to a linear list of corresponding TypeLists and values 121 typedef ScopedMap< Key*, ValueList > InnerMap; 122 123 InnerMap instantiations; ///< instantiations 121 124 122 125 public: 123 126 /// Starts a new scope 124 void beginScope() { 125 Scope scope; 126 scopes.push_back(scope); 127 } 127 void beginScope() { instantiations.beginScope(); } 128 128 129 129 /// Ends a scope 130 void endScope() { 131 scopes.pop_back(); 132 } 133 134 /// Default constructor initializes with one scope 135 InstantiationMap() { beginScope(); } 136 137 // private: 138 /// Gets the value for the concrete instantiation of this type, assuming it has already been instantiated in the current scope. 139 /// Returns NULL on none such. 140 Value *lookup( AggregateDecl *generic, const std::list< TypeExpr* >& params ) { 141 ConcreteType key(generic, params); 142 // scan scopes from innermost out 143 for ( typename std::vector< Scope >::const_reverse_iterator scope = scopes.rbegin(); scope != scopes.rend(); ++scope ) { 144 // skip scope if no instantiations of this generic type 145 typename Scope::const_iterator insts = scope->find( generic ); 146 if ( insts == scope->end() ) continue; 147 // look through instantiations for matches to concrete type 148 for ( typename std::vector< Instantiation >::const_iterator inst = insts->second.begin(); inst != insts->second.end(); ++inst ) { 149 if ( inst->key == key ) return inst->value; 130 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 key 137 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; 150 140 } 151 141 } 152 // no matching instantiation found142 // no matching instantiations found 153 143 return 0; 154 144 } 155 public: 156 // StructDecl* lookup( StructInstType *inst, const std::list< TypeExpr* > &typeSubs ) { return (StructDecl*)lookup( inst->get_baseStruct(), typeSubs ); } 157 // UnionDecl* lookup( UnionInstType *inst, const std::list< TypeExpr* > &typeSubs ) { return (UnionDecl*)lookup( inst->get_baseUnion(), typeSubs ); } 158 159 // private: 160 /// Adds a value for a concrete type to the current scope 161 void insert( AggregateDecl *generic, const std::list< TypeExpr* > ¶ms, Value *value ) { 162 ConcreteType key(generic, params); 163 scopes.back()[generic].push_back( Instantiation( key, value ) ); 164 } 165 // public: 166 // void insert( StructInstType *inst, const std::list< TypeExpr* > &typeSubs, StructDecl *decl ) { insert( inst->get_baseStruct(), typeSubs, decl ); } 167 // void insert( UnionInstType *inst, const std::list< TypeExpr* > &typeSubs, UnionDecl *decl ) { insert( inst->get_baseUnion(), typeSubs, decl ); } 145 146 /// Adds a value for a (key, typeList) pair to the current scope 147 void insert( Key *key, const std::list< TypeExpr* > ¶ms, Value *value ) { 148 instantiations[ key ].push_back( Instantiation( TypeList( params ), value ) ); 149 } 168 150 }; 169 151 … … 178 160 virtual Declaration *mutate( UnionDecl *unionDecl ); 179 161 }; 180 162 181 163 /// 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 182 164 class Pass1 : public PolyMutator { … … 197 179 virtual void doEndScope(); 198 180 private: 199 /// Makes a new temporary array holding the offsets of the fields of `type`, and returns a new variable expression referencing it200 Expression *makeOffsetArray( StructInstType *type );201 181 /// Pass the extra type parameters from polymorphic generic arguments or return types into a function application 202 182 void passArgTypeVars( ApplicationExpr *appExpr, Type *parmType, Type *argBaseType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars, std::set< std::string > &seenTypes ); … … 225 205 ObjectDecl *makeTemporary( Type *type ); 226 206 227 std::map< std::string, DeclarationWithType *> assignOps; 228 ResolvExpr::TypeMap< DeclarationWithType > scopedAssignOps; 229 ScopedMap< std::string, DeclarationWithType* > adapters; 207 ScopedMap< std::string, DeclarationWithType *> assignOps; ///< Currently known type variable assignment operators 208 ResolvExpr::TypeMap< DeclarationWithType > scopedAssignOps; ///< Currently known assignment operators 209 ScopedMap< std::string, DeclarationWithType* > adapters; ///< Set of adapter functions in the current scope 210 230 211 DeclarationWithType *retval; 231 212 bool useRetval; … … 233 214 }; 234 215 235 /// Moves polymorphic returns in function types to pointer-type parameters, adds type size and assertion parameters to parameter lists as well 216 /// * Moves polymorphic returns in function types to pointer-type parameters 217 /// * adds type size and assertion parameters to parameter lists 236 218 class Pass2 : public PolyMutator { 237 219 public: … … 244 226 virtual Type *mutate( PointerType *pointerType ); 245 227 virtual Type *mutate( FunctionType *funcType ); 228 246 229 private: 247 230 void addAdapters( FunctionType *functionType ); … … 253 236 class GenericInstantiator : public DeclMutator { 254 237 /// Map of (generic type, parameter list) pairs to concrete type instantiations 255 InstantiationMap< AggregateDecl > instantiations;238 InstantiationMap< AggregateDecl, AggregateDecl > instantiations; 256 239 /// Namer for concrete types 257 240 UniqueName typeNamer; … … 278 261 }; 279 262 280 /// Replaces member expressions for polymorphic types with calculated add-field-offset-and-dereference; 281 /// also fixes offsetof expressions. 282 class MemberExprFixer : public PolyMutator { 283 public: 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: 284 269 template< typename DeclClass > 285 270 DeclClass *handleDecl( DeclClass *decl, Type *type ); … … 292 277 virtual Type *mutate( FunctionType *funcType ); 293 278 virtual Expression *mutate( MemberExpr *memberExpr ); 279 virtual Expression *mutate( SizeofExpr *sizeofExpr ); 280 virtual Expression *mutate( AlignofExpr *alignofExpr ); 294 281 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 initializer 289 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 returns 291 bool findGeneric( Type *ty ); 292 /// adds type parameters to the layout call; will generate the appropriate parameters if needed 293 void addOtypeParamsToLayoutCall( UntypedExpr *layoutCall, const std::list< Type* > &otypeParams ); 294 295 /// Enters a new scope for type-variables, adding the type variables from ty 296 void beginTypeScope( Type *ty ); 297 /// Exits the type-variable scope 298 void endTypeScope(); 299 300 ScopedSet< std::string > knownLayouts; ///< Set of generic type layouts known in the current scope, indexed by sizeofName 301 ScopedSet< std::string > knownOffsets; ///< Set of non-generic types for which the offset array exists in the current scope, indexed by offsetofName 295 302 }; 296 303 … … 342 349 Pass2 pass2; 343 350 GenericInstantiator instantiator; 344 MemberExprFixer memberFixer;351 PolyGenericCalculator polyCalculator; 345 352 Pass3 pass3; 346 353 347 354 layoutBuilder.mutateDeclarationList( translationUnit ); 348 355 mutateTranslationUnit/*All*/( translationUnit, pass1 ); 349 356 mutateTranslationUnit/*All*/( translationUnit, pass2 ); 350 // instantiateGeneric( translationUnit );351 357 instantiator.mutateDeclarationList( translationUnit ); 352 mutateTranslationUnit/*All*/( translationUnit, memberFixer );358 mutateTranslationUnit/*All*/( translationUnit, polyCalculator ); 353 359 mutateTranslationUnit/*All*/( translationUnit, pass3 ); 354 360 } … … 364 370 return functionDecl; 365 371 } 366 372 367 373 /// Get a list of type declarations that will affect a layout function 368 374 std::list< TypeDecl* > takeOtypeOnly( std::list< TypeDecl* > &decls ) { … … 374 380 } 375 381 } 376 382 377 383 return otypeDecls; 378 384 } … … 381 387 void addOtypeParams( FunctionType *layoutFnType, std::list< TypeDecl* > &otypeParams ) { 382 388 BasicType sizeAlignType( Type::Qualifiers(), BasicType::LongUnsignedInt ); 383 389 384 390 for ( std::list< TypeDecl* >::const_iterator param = otypeParams.begin(); param != otypeParams.end(); ++param ) { 385 391 TypeInstType paramType( Type::Qualifiers(), (*param)->get_name(), *param ); 386 layoutFnType->get_parameters().push_back( new ObjectDecl( sizeofName( ¶mType ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignType.clone(), 0 ) ); 387 layoutFnType->get_parameters().push_back( new ObjectDecl( alignofName( ¶mType ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignType.clone(), 0 ) ); 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 ) ); 388 395 } 389 396 } 390 397 391 398 /// Builds a layout function declaration 392 FunctionDecl *buildLayoutFunctionDecl( const std::string &typeName, unsigned int functionNesting, FunctionType *layoutFnType ) {399 FunctionDecl *buildLayoutFunctionDecl( AggregateDecl *typeDecl, unsigned int functionNesting, FunctionType *layoutFnType ) { 393 400 // Routines at global scope marked "static" to prevent multiple definitions is separate translation units 394 401 // because each unit generates copies of the default routines for each aggregate. 395 402 FunctionDecl *layoutDecl = new FunctionDecl( 396 "__layoutof_" + typeName, functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, layoutFnType, new CompoundStmt( noLabels ), true, false );403 layoutofName( typeDecl ), functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, layoutFnType, new CompoundStmt( noLabels ), true, false ); 397 404 layoutDecl->fixUniqueId(); 398 405 return layoutDecl; … … 437 444 return makeCond( ifCond, ifExpr ); 438 445 } 439 446 440 447 /// adds an expression to a compound statement 441 448 void addExpr( CompoundStmt *stmts, Expression *expr ) { … … 447 454 stmts->get_kids().push_back( stmt ); 448 455 } 449 456 450 457 Declaration *LayoutFunctionBuilder::mutate( StructDecl *structDecl ) { 451 458 // do not generate layout function for "empty" tag structs … … 460 467 BasicType *sizeAlignType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ); 461 468 PointerType *sizeAlignOutType = new PointerType( Type::Qualifiers(), sizeAlignType ); 462 463 ObjectDecl *sizeParam = new ObjectDecl( "__sizeof_" + structDecl->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType, 0 );469 470 ObjectDecl *sizeParam = new ObjectDecl( sizeofName( structDecl->get_name() ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType, 0 ); 464 471 layoutFnType->get_parameters().push_back( sizeParam ); 465 ObjectDecl *alignParam = new ObjectDecl( "__alignof_" + structDecl->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType->clone(), 0 );472 ObjectDecl *alignParam = new ObjectDecl( alignofName( structDecl->get_name() ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType->clone(), 0 ); 466 473 layoutFnType->get_parameters().push_back( alignParam ); 467 ObjectDecl *offsetParam = new ObjectDecl( "__offsetof_" + structDecl->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType->clone(), 0 );474 ObjectDecl *offsetParam = new ObjectDecl( offsetofName( structDecl->get_name() ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType->clone(), 0 ); 468 475 layoutFnType->get_parameters().push_back( offsetParam ); 469 476 addOtypeParams( layoutFnType, otypeParams ); 470 477 471 478 // build function decl 472 FunctionDecl *layoutDecl = buildLayoutFunctionDecl( structDecl ->get_name(), functionNesting, layoutFnType );479 FunctionDecl *layoutDecl = buildLayoutFunctionDecl( structDecl, functionNesting, layoutFnType ); 473 480 474 481 // calculate struct layout in function body … … 490 497 addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), new AlignofExpr( memberType->clone() ) ) ); 491 498 } 492 499 493 500 // place current size in the current offset index 494 501 addExpr( layoutDecl->get_statements(), makeOp( "?=?", makeOp( "?[?]", new VariableExpr( offsetParam ), new ConstantExpr( Constant::from( n_members ) ) ), … … 498 505 // add member size to current size 499 506 addExpr( layoutDecl->get_statements(), makeOp( "?+=?", derefVar( sizeParam ), new SizeofExpr( memberType->clone() ) ) ); 500 507 501 508 // take max of member alignment and global alignment 502 509 addStmt( layoutDecl->get_statements(), makeAssignMax( derefVar( alignParam ), new AlignofExpr( memberType->clone() ) ) ); … … 508 515 return structDecl; 509 516 } 510 517 511 518 Declaration *LayoutFunctionBuilder::mutate( UnionDecl *unionDecl ) { 512 519 // do not generate layout function for "empty" tag unions 513 520 if ( unionDecl->get_members().empty() ) return unionDecl; 514 521 515 522 // get parameters that can change layout, exiting early if none 516 523 std::list< TypeDecl* > otypeParams = takeOtypeOnly( unionDecl->get_parameters() ); … … 521 528 BasicType *sizeAlignType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ); 522 529 PointerType *sizeAlignOutType = new PointerType( Type::Qualifiers(), sizeAlignType ); 523 524 ObjectDecl *sizeParam = new ObjectDecl( "__sizeof_" + unionDecl->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType, 0 );530 531 ObjectDecl *sizeParam = new ObjectDecl( sizeofName( unionDecl->get_name() ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType, 0 ); 525 532 layoutFnType->get_parameters().push_back( sizeParam ); 526 ObjectDecl *alignParam = new ObjectDecl( "__alignof_" + unionDecl->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType->clone(), 0 );533 ObjectDecl *alignParam = new ObjectDecl( alignofName( unionDecl->get_name() ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType->clone(), 0 ); 527 534 layoutFnType->get_parameters().push_back( alignParam ); 528 535 addOtypeParams( layoutFnType, otypeParams ); 529 536 530 537 // build function decl 531 FunctionDecl *layoutDecl = buildLayoutFunctionDecl( unionDecl ->get_name(), functionNesting, layoutFnType );538 FunctionDecl *layoutDecl = buildLayoutFunctionDecl( unionDecl, functionNesting, layoutFnType ); 532 539 533 540 // calculate union layout in function body … … 538 545 assert( dwt ); 539 546 Type *memberType = dwt->get_type(); 540 547 541 548 // take max member size and global size 542 549 addStmt( layoutDecl->get_statements(), makeAssignMax( derefVar( sizeParam ), new SizeofExpr( memberType->clone() ) ) ); 543 550 544 551 // take max of member alignment and global alignment 545 552 addStmt( layoutDecl->get_statements(), makeAssignMax( derefVar( alignParam ), new AlignofExpr( memberType->clone() ) ) ); … … 551 558 return unionDecl; 552 559 } 553 560 554 561 ////////////////////////////////////////// Pass1 //////////////////////////////////////////////////// 555 562 … … 612 619 return 0; 613 620 } 614 621 615 622 /// returns T if the given declaration is: (*?=?)(T *, T) for some type T (return not checked, but maybe should be), NULL otherwise 616 623 /// Only picks assignments where neither parameter is cv-qualified … … 624 631 Type *paramType2 = funType->get_parameters().back()->get_type(); 625 632 if ( paramType2->get_qualifiers() != defaultQualifiers ) return 0; 626 633 627 634 if ( PointerType *pointerType = dynamic_cast< PointerType* >( paramType1 ) ) { 628 635 Type *baseType1 = pointerType->get_base(); … … 653 660 654 661 DeclarationWithType *Pass1::mutate( FunctionDecl *functionDecl ) { 655 // if this is a polymorphicassignment function, put it in the map for this scope662 // if this is a assignment function, put it in the map for this scope 656 663 if ( Type *assignedType = isAssignment( functionDecl ) ) { 657 664 if ( ! dynamic_cast< TypeInstType* >( assignedType ) ) { … … 662 669 if ( functionDecl->get_statements() ) { // empty routine body ? 663 670 doBeginScope(); 664 TyVarMap oldtyVars = scopeTyVars;665 std::map< std::string, DeclarationWithType *> oldassignOps = assignOps;671 scopeTyVars.beginScope(); 672 assignOps.beginScope(); 666 673 DeclarationWithType *oldRetval = retval; 667 674 bool oldUseRetval = useRetval; … … 704 711 functionDecl->set_statements( functionDecl->get_statements()->acceptMutator( *this ) ); 705 712 706 scopeTyVars = oldtyVars; 707 assignOps = oldassignOps; 708 // std::cerr << "end FunctionDecl: "; 709 // for ( TyVarMap::iterator i = scopeTyVars.begin(); i != scopeTyVars.end(); ++i ) { 710 // std::cerr << i->first << " "; 711 // } 712 // std::cerr << "\n"; 713 scopeTyVars.endScope(); 714 assignOps.endScope(); 713 715 retval = oldRetval; 714 716 useRetval = oldUseRetval; … … 743 745 } 744 746 745 Expression *Pass1::makeOffsetArray( StructInstType *ty ) {746 std::list<Expression*> noDesignators;747 std::list< Declaration* > &baseMembers = ty->get_baseStruct()->get_members();748 749 // make a new temporary array750 Type *offsetType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );751 std::stringstream lenGen;752 lenGen << baseMembers.size();753 ConstantExpr *lenExpr = new ConstantExpr( Constant( offsetType->clone(), lenGen.str() ) );754 ObjectDecl *arrayTemp = makeTemporary( new ArrayType( Type::Qualifiers(), offsetType, lenExpr, false, false ) );755 756 // build initializer list for temporary757 std::list< Initializer* > inits;758 for ( std::list< Declaration* >::const_iterator member = baseMembers.begin(); member != baseMembers.end(); ++member ) {759 DeclarationWithType *memberDecl;760 if ( DeclarationWithType *origMember = dynamic_cast< DeclarationWithType* >( *member ) ) {761 memberDecl = origMember->clone();762 } else {763 memberDecl = new ObjectDecl( (*member)->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, offsetType->clone(), 0 );764 }765 inits.push_back( new SingleInit( new OffsetofExpr( ty->clone(), memberDecl ), noDesignators ) );766 }767 arrayTemp->set_init( new ListInit( inits, noDesignators ) );768 769 // return variable pointing to temporary770 return new VariableExpr( arrayTemp );771 }772 773 747 void Pass1::passArgTypeVars( ApplicationExpr *appExpr, Type *parmType, Type *argBaseType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars, std::set< std::string > &seenTypes ) { 774 Type *poly Base = hasPolyBase( parmType, exprTyVars );775 if ( poly Base && ! dynamic_cast< TypeInstType* >( polyBase ) ) {776 std::string sizeName = sizeofName( polyBase );777 if ( seenTypes.count( sizeName ) ) return;748 Type *polyType = isPolyType( parmType, exprTyVars ); 749 if ( polyType && ! dynamic_cast< TypeInstType* >( polyType ) ) { 750 std::string typeName = mangleType( polyType ); 751 if ( seenTypes.count( typeName ) ) return; 778 752 779 753 arg = appExpr->get_args().insert( arg, new SizeofExpr( argBaseType->clone() ) ); … … 781 755 arg = appExpr->get_args().insert( arg, new AlignofExpr( argBaseType->clone() ) ); 782 756 arg++; 783 if ( dynamic_cast< StructInstType* >( poly Base ) ) {757 if ( dynamic_cast< StructInstType* >( polyType ) ) { 784 758 if ( StructInstType *argBaseStructType = dynamic_cast< StructInstType* >( argBaseType ) ) { 785 arg = appExpr->get_args().insert( arg, makeOffsetArray( argBaseStructType ) ); 786 arg++; 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 } 787 764 } else { 788 765 throw SemanticError( "Cannot pass non-struct type for generic struct" ); … … 790 767 } 791 768 792 seenTypes.insert( sizeName );769 seenTypes.insert( typeName ); 793 770 } 794 771 } … … 826 803 passArgTypeVars( appExpr, polyRetType, concRetType, arg, exprTyVars, seenTypes ); 827 804 } 828 805 829 806 // add type information args for presently unseen types in parameter list 830 807 for ( ; fnParm != funcType->get_parameters().end() && fnArg != appExpr->get_args().end(); ++fnParm, ++fnArg ) { … … 905 882 assert( env ); 906 883 Type *concrete = replaceWithConcrete( appExpr, polyType ); 907 // add out-parameter for return value 884 // add out-parameter for return value 908 885 return addRetParam( appExpr, function, concrete, arg ); 909 886 } … … 932 909 return; 933 910 } else if ( arg->get_results().front()->get_isLvalue() ) { 934 // VariableExpr and MemberExpr are lvalues 935 arg = new AddressExpr( arg ); 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 } 936 917 } else { 937 918 // use type computed in unification to declare boxed variables … … 1028 1009 } // for 1029 1010 } 1030 1031 1032 1011 1033 1012 FunctionDecl *Pass1::makeAdapter( FunctionType *adaptee, FunctionType *realType, const std::string &mangleName, const TyVarMap &tyVars ) { … … 1146 1125 addAssign->get_args().push_back( appExpr->get_args().front() ); 1147 1126 } // if 1148 addAssign->get_args().push_back( new NameExpr( sizeofName( polyType) ) );1127 addAssign->get_args().push_back( new NameExpr( sizeofName( mangleType( polyType ) ) ) ); 1149 1128 addAssign->get_results().front() = appExpr->get_results().front()->clone(); 1150 1129 if ( appExpr->get_env() ) { … … 1173 1152 UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) ); 1174 1153 multiply->get_args().push_back( appExpr->get_args().back() ); 1175 multiply->get_args().push_back( new NameExpr( sizeofName( baseType1) ) );1154 multiply->get_args().push_back( new SizeofExpr( baseType1->clone() ) ); 1176 1155 ret->get_args().push_back( appExpr->get_args().front() ); 1177 1156 ret->get_args().push_back( multiply ); … … 1179 1158 UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) ); 1180 1159 multiply->get_args().push_back( appExpr->get_args().front() ); 1181 multiply->get_args().push_back( new NameExpr( sizeofName( baseType2) ) );1160 multiply->get_args().push_back( new SizeofExpr( baseType2->clone() ) ); 1182 1161 ret->get_args().push_back( multiply ); 1183 1162 ret->get_args().push_back( appExpr->get_args().back() ); … … 1242 1221 UntypedExpr *divide = new UntypedExpr( new NameExpr( "?/?" ) ); 1243 1222 divide->get_args().push_back( appExpr ); 1244 divide->get_args().push_back( new NameExpr( sizeofName( baseType1) ) );1223 divide->get_args().push_back( new SizeofExpr( baseType1->clone() ) ); 1245 1224 divide->get_results().push_front( appExpr->get_results().front()->clone() ); 1246 1225 if ( appExpr->get_env() ) { … … 1252 1231 UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) ); 1253 1232 multiply->get_args().push_back( appExpr->get_args().back() ); 1254 multiply->get_args().push_back( new NameExpr( sizeofName( baseType1) ) );1233 multiply->get_args().push_back( new SizeofExpr( baseType1->clone() ) ); 1255 1234 appExpr->get_args().back() = multiply; 1256 1235 } else if ( baseType2 ) { 1257 1236 UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) ); 1258 1237 multiply->get_args().push_back( appExpr->get_args().front() ); 1259 multiply->get_args().push_back( new NameExpr( sizeofName( baseType2) ) );1238 multiply->get_args().push_back( new SizeofExpr( baseType2->clone() ) ); 1260 1239 appExpr->get_args().front() = multiply; 1261 1240 } // if … … 1267 1246 UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) ); 1268 1247 multiply->get_args().push_back( appExpr->get_args().back() ); 1269 multiply->get_args().push_back( new NameExpr( sizeofName( baseType) ) );1248 multiply->get_args().push_back( new SizeofExpr( baseType->clone() ) ); 1270 1249 appExpr->get_args().back() = multiply; 1271 1250 } // if … … 1304 1283 std::list< Expression *>::iterator paramBegin = appExpr->get_args().begin(); 1305 1284 1306 TyVarMap exprTyVars ;1285 TyVarMap exprTyVars( (TypeDecl::Kind)-1 ); 1307 1286 makeTyVarMap( function, exprTyVars ); 1308 1287 ReferenceToType *polyRetType = isPolyRet( function ); … … 1327 1306 1328 1307 boxParams( appExpr, function, arg, exprTyVars ); 1329 1330 1308 passAdapters( appExpr, function, exprTyVars ); 1331 1309 … … 1388 1366 return new VariableExpr( functionObj ); 1389 1367 } 1390 1368 1391 1369 Statement * Pass1::mutate( ReturnStmt *returnStmt ) { 1392 1370 if ( retval && returnStmt->get_expr() ) { … … 1407 1385 if ( TypeInstType *typeInst = dynamic_cast< TypeInstType *>( retval->get_type() ) ) { 1408 1386 // find assignment operator for type variable 1409 std::map< std::string, DeclarationWithType *>::const_iterator assignIter = assignOps.find( typeInst->get_name() );1387 ScopedMap< std::string, DeclarationWithType *>::const_iterator assignIter = assignOps.find( typeInst->get_name() ); 1410 1388 if ( assignIter == assignOps.end() ) { 1411 1389 throw SemanticError( "Attempt to return dtype or ftype object in ", returnStmt->get_expr() ); … … 1429 1407 std::list< TypeDecl* >::const_iterator forallIt = forallParams.begin(); 1430 1408 for ( ; tyIt != tyParams.end() && forallIt != forallParams.end(); ++tyIt, ++forallIt ) { 1431 if ( (*forallIt)->get_kind() != TypeDecl::Any ) continue; // skip types with no assign op (ftype/dtype) 1432 1433 std::list< DeclarationWithType* > &asserts = (*forallIt)->get_assertions(); 1434 assert( ! asserts.empty() && "Type param needs assignment operator assertion" ); 1435 DeclarationWithType *actualDecl = asserts.front(); 1436 TypeInstType *actualType = isTypeInstAssignment( actualDecl ); 1437 assert( actualType && "First assertion of type with assertions should be assignment operator" ); 1409 // Add appropriate mapping to assignment expression environment 1438 1410 TypeExpr *formalTypeExpr = dynamic_cast< TypeExpr* >( *tyIt ); 1439 1411 assert( formalTypeExpr && "type parameters must be type expressions" ); 1440 1412 Type *formalType = formalTypeExpr->get_type(); 1441 assignExpr->get_env()->add( actualType->get_name(), formalType ); 1442 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 1443 1419 DeclarationWithType *assertAssign = 0; 1444 1420 if ( TypeInstType *formalTypeInstType = dynamic_cast< TypeInstType* >( formalType ) ) { 1445 std::map< std::string, DeclarationWithType *>::const_iterator assertAssignIt = assignOps.find( formalTypeInstType->get_name() );1421 ScopedMap< std::string, DeclarationWithType *>::const_iterator assertAssignIt = assignOps.find( formalTypeInstType->get_name() ); 1446 1422 if ( assertAssignIt == assignOps.end() ) { 1447 1423 throw SemanticError( "No assignment operation found for ", formalTypeInstType ); … … 1454 1430 } 1455 1431 } 1456 1457 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(); 1458 1437 assignExpr->get_inferParams()[ actualDecl->get_uniqueId() ] 1459 1438 = ParamEntry( assertAssign->get_uniqueId(), assertAssign->get_type()->clone(), actualDecl->get_type()->clone(), wrapFunctionDecl( assertAssign ) ); … … 1481 1460 1482 1461 Type * Pass1::mutate( PointerType *pointerType ) { 1483 TyVarMap oldtyVars = scopeTyVars;1462 scopeTyVars.beginScope(); 1484 1463 makeTyVarMap( pointerType, scopeTyVars ); 1485 1464 1486 1465 Type *ret = Mutator::mutate( pointerType ); 1487 1466 1488 scopeTyVars = oldtyVars;1467 scopeTyVars.endScope(); 1489 1468 return ret; 1490 1469 } 1491 1470 1492 1471 Type * Pass1::mutate( FunctionType *functionType ) { 1493 TyVarMap oldtyVars = scopeTyVars;1472 scopeTyVars.beginScope(); 1494 1473 makeTyVarMap( functionType, scopeTyVars ); 1495 1474 1496 1475 Type *ret = Mutator::mutate( functionType ); 1497 1476 1498 scopeTyVars = oldtyVars;1477 scopeTyVars.endScope(); 1499 1478 return ret; 1500 1479 } … … 1561 1540 1562 1541 Type * Pass2::mutate( PointerType *pointerType ) { 1563 TyVarMap oldtyVars = scopeTyVars;1542 scopeTyVars.beginScope(); 1564 1543 makeTyVarMap( pointerType, scopeTyVars ); 1565 1544 1566 1545 Type *ret = Mutator::mutate( pointerType ); 1567 1546 1568 scopeTyVars = oldtyVars;1547 scopeTyVars.endScope(); 1569 1548 return ret; 1570 1549 } 1571 1550 1572 1551 Type *Pass2::mutate( FunctionType *funcType ) { 1573 TyVarMap oldtyVars = scopeTyVars;1552 scopeTyVars.beginScope(); 1574 1553 makeTyVarMap( funcType, scopeTyVars ); 1575 1554 … … 1588 1567 ObjectDecl newPtr( "", DeclarationNode::NoStorageClass, LinkageSpec::C, 0, 1589 1568 new PointerType( Type::Qualifiers(), new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) ), 0 ); 1590 // ObjectDecl *newFunPtr = new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), new FunctionType( Type::Qualifiers(), true ) ), 0 );1591 1569 for ( std::list< TypeDecl *>::const_iterator tyParm = funcType->get_forall().begin(); tyParm != funcType->get_forall().end(); ++tyParm ) { 1592 1570 ObjectDecl *sizeParm, *alignParm; … … 1594 1572 if ( (*tyParm)->get_kind() == TypeDecl::Any ) { 1595 1573 TypeInstType parmType( Type::Qualifiers(), (*tyParm)->get_name(), *tyParm ); 1574 std::string parmName = mangleType( &parmType ); 1596 1575 1597 1576 sizeParm = newObj.clone(); 1598 sizeParm->set_name( sizeofName( &parmType ) );1577 sizeParm->set_name( sizeofName( parmName ) ); 1599 1578 last = funcType->get_parameters().insert( last, sizeParm ); 1600 1579 ++last; 1601 1580 1602 1581 alignParm = newObj.clone(); 1603 alignParm->set_name( alignofName( &parmType ) );1582 alignParm->set_name( alignofName( parmName ) ); 1604 1583 last = funcType->get_parameters().insert( last, alignParm ); 1605 1584 ++last; … … 1616 1595 std::set< std::string > seenTypes; // sizeofName for generic types we've seen 1617 1596 for ( std::list< DeclarationWithType* >::const_iterator fnParm = last; fnParm != funcType->get_parameters().end(); ++fnParm ) { 1618 Type *poly Base = hasPolyBase( (*fnParm)->get_type(), scopeTyVars );1619 if ( poly Base && ! dynamic_cast< TypeInstType* >( polyBase ) ) {1620 std::string sizeName = sizeofName( polyBase );1621 if ( seenTypes.count( sizeName ) ) continue;1597 Type *polyType = isPolyType( (*fnParm)->get_type(), scopeTyVars ); 1598 if ( polyType && ! dynamic_cast< TypeInstType* >( polyType ) ) { 1599 std::string typeName = mangleType( polyType ); 1600 if ( seenTypes.count( typeName ) ) continue; 1622 1601 1623 1602 ObjectDecl *sizeParm, *alignParm, *offsetParm; 1624 1603 sizeParm = newObj.clone(); 1625 sizeParm->set_name( size Name);1604 sizeParm->set_name( sizeofName( typeName ) ); 1626 1605 last = funcType->get_parameters().insert( last, sizeParm ); 1627 1606 ++last; 1628 1607 1629 1608 alignParm = newObj.clone(); 1630 alignParm->set_name( alignofName( polyBase ) );1609 alignParm->set_name( alignofName( typeName ) ); 1631 1610 last = funcType->get_parameters().insert( last, alignParm ); 1632 1611 ++last; 1633 1612 1634 if ( dynamic_cast< StructInstType* >( polyBase ) ) { 1635 offsetParm = newPtr.clone(); 1636 offsetParm->set_name( offsetofName( polyBase ) ); 1637 last = funcType->get_parameters().insert( last, offsetParm ); 1638 ++last; 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 } 1639 1621 } 1640 1622 1641 seenTypes.insert( sizeName );1623 seenTypes.insert( typeName ); 1642 1624 } 1643 1625 } … … 1649 1631 mutateAll( funcType->get_parameters(), *this ); 1650 1632 1651 scopeTyVars = oldtyVars;1633 scopeTyVars.endScope(); 1652 1634 return funcType; 1653 1635 } … … 1842 1824 } 1843 1825 1844 ////////////////////////////////////////// MemberExprFixer //////////////////////////////////////////////////// 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 } 1845 1836 1846 1837 template< typename DeclClass > 1847 DeclClass * MemberExprFixer::handleDecl( DeclClass *decl, Type *type ) { 1848 TyVarMap oldtyVars = scopeTyVars; 1849 makeTyVarMap( type, scopeTyVars ); 1838 DeclClass * PolyGenericCalculator::handleDecl( DeclClass *decl, Type *type ) { 1839 beginTypeScope( type ); 1840 knownLayouts.beginScope(); 1841 knownOffsets.beginScope(); 1850 1842 1851 1843 DeclClass *ret = static_cast< DeclClass *>( Mutator::mutate( decl ) ); 1852 1844 1853 scopeTyVars = oldtyVars; 1845 knownOffsets.endScope(); 1846 knownLayouts.endScope(); 1847 endTypeScope(); 1854 1848 return ret; 1855 1849 } 1856 1850 1857 ObjectDecl * MemberExprFixer::mutate( ObjectDecl *objectDecl ) {1851 ObjectDecl * PolyGenericCalculator::mutate( ObjectDecl *objectDecl ) { 1858 1852 return handleDecl( objectDecl, objectDecl->get_type() ); 1859 1853 } 1860 1854 1861 DeclarationWithType * MemberExprFixer::mutate( FunctionDecl *functionDecl ) {1855 DeclarationWithType * PolyGenericCalculator::mutate( FunctionDecl *functionDecl ) { 1862 1856 return handleDecl( functionDecl, functionDecl->get_functionType() ); 1863 1857 } 1864 1858 1865 TypedefDecl * MemberExprFixer::mutate( TypedefDecl *typedefDecl ) {1859 TypedefDecl * PolyGenericCalculator::mutate( TypedefDecl *typedefDecl ) { 1866 1860 return handleDecl( typedefDecl, typedefDecl->get_base() ); 1867 1861 } 1868 1862 1869 TypeDecl * MemberExprFixer::mutate( TypeDecl *typeDecl ) {1863 TypeDecl * PolyGenericCalculator::mutate( TypeDecl *typeDecl ) { 1870 1864 scopeTyVars[ typeDecl->get_name() ] = typeDecl->get_kind(); 1871 1865 return Mutator::mutate( typeDecl ); 1872 1866 } 1873 1867 1874 Type * MemberExprFixer::mutate( PointerType *pointerType ) { 1875 TyVarMap oldtyVars = scopeTyVars; 1876 makeTyVarMap( pointerType, scopeTyVars ); 1868 Type * PolyGenericCalculator::mutate( PointerType *pointerType ) { 1869 beginTypeScope( pointerType ); 1877 1870 1878 1871 Type *ret = Mutator::mutate( pointerType ); 1879 1872 1880 scopeTyVars = oldtyVars;1873 endTypeScope(); 1881 1874 return ret; 1882 1875 } 1883 1876 1884 Type * MemberExprFixer::mutate( FunctionType *functionType ) { 1885 TyVarMap oldtyVars = scopeTyVars; 1886 makeTyVarMap( functionType, scopeTyVars ); 1887 1888 Type *ret = Mutator::mutate( functionType ); 1889 1890 scopeTyVars = oldtyVars; 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(); 1891 1892 return ret; 1892 1893 } 1893 1894 1894 Statement * MemberExprFixer::mutate( DeclStmt *declStmt ) {1895 Statement *PolyGenericCalculator::mutate( DeclStmt *declStmt ) { 1895 1896 if ( ObjectDecl *objectDecl = dynamic_cast< ObjectDecl *>( declStmt->get_decl() ) ) { 1896 if ( isPolyType( objectDecl->get_type(), scopeTyVars) ) {1897 if ( findGeneric( objectDecl->get_type() ) ) { 1897 1898 // change initialization of a polymorphic value object 1898 1899 // to allocate storage with alloca 1899 1900 Type *declType = objectDecl->get_type(); 1900 1901 UntypedExpr *alloc = new UntypedExpr( new NameExpr( "__builtin_alloca" ) ); 1901 alloc->get_args().push_back( new NameExpr( sizeofName( declType) ) );1902 alloc->get_args().push_back( new NameExpr( sizeofName( mangleType( declType ) ) ) ); 1902 1903 1903 1904 delete objectDecl->get_init(); … … 1931 1932 ConstantExpr *fieldIndex = new ConstantExpr( Constant( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), offset_namer.str() ) ); 1932 1933 UntypedExpr *fieldOffset = new UntypedExpr( new NameExpr( "?[?]" ) ); 1933 fieldOffset->get_args().push_back( new NameExpr( offsetofName( objectType) ) );1934 fieldOffset->get_args().push_back( new NameExpr( offsetofName( mangleType( objectType ) ) ) ); 1934 1935 fieldOffset->get_args().push_back( fieldIndex ); 1935 1936 return fieldOffset; … … 1946 1947 } 1947 1948 1948 Expression * MemberExprFixer::mutate( MemberExpr *memberExpr ) {1949 Expression *PolyGenericCalculator::mutate( MemberExpr *memberExpr ) { 1949 1950 // mutate, exiting early if no longer MemberExpr 1950 1951 Expression *expr = Mutator::mutate( memberExpr ); … … 1963 1964 Type *objectType = hasPolyBase( objectDecl->get_type(), scopeTyVars, &tyDepth ); 1964 1965 if ( ! objectType ) return memberExpr; 1966 findGeneric( objectType ); // ensure layout for this type is available 1965 1967 1966 1968 Expression *newMemberExpr = 0; … … 1994 1996 } 1995 1997 1996 Expression *MemberExprFixer::mutate( OffsetofExpr *offsetofExpr ) { 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 ) { 1997 2138 // mutate, exiting early if no longer OffsetofExpr 1998 2139 Expression *expr = Mutator::mutate( offsetofExpr ); … … 2001 2142 2002 2143 // only mutate expressions for polymorphic structs/unions 2003 Type *ty = isPolyType( offsetofExpr->get_type(), scopeTyVars);2004 if ( ! ty) return offsetofExpr;2144 Type *ty = offsetofExpr->get_type(); 2145 if ( ! findGeneric( ty ) ) return offsetofExpr; 2005 2146 2006 2147 if ( StructInstType *structType = dynamic_cast< StructInstType* >( ty ) ) { … … 2019 2160 } 2020 2161 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 information 2168 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 type 2173 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 array 2181 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 it 2193 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 2021 2213 ////////////////////////////////////////// Pass3 //////////////////////////////////////////////////// 2022 2214 2023 2215 template< typename DeclClass > 2024 2216 DeclClass * Pass3::handleDecl( DeclClass *decl, Type *type ) { 2025 TyVarMap oldtyVars = scopeTyVars;2217 scopeTyVars.beginScope(); 2026 2218 makeTyVarMap( type, scopeTyVars ); 2027 2219 … … 2029 2221 ScrubTyVars::scrub( decl, scopeTyVars ); 2030 2222 2031 scopeTyVars = oldtyVars;2223 scopeTyVars.endScope(); 2032 2224 return ret; 2033 2225 } … … 2059 2251 2060 2252 Type * Pass3::mutate( PointerType *pointerType ) { 2061 TyVarMap oldtyVars = scopeTyVars;2253 scopeTyVars.beginScope(); 2062 2254 makeTyVarMap( pointerType, scopeTyVars ); 2063 2255 2064 2256 Type *ret = Mutator::mutate( pointerType ); 2065 2257 2066 scopeTyVars = oldtyVars;2258 scopeTyVars.endScope(); 2067 2259 return ret; 2068 2260 } 2069 2261 2070 2262 Type * Pass3::mutate( FunctionType *functionType ) { 2071 TyVarMap oldtyVars = scopeTyVars;2263 scopeTyVars.beginScope(); 2072 2264 makeTyVarMap( functionType, scopeTyVars ); 2073 2265 2074 2266 Type *ret = Mutator::mutate( functionType ); 2075 2267 2076 scopeTyVars = oldtyVars;2268 scopeTyVars.endScope(); 2077 2269 return ret; 2078 2270 } -
src/GenPoly/FindFunction.cc
rdb4ecc5 r70a06f6 55 55 TyVarMap::iterator var = tyVars.find( (*i)->get_name() ); 56 56 if ( var != tyVars.end() ) { 57 tyVars.erase( var );57 tyVars.erase( var->first ); 58 58 } // if 59 59 } // for … … 61 61 62 62 Type * FindFunction::mutate( FunctionType *functionType ) { 63 TyVarMap oldTyVars = tyVars;63 tyVars.beginScope(); 64 64 handleForall( functionType->get_forall() ); 65 65 mutateAll( functionType->get_returnVals(), *this ); … … 72 72 } // if 73 73 } // if 74 tyVars = oldTyVars;74 tyVars.endScope(); 75 75 return ret; 76 76 } 77 77 78 78 Type * FindFunction::mutate( PointerType *pointerType ) { 79 TyVarMap oldTyVars = tyVars;79 tyVars.beginScope(); 80 80 handleForall( pointerType->get_forall() ); 81 81 Type *ret = Mutator::mutate( pointerType ); 82 tyVars = oldTyVars;82 tyVars.endScope(); 83 83 return ret; 84 84 } -
src/GenPoly/GenPoly.cc
rdb4ecc5 r70a06f6 16 16 #include "GenPoly.h" 17 17 18 #include "SymTab/Mangler.h"19 18 #include "SynTree/Expression.h" 20 19 #include "SynTree/Type.h" … … 38 37 ReferenceToType *isPolyRet( FunctionType *function ) { 39 38 if ( ! function->get_returnVals().empty() ) { 40 TyVarMap forallTypes ;39 TyVarMap forallTypes( (TypeDecl::Kind)-1 ); 41 40 makeTyVarMap( function, forallTypes ); 42 41 return (ReferenceToType*)isPolyType( function->get_returnVals().front()->get_type(), forallTypes ); … … 218 217 } 219 218 220 std::string sizeofName( Type *ty ) {221 return std::string( "_sizeof_" ) + SymTab::Mangler::mangleType( ty );222 }223 224 std::string alignofName( Type *ty ) {225 return std::string( "_alignof_" ) + SymTab::Mangler::mangleType( ty );226 }227 228 std::string offsetofName( Type* ty ) {229 return std::string( "_offsetof_" ) + SymTab::Mangler::mangleType( ty );230 }231 232 219 } // namespace GenPoly 233 220 -
src/GenPoly/GenPoly.h
rdb4ecc5 r70a06f6 17 17 #define GENPOLY_H 18 18 19 #include <map>20 19 #include <string> 21 20 #include <iostream> 22 21 #include <utility> 22 23 #include "ErasableScopedMap.h" 24 25 #include "SymTab/Mangler.h" 23 26 24 27 #include "SynTree/Declaration.h" … … 27 30 28 31 namespace GenPoly { 29 typedef std::map< std::string, TypeDecl::Kind > TyVarMap;32 typedef ErasableScopedMap< std::string, TypeDecl::Kind > TyVarMap; 30 33 31 34 /// A function needs an adapter if it returns a polymorphic value or if any of its … … 69 72 void printTyVarMap( std::ostream &os, const TyVarMap &tyVarMap ); 70 73 71 /// Gets the name of the sizeof parameter for the type 72 std::string sizeofName( Type *ty ); 74 /// Gets the mangled name of this type; alias for SymTab::Mangler::mangleType(). 75 inline std::string mangleType( Type *ty ) { return SymTab::Mangler::mangleType( ty ); } 76 77 /// Gets the name of the sizeof parameter for the type, given its mangled name 78 inline std::string sizeofName( const std::string &name ) { return std::string( "_sizeof_" ) + name; } 73 79 74 /// Gets the name of the alignof parameter for the type 75 std::string alignofName( Type *ty );80 /// Gets the name of the alignof parameter for the type, given its mangled name 81 inline std::string alignofName( const std::string &name ) { return std::string( "_alignof_" ) + name; } 76 82 77 /// Gets the name of the offsetof parameter for the type 78 std::string offsetofName( Type *ty ); 83 /// Gets the name of the offsetof parameter for the type, given its mangled name 84 inline std::string offsetofName( const std::string &name ) { return std::string( "_offsetof_" ) + name; } 85 86 /// Gets the name of the layout function for a given aggregate type, given its declaration 87 inline std::string layoutofName( AggregateDecl *decl ) { return std::string( "_layoutof_" ) + decl->get_name(); } 88 79 89 } // namespace GenPoly 80 90 -
src/GenPoly/Lvalue.cc
rdb4ecc5 r70a06f6 17 17 18 18 #include "Lvalue.h" 19 20 #include "GenPoly.h" 19 21 20 22 #include "SynTree/Declaration.h" … … 63 65 64 66 namespace { 65 bool isLvalueRet( FunctionType *function ) { 66 if ( ! function->get_returnVals().empty() ) { 67 return function->get_returnVals().front()->get_type()->get_isLvalue(); 68 } else { 69 return false; 70 } // if 67 Type* isLvalueRet( FunctionType *function ) { 68 if ( function->get_returnVals().empty() ) return 0; 69 Type *ty = function->get_returnVals().front()->get_type(); 70 return ty->get_isLvalue() ? ty : 0; 71 71 } 72 72 … … 107 107 assert( function ); 108 108 109 std::string typeName; 110 if ( isLvalueRet( function ) && ! isIntrinsicApp( appExpr ) ) { 109 Type *funType = isLvalueRet( function ); 110 if ( funType && ! isIntrinsicApp( appExpr ) ) { 111 Expression *expr = appExpr; 112 Type *appType = appExpr->get_results().front(); 113 if ( isPolyType( funType ) && ! isPolyType( appType ) ) { 114 // make sure cast for polymorphic type is inside dereference 115 expr = new CastExpr( appExpr, new PointerType( Type::Qualifiers(), appType->clone() ) ); 116 } 111 117 UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) ); 112 deref->get_results().push_back( app Expr->get_results().front() );113 appExpr->get_results().front() = new PointerType( Type::Qualifiers(), deref->get_results().front()->clone());114 deref->get_args().push_back( appExpr );118 deref->get_results().push_back( appType->clone() ); 119 appExpr->get_results().front() = new PointerType( Type::Qualifiers(), appType ); 120 deref->get_args().push_back( expr ); 115 121 return deref; 116 122 } else { -
src/GenPoly/PolyMutator.cc
rdb4ecc5 r70a06f6 27 27 } 28 28 29 PolyMutator::PolyMutator() : env( 0 ) { 30 } 29 PolyMutator::PolyMutator() : scopeTyVars( (TypeDecl::Kind)-1 ), env( 0 ) {} 31 30 32 31 void PolyMutator::mutateStatementList( std::list< Statement* > &statements ) { -
src/GenPoly/ScopedMap.h
rdb4ecc5 r70a06f6 17 17 #define _SCOPEDMAP_H 18 18 19 #include <cassert> 19 20 #include <iterator> 20 21 #include <map> … … 50 51 typedef typename scope_list::size_type size_type; 51 52 53 /// Checks if this iterator points to a valid item 54 bool is_valid() const { 55 return it != (*scopes)[i].end(); 56 } 57 58 /// Increments on invalid 59 iterator& next_valid() { 60 if ( ! is_valid() ) { ++(*this); } 61 return *this; 62 } 63 64 /// Decrements on invalid 65 iterator& prev_valid() { 66 if ( ! is_valid() ) { --(*this); } 67 return *this; 68 } 69 52 70 iterator(scope_list const &_scopes, const wrapped_iterator &_it, size_type _i) 53 71 : scopes(&_scopes), it(_it), i(_i) {} … … 67 85 --i; 68 86 it = (*scopes)[i].begin(); 69 return *this;70 }71 ++it;72 return *this;87 } else { 88 ++it; 89 } 90 return next_valid(); 73 91 } 74 92 iterator& operator++ (int) { iterator tmp = *this; ++(*this); return tmp; } … … 81 99 } 82 100 --it; 83 return *this;101 return prev_valid(); 84 102 } 85 103 iterator& operator-- (int) { iterator tmp = *this; --(*this); return tmp; } … … 104 122 typedef typename scope_list::size_type size_type; 105 123 124 /// Checks if this iterator points to a valid item 125 bool is_valid() const { 126 return it != (*scopes)[i].end(); 127 } 128 129 /// Increments on invalid 130 const_iterator& next_valid() { 131 if ( ! is_valid() ) { ++(*this); } 132 return *this; 133 } 134 135 /// Decrements on invalid 136 const_iterator& prev_valid() { 137 if ( ! is_valid() ) { --(*this); } 138 return *this; 139 } 140 106 141 const_iterator(scope_list const &_scopes, const wrapped_const_iterator &_it, size_type _i) 107 142 : scopes(&_scopes), it(_it), i(_i) {} … … 126 161 --i; 127 162 it = (*scopes)[i].begin(); 128 return *this;129 }130 ++it;131 return *this;163 } else { 164 ++it; 165 } 166 return next_valid(); 132 167 } 133 168 const_iterator& operator++ (int) { const_iterator tmp = *this; ++(*this); return tmp; } … … 140 175 } 141 176 --it; 142 return *this;177 return prev_valid(); 143 178 } 144 179 const_iterator& operator-- (int) { const_iterator tmp = *this; --(*this); return tmp; } … … 164 199 void endScope() { 165 200 scopes.pop_back(); 201 assert( ! scopes.empty() ); 166 202 } 167 203 … … 169 205 ScopedMap() { beginScope(); } 170 206 171 iterator begin() { return iterator(scopes, scopes.back().begin(), scopes.size()-1) ; }172 const_iterator begin() const { return const_iterator(scopes, scopes.back().begin(), scopes.size()-1) ; }173 const_iterator cbegin() const { return const_iterator(scopes, scopes.back().begin(), scopes.size()-1) ; }207 iterator begin() { return iterator(scopes, scopes.back().begin(), scopes.size()-1).next_valid(); } 208 const_iterator begin() const { return const_iterator(scopes, scopes.back().begin(), scopes.size()-1).next_valid(); } 209 const_iterator cbegin() const { return const_iterator(scopes, scopes.back().begin(), scopes.size()-1).next_valid(); } 174 210 iterator end() { return iterator(scopes, scopes[0].end(), 0); } 175 211 const_iterator end() const { return const_iterator(scopes, scopes[0].end(), 0); } … … 188 224 return end(); 189 225 } 190 const_iterator find( const Key &key ) const { return const_iterator( find( key ) ); } 226 const_iterator find( const Key &key ) const { 227 return const_iterator( const_cast< ScopedMap< Key, Value >* >(this)->find( key ) ); 228 } 191 229 192 230 /// Finds the given key in the outermost scope inside the given scope where it occurs … … 200 238 return end(); 201 239 } 202 const_iterator findNext( const_iterator &it, const Key &key ) const { return const_iterator( findNext( it, key ) ); } 240 const_iterator findNext( const_iterator &it, const Key &key ) const { 241 return const_iterator( const_cast< ScopedMap< Key, Value >* >(this)->findNext( it, key ) ); 242 } 203 243 204 244 /// Inserts the given key-value pair into the outermost scope … … 208 248 } 209 249 std::pair< iterator, bool > insert( const Key &key, const Value &value ) { return insert( std::make_pair( key, value ) ); } 210 250 251 Value& operator[] ( const Key &key ) { 252 iterator slot = find( key ); 253 if ( slot != end() ) return slot->second; 254 return insert( key, Value() ).first->second; 255 } 211 256 }; 212 257 } // namespace GenPoly -
src/GenPoly/ScrubTyVars.cc
rdb4ecc5 r70a06f6 64 64 // sizeof( T ) => _sizeof_T parameter, which is the size of T 65 65 if ( Type *polyType = isPolyType( szeof->get_type() ) ) { 66 Expression *expr = new NameExpr( sizeofName( polyType) );66 Expression *expr = new NameExpr( sizeofName( mangleType( polyType ) ) ); 67 67 return expr; 68 68 } else { … … 74 74 // alignof( T ) => _alignof_T parameter, which is the alignment of T 75 75 if ( Type *polyType = isPolyType( algnof->get_type() ) ) { 76 Expression *expr = new NameExpr( alignofName( polyType) );76 Expression *expr = new NameExpr( alignofName( mangleType( polyType ) ) ); 77 77 return expr; 78 78 } else {
Note:
See TracChangeset
for help on using the changeset viewer.