Changes in src/GenPoly/Box.cc [c29d9ce:9799ec8]
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/GenPoly/Box.cc
rc29d9ce r9799ec8 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // Box.cc -- 7 // Box.cc -- 8 8 // 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Rob Schluntz12 // Last Modified On : Tue Aug 11 16:22:35 201513 // Update Count : 8911 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Jun 29 21:43:03 2016 13 // Update Count : 296 14 14 // 15 15 16 #include <algorithm> 17 #include <iterator> 18 #include <list> 19 #include <map> 16 20 #include <set> 17 21 #include <stack> 18 22 #include <string> 19 #include < iterator>20 #include < algorithm>23 #include <utility> 24 #include <vector> 21 25 #include <cassert> 22 26 23 27 #include "Box.h" 28 #include "DeclMutator.h" 24 29 #include "PolyMutator.h" 25 30 #include "FindFunction.h" 31 #include "ScopedMap.h" 32 #include "ScopedSet.h" 26 33 #include "ScrubTyVars.h" 27 34 28 35 #include "Parser/ParseNode.h" 29 36 30 #include "SynTree/Type.h" 37 #include "SynTree/Constant.h" 38 #include "SynTree/Declaration.h" 31 39 #include "SynTree/Expression.h" 32 40 #include "SynTree/Initializer.h" 41 #include "SynTree/Mutator.h" 33 42 #include "SynTree/Statement.h" 34 #include "SynTree/Mutator.h" 43 #include "SynTree/Type.h" 44 #include "SynTree/TypeSubstitution.h" 35 45 36 46 #include "ResolvExpr/TypeEnvironment.h" 37 47 #include "ResolvExpr/TypeMap.h" 48 #include "ResolvExpr/typeops.h" 49 50 #include "SymTab/Indexer.h" 38 51 #include "SymTab/Mangler.h" 39 52 40 #include " SemanticError.h"41 #include " UniqueName.h"42 #include " utility.h"53 #include "Common/SemanticError.h" 54 #include "Common/UniqueName.h" 55 #include "Common/utility.h" 43 56 44 57 #include <ext/functional> // temporary … … 48 61 const std::list<Label> noLabels; 49 62 63 FunctionType *makeAdapterType( FunctionType *adaptee, const TyVarMap &tyVars ); 64 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 ) ) {} 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 parameters 111 }; 112 113 /// Maps a key and a TypeList to the some value, accounting for scope 114 template< typename Key, typename Value > 115 class InstantiationMap { 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 124 125 public: 126 /// Starts a new scope 127 void beginScope() { instantiations.beginScope(); } 128 129 /// Ends a scope 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; 140 } 141 } 142 // no matching instantiations found 143 return 0; 144 } 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 } 150 }; 151 152 /// Adds layout-generation functions to polymorphic types 153 class LayoutFunctionBuilder : public DeclMutator { 154 unsigned int functionNesting; // current level of nested functions 155 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 /// 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 50 164 class Pass1 : public PolyMutator { 51 165 public: … … 58 172 virtual Expression *mutate( CommaExpr *commaExpr ); 59 173 virtual Expression *mutate( ConditionalExpr *condExpr ); 60 virtual Statement * mutate(ReturnStmt *catchStmt);174 virtual Statement * mutate( ReturnStmt *returnStmt ); 61 175 virtual Type *mutate( PointerType *pointerType ); 62 virtual Type * mutate( FunctionType *pointerType );63 176 virtual Type * mutate( FunctionType *functionType ); 177 64 178 virtual void doBeginScope(); 65 179 virtual void doEndScope(); 66 180 private: 67 void passTypeVars( ApplicationExpr *appExpr, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars ); 181 /// Pass the extra type parameters from polymorphic generic arguments or return types into a function application 182 void passArgTypeVars( ApplicationExpr *appExpr, Type *parmType, Type *argBaseType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars, std::set< std::string > &seenTypes ); 183 /// passes extra type parameters into a polymorphic function application 184 void passTypeVars( ApplicationExpr *appExpr, ReferenceToType *polyRetType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars ); 185 /// wraps a function application with a new temporary for the out-parameter return value 68 186 Expression *addRetParam( ApplicationExpr *appExpr, FunctionType *function, Type *retType, std::list< Expression *>::iterator &arg ); 69 Expression *addPolyRetParam( ApplicationExpr *appExpr, FunctionType *function, std::string typeName, std::list< Expression *>::iterator &arg ); 187 /// Replaces all the type parameters of a generic type with their concrete equivalents under the current environment 188 void replaceParametersWithConcrete( ApplicationExpr *appExpr, std::list< Expression* >& params ); 189 /// Replaces a polymorphic type with its concrete equivalant under the current environment (returns itself if concrete). 190 /// If `doClone` is set to false, will not clone interior types 191 Type *replaceWithConcrete( ApplicationExpr *appExpr, Type *type, bool doClone = true ); 192 /// wraps a function application returning a polymorphic type with a new temporary for the out-parameter return value 193 Expression *addPolyRetParam( ApplicationExpr *appExpr, FunctionType *function, ReferenceToType *polyType, std::list< Expression *>::iterator &arg ); 70 194 Expression *applyAdapter( ApplicationExpr *appExpr, FunctionType *function, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars ); 71 195 void boxParam( Type *formal, Expression *&arg, const TyVarMap &exprTyVars ); 72 196 void boxParams( ApplicationExpr *appExpr, FunctionType *function, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars ); 73 197 void addInferredParams( ApplicationExpr *appExpr, FunctionType *functionType, std::list< Expression *>::iterator &arg, const TyVarMap &tyVars ); 74 void findAssignOps( const std::list< TypeDecl *> &forall ); 198 /// Stores assignment operators from assertion list in local map of assignment operations 199 void findTypeOps( const std::list< TypeDecl *> &forall ); 75 200 void passAdapters( ApplicationExpr *appExpr, FunctionType *functionType, const TyVarMap &exprTyVars ); 76 201 FunctionDecl *makeAdapter( FunctionType *adaptee, FunctionType *realType, const std::string &mangleName, const TyVarMap &tyVars ); 202 /// Replaces intrinsic operator functions with their arithmetic desugaring 77 203 Expression *handleIntrinsics( ApplicationExpr *appExpr ); 204 /// Inserts a new temporary variable into the current scope with an auto-generated name 78 205 ObjectDecl *makeTemporary( Type *type ); 79 206 80 typedef std::map< std::string, FunctionDecl *> AdapterMap; 81 std::map< std::string, DeclarationWithType *> assignOps; 82 std::stack< AdapterMap > adapters; 207 ScopedMap< std::string, DeclarationWithType* > assignOps; ///< Currently known type variable assignment operators 208 ScopedMap< std::string, DeclarationWithType* > ctorOps; ///< Currently known type variable constructors 209 ScopedMap< std::string, DeclarationWithType* > copyOps; ///< Currently known type variable copy constructors 210 ScopedMap< std::string, DeclarationWithType* > dtorOps; ///< Currently known type variable destructors 211 ResolvExpr::TypeMap< DeclarationWithType > scopedAssignOps; ///< Currently known assignment operators 212 ResolvExpr::TypeMap< DeclarationWithType > scopedCtorOps; ///< Currently known assignment operators 213 ResolvExpr::TypeMap< DeclarationWithType > scopedCopyOps; ///< Currently known assignment operators 214 ResolvExpr::TypeMap< DeclarationWithType > scopedDtorOps; ///< Currently known assignment operators 215 ScopedMap< std::string, DeclarationWithType* > adapters; ///< Set of adapter functions in the current scope 216 83 217 DeclarationWithType *retval; 84 218 bool useRetval; … … 86 220 }; 87 221 222 /// * Moves polymorphic returns in function types to pointer-type parameters 223 /// * adds type size and assertion parameters to parameter lists 88 224 class Pass2 : public PolyMutator { 89 225 public: 90 Pass2();91 226 template< typename DeclClass > 92 227 DeclClass *handleDecl( DeclClass *decl, Type *type ); … … 97 232 virtual Type *mutate( PointerType *pointerType ); 98 233 virtual Type *mutate( FunctionType *funcType ); 234 99 235 private: 100 236 void addAdapters( FunctionType *functionType ); 101 237 102 238 std::map< UniqueId, std::string > adapterName; 103 239 }; 104 240 105 class Pass3 : public PolyMutator { 106 public: 241 /// Mutator pass that replaces concrete instantiations of generic types with actual struct declarations, scoped appropriately 242 class GenericInstantiator : public DeclMutator { 243 /// Map of (generic type, parameter list) pairs to concrete type instantiations 244 InstantiationMap< AggregateDecl, AggregateDecl > instantiations; 245 /// Namer for concrete types 246 UniqueName typeNamer; 247 248 public: 249 GenericInstantiator() : DeclMutator(), instantiations(), typeNamer("_conc_") {} 250 251 virtual Type* mutate( StructInstType *inst ); 252 virtual Type* mutate( UnionInstType *inst ); 253 254 // virtual Expression* mutate( MemberExpr *memberExpr ); 255 256 virtual void doBeginScope(); 257 virtual void doEndScope(); 258 private: 259 /// Wrap instantiation lookup for structs 260 StructDecl* lookup( StructInstType *inst, const std::list< TypeExpr* > &typeSubs ) { return (StructDecl*)instantiations.lookup( inst->get_baseStruct(), typeSubs ); } 261 /// Wrap instantiation lookup for unions 262 UnionDecl* lookup( UnionInstType *inst, const std::list< TypeExpr* > &typeSubs ) { return (UnionDecl*)instantiations.lookup( inst->get_baseUnion(), typeSubs ); } 263 /// Wrap instantiation insertion for structs 264 void insert( StructInstType *inst, const std::list< TypeExpr* > &typeSubs, StructDecl *decl ) { instantiations.insert( inst->get_baseStruct(), typeSubs, decl ); } 265 /// Wrap instantiation insertion for unions 266 void insert( UnionInstType *inst, const std::list< TypeExpr* > &typeSubs, UnionDecl *decl ) { instantiations.insert( inst->get_baseUnion(), typeSubs, decl ); } 267 }; 268 269 /// Replaces member and size/align/offsetof expressions on polymorphic generic types with calculated expressions. 270 /// * Replaces member expressions for polymorphic types with calculated add-field-offset-and-dereference 271 /// * Calculates polymorphic offsetof expressions from offset array 272 /// * Inserts dynamic calculation of polymorphic type layouts where needed 273 class PolyGenericCalculator : public PolyMutator { 274 public: 107 275 template< typename DeclClass > 108 276 DeclClass *handleDecl( DeclClass *decl, Type *type ); … … 114 282 virtual Type *mutate( PointerType *pointerType ); 115 283 virtual Type *mutate( FunctionType *funcType ); 284 virtual Expression *mutate( MemberExpr *memberExpr ); 285 virtual Expression *mutate( SizeofExpr *sizeofExpr ); 286 virtual Expression *mutate( AlignofExpr *alignofExpr ); 287 virtual Expression *mutate( OffsetofExpr *offsetofExpr ); 288 virtual Expression *mutate( OffsetPackExpr *offsetPackExpr ); 289 290 virtual void doBeginScope(); 291 virtual void doEndScope(); 292 293 private: 294 /// Makes a new variable in the current scope with the given name, type & optional initializer 295 ObjectDecl *makeVar( const std::string &name, Type *type, Initializer *init = 0 ); 296 /// returns true if the type has a dynamic layout; such a layout will be stored in appropriately-named local variables when the function returns 297 bool findGeneric( Type *ty ); 298 /// adds type parameters to the layout call; will generate the appropriate parameters if needed 299 void addOtypeParamsToLayoutCall( UntypedExpr *layoutCall, const std::list< Type* > &otypeParams ); 300 301 /// Enters a new scope for type-variables, adding the type variables from ty 302 void beginTypeScope( Type *ty ); 303 /// Exits the type-variable scope 304 void endTypeScope(); 305 306 ScopedSet< std::string > knownLayouts; ///< Set of generic type layouts known in the current scope, indexed by sizeofName 307 ScopedSet< std::string > knownOffsets; ///< Set of non-generic types for which the offset array exists in the current scope, indexed by offsetofName 308 }; 309 310 /// Replaces initialization of polymorphic values with alloca, declaration of dtype/ftype with appropriate void expression, and sizeof expressions of polymorphic types with the proper variable 311 class Pass3 : public PolyMutator { 312 public: 313 template< typename DeclClass > 314 DeclClass *handleDecl( DeclClass *decl, Type *type ); 315 virtual DeclarationWithType *mutate( FunctionDecl *functionDecl ); 316 virtual ObjectDecl *mutate( ObjectDecl *objectDecl ); 317 virtual TypedefDecl *mutate( TypedefDecl *objectDecl ); 318 virtual TypeDecl *mutate( TypeDecl *objectDecl ); 319 virtual Type *mutate( PointerType *pointerType ); 320 virtual Type *mutate( FunctionType *funcType ); 116 321 private: 117 322 }; … … 119 324 } // anonymous namespace 120 325 121 void printAllNotBuiltin( const std::list< Declaration *>& translationUnit, std::ostream &os ) { 122 for ( std::list< Declaration *>::const_iterator i = translationUnit.begin(); i != translationUnit.end(); ++i ) { 123 if ( ! LinkageSpec::isBuiltin( (*i)->get_linkage() ) ) { 124 (*i)->print( os ); 125 os << std::endl; 126 } // if 326 /// version of mutateAll with special handling for translation unit so you can check the end of the prelude when debugging 327 template< typename MutatorType > 328 inline void mutateTranslationUnit( std::list< Declaration* > &translationUnit, MutatorType &mutator ) { 329 bool seenIntrinsic = false; 330 SemanticError errors; 331 for ( typename std::list< Declaration* >::iterator i = translationUnit.begin(); i != translationUnit.end(); ++i ) { 332 try { 333 if ( *i ) { 334 if ( (*i)->get_linkage() == LinkageSpec::Intrinsic ) { 335 seenIntrinsic = true; 336 } else if ( seenIntrinsic ) { 337 seenIntrinsic = false; // break on this line when debugging for end of prelude 338 } 339 340 *i = dynamic_cast< Declaration* >( (*i)->acceptMutator( mutator ) ); 341 assert( *i ); 342 } // if 343 } catch( SemanticError &e ) { 344 errors.append( e ); 345 } // try 127 346 } // for 347 if ( ! errors.isEmpty() ) { 348 throw errors; 349 } // if 128 350 } 129 351 130 352 void box( std::list< Declaration *>& translationUnit ) { 353 LayoutFunctionBuilder layoutBuilder; 131 354 Pass1 pass1; 132 355 Pass2 pass2; 356 GenericInstantiator instantiator; 357 PolyGenericCalculator polyCalculator; 133 358 Pass3 pass3; 134 mutateAll( translationUnit, pass1 ); 135 mutateAll( translationUnit, pass2 ); 136 mutateAll( translationUnit, pass3 ); 359 360 layoutBuilder.mutateDeclarationList( translationUnit ); 361 mutateTranslationUnit/*All*/( translationUnit, pass1 ); 362 mutateTranslationUnit/*All*/( translationUnit, pass2 ); 363 instantiator.mutateDeclarationList( translationUnit ); 364 mutateTranslationUnit/*All*/( translationUnit, polyCalculator ); 365 mutateTranslationUnit/*All*/( translationUnit, pass3 ); 137 366 } 138 367 368 ////////////////////////////////// LayoutFunctionBuilder //////////////////////////////////////////// 369 370 DeclarationWithType *LayoutFunctionBuilder::mutate( FunctionDecl *functionDecl ) { 371 functionDecl->set_functionType( maybeMutate( functionDecl->get_functionType(), *this ) ); 372 mutateAll( functionDecl->get_oldDecls(), *this ); 373 ++functionNesting; 374 functionDecl->set_statements( maybeMutate( functionDecl->get_statements(), *this ) ); 375 --functionNesting; 376 return functionDecl; 377 } 378 379 /// Get a list of type declarations that will affect a layout function 380 std::list< TypeDecl* > takeOtypeOnly( std::list< TypeDecl* > &decls ) { 381 std::list< TypeDecl * > otypeDecls; 382 383 for ( std::list< TypeDecl* >::const_iterator decl = decls.begin(); decl != decls.end(); ++decl ) { 384 if ( (*decl)->get_kind() == TypeDecl::Any ) { 385 otypeDecls.push_back( *decl ); 386 } 387 } 388 389 return otypeDecls; 390 } 391 392 /// Adds parameters for otype layout to a function type 393 void addOtypeParams( FunctionType *layoutFnType, std::list< TypeDecl* > &otypeParams ) { 394 BasicType sizeAlignType( Type::Qualifiers(), BasicType::LongUnsignedInt ); 395 396 for ( std::list< TypeDecl* >::const_iterator param = otypeParams.begin(); param != otypeParams.end(); ++param ) { 397 TypeInstType paramType( Type::Qualifiers(), (*param)->get_name(), *param ); 398 std::string paramName = mangleType( ¶mType ); 399 layoutFnType->get_parameters().push_back( new ObjectDecl( sizeofName( paramName ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignType.clone(), 0 ) ); 400 layoutFnType->get_parameters().push_back( new ObjectDecl( alignofName( paramName ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignType.clone(), 0 ) ); 401 } 402 } 403 404 /// Builds a layout function declaration 405 FunctionDecl *buildLayoutFunctionDecl( AggregateDecl *typeDecl, unsigned int functionNesting, FunctionType *layoutFnType ) { 406 // Routines at global scope marked "static" to prevent multiple definitions is separate translation units 407 // because each unit generates copies of the default routines for each aggregate. 408 FunctionDecl *layoutDecl = new FunctionDecl( 409 layoutofName( typeDecl ), functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, layoutFnType, new CompoundStmt( noLabels ), true, false ); 410 layoutDecl->fixUniqueId(); 411 return layoutDecl; 412 } 413 414 /// Makes a unary operation 415 Expression *makeOp( const std::string &name, Expression *arg ) { 416 UntypedExpr *expr = new UntypedExpr( new NameExpr( name ) ); 417 expr->get_args().push_back( arg ); 418 return expr; 419 } 420 421 /// Makes a binary operation 422 Expression *makeOp( const std::string &name, Expression *lhs, Expression *rhs ) { 423 UntypedExpr *expr = new UntypedExpr( new NameExpr( name ) ); 424 expr->get_args().push_back( lhs ); 425 expr->get_args().push_back( rhs ); 426 return expr; 427 } 428 429 /// Returns the dereference of a local pointer variable 430 Expression *derefVar( ObjectDecl *var ) { 431 return makeOp( "*?", new VariableExpr( var ) ); 432 } 433 434 /// makes an if-statement with a single-expression if-block and no then block 435 Statement *makeCond( Expression *cond, Expression *ifPart ) { 436 return new IfStmt( noLabels, cond, new ExprStmt( noLabels, ifPart ), 0 ); 437 } 438 439 /// makes a statement that assigns rhs to lhs if lhs < rhs 440 Statement *makeAssignMax( Expression *lhs, Expression *rhs ) { 441 return makeCond( makeOp( "?<?", lhs, rhs ), makeOp( "?=?", lhs->clone(), rhs->clone() ) ); 442 } 443 444 /// makes a statement that aligns lhs to rhs (rhs should be an integer power of two) 445 Statement *makeAlignTo( Expression *lhs, Expression *rhs ) { 446 // check that the lhs is zeroed out to the level of rhs 447 Expression *ifCond = makeOp( "?&?", lhs, makeOp( "?-?", rhs, new ConstantExpr( Constant( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), "1" ) ) ) ); 448 // if not aligned, increment to alignment 449 Expression *ifExpr = makeOp( "?+=?", lhs->clone(), makeOp( "?-?", rhs->clone(), ifCond->clone() ) ); 450 return makeCond( ifCond, ifExpr ); 451 } 452 453 /// adds an expression to a compound statement 454 void addExpr( CompoundStmt *stmts, Expression *expr ) { 455 stmts->get_kids().push_back( new ExprStmt( noLabels, expr ) ); 456 } 457 458 /// adds a statement to a compound statement 459 void addStmt( CompoundStmt *stmts, Statement *stmt ) { 460 stmts->get_kids().push_back( stmt ); 461 } 462 463 Declaration *LayoutFunctionBuilder::mutate( StructDecl *structDecl ) { 464 // do not generate layout function for "empty" tag structs 465 if ( structDecl->get_members().empty() ) return structDecl; 466 467 // get parameters that can change layout, exiting early if none 468 std::list< TypeDecl* > otypeParams = takeOtypeOnly( structDecl->get_parameters() ); 469 if ( otypeParams.empty() ) return structDecl; 470 471 // build layout function signature 472 FunctionType *layoutFnType = new FunctionType( Type::Qualifiers(), false ); 473 BasicType *sizeAlignType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ); 474 PointerType *sizeAlignOutType = new PointerType( Type::Qualifiers(), sizeAlignType ); 475 476 ObjectDecl *sizeParam = new ObjectDecl( sizeofName( structDecl->get_name() ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType, 0 ); 477 layoutFnType->get_parameters().push_back( sizeParam ); 478 ObjectDecl *alignParam = new ObjectDecl( alignofName( structDecl->get_name() ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType->clone(), 0 ); 479 layoutFnType->get_parameters().push_back( alignParam ); 480 ObjectDecl *offsetParam = new ObjectDecl( offsetofName( structDecl->get_name() ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType->clone(), 0 ); 481 layoutFnType->get_parameters().push_back( offsetParam ); 482 addOtypeParams( layoutFnType, otypeParams ); 483 484 // build function decl 485 FunctionDecl *layoutDecl = buildLayoutFunctionDecl( structDecl, functionNesting, layoutFnType ); 486 487 // calculate struct layout in function body 488 489 // initialize size and alignment to 0 and 1 (will have at least one member to re-edit size 490 addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( sizeParam ), new ConstantExpr( Constant( sizeAlignType->clone(), "0" ) ) ) ); 491 addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( alignParam ), new ConstantExpr( Constant( sizeAlignType->clone(), "1" ) ) ) ); 492 unsigned long n_members = 0; 493 bool firstMember = true; 494 for ( std::list< Declaration* >::const_iterator member = structDecl->get_members().begin(); member != structDecl->get_members().end(); ++member ) { 495 DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( *member ); 496 assert( dwt ); 497 Type *memberType = dwt->get_type(); 498 499 if ( firstMember ) { 500 firstMember = false; 501 } else { 502 // make sure all members after the first (automatically aligned at 0) are properly padded for alignment 503 addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), new AlignofExpr( memberType->clone() ) ) ); 504 } 505 506 // place current size in the current offset index 507 addExpr( layoutDecl->get_statements(), makeOp( "?=?", makeOp( "?[?]", new VariableExpr( offsetParam ), new ConstantExpr( Constant::from_ulong( n_members ) ) ), 508 derefVar( sizeParam ) ) ); 509 ++n_members; 510 511 // add member size to current size 512 addExpr( layoutDecl->get_statements(), makeOp( "?+=?", derefVar( sizeParam ), new SizeofExpr( memberType->clone() ) ) ); 513 514 // take max of member alignment and global alignment 515 addStmt( layoutDecl->get_statements(), makeAssignMax( derefVar( alignParam ), new AlignofExpr( memberType->clone() ) ) ); 516 } 517 // make sure the type is end-padded to a multiple of its alignment 518 addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), derefVar( alignParam ) ) ); 519 520 addDeclarationAfter( layoutDecl ); 521 return structDecl; 522 } 523 524 Declaration *LayoutFunctionBuilder::mutate( UnionDecl *unionDecl ) { 525 // do not generate layout function for "empty" tag unions 526 if ( unionDecl->get_members().empty() ) return unionDecl; 527 528 // get parameters that can change layout, exiting early if none 529 std::list< TypeDecl* > otypeParams = takeOtypeOnly( unionDecl->get_parameters() ); 530 if ( otypeParams.empty() ) return unionDecl; 531 532 // build layout function signature 533 FunctionType *layoutFnType = new FunctionType( Type::Qualifiers(), false ); 534 BasicType *sizeAlignType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ); 535 PointerType *sizeAlignOutType = new PointerType( Type::Qualifiers(), sizeAlignType ); 536 537 ObjectDecl *sizeParam = new ObjectDecl( sizeofName( unionDecl->get_name() ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType, 0 ); 538 layoutFnType->get_parameters().push_back( sizeParam ); 539 ObjectDecl *alignParam = new ObjectDecl( alignofName( unionDecl->get_name() ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType->clone(), 0 ); 540 layoutFnType->get_parameters().push_back( alignParam ); 541 addOtypeParams( layoutFnType, otypeParams ); 542 543 // build function decl 544 FunctionDecl *layoutDecl = buildLayoutFunctionDecl( unionDecl, functionNesting, layoutFnType ); 545 546 // calculate union layout in function body 547 addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( sizeParam ), new ConstantExpr( Constant( sizeAlignType->clone(), "1" ) ) ) ); 548 addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( alignParam ), new ConstantExpr( Constant( sizeAlignType->clone(), "1" ) ) ) ); 549 for ( std::list< Declaration* >::const_iterator member = unionDecl->get_members().begin(); member != unionDecl->get_members().end(); ++member ) { 550 DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( *member ); 551 assert( dwt ); 552 Type *memberType = dwt->get_type(); 553 554 // take max member size and global size 555 addStmt( layoutDecl->get_statements(), makeAssignMax( derefVar( sizeParam ), new SizeofExpr( memberType->clone() ) ) ); 556 557 // take max of member alignment and global alignment 558 addStmt( layoutDecl->get_statements(), makeAssignMax( derefVar( alignParam ), new AlignofExpr( memberType->clone() ) ) ); 559 } 560 // make sure the type is end-padded to a multiple of its alignment 561 addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), derefVar( alignParam ) ) ); 562 563 addDeclarationAfter( layoutDecl ); 564 return unionDecl; 565 } 566 139 567 ////////////////////////////////////////// Pass1 //////////////////////////////////////////////////// 140 568 141 569 namespace { 570 std::string makePolyMonoSuffix( FunctionType * function, const TyVarMap &tyVars ) { 571 std::stringstream name; 572 573 // NOTE: this function previously used isPolyObj, which failed to produce 574 // the correct thing in some situations. It's not clear to me why this wasn't working. 575 576 // if the return type or a parameter type involved polymorphic types, then the adapter will need 577 // to take those polymorphic types as pointers. Therefore, there can be two different functions 578 // with the same mangled name, so we need to further mangle the names. 579 for ( std::list< DeclarationWithType *>::iterator retval = function->get_returnVals().begin(); retval != function->get_returnVals().end(); ++retval ) { 580 if ( isPolyType( (*retval)->get_type(), tyVars ) ) { 581 name << "P"; 582 } else { 583 name << "M"; 584 } 585 } 586 name << "_"; 587 std::list< DeclarationWithType *> ¶mList = function->get_parameters(); 588 for ( std::list< DeclarationWithType *>::iterator arg = paramList.begin(); arg != paramList.end(); ++arg ) { 589 if ( isPolyType( (*arg)->get_type(), tyVars ) ) { 590 name << "P"; 591 } else { 592 name << "M"; 593 } 594 } // for 595 return name.str(); 596 } 597 598 std::string mangleAdapterName( FunctionType * function, const TyVarMap &tyVars ) { 599 return SymTab::Mangler::mangle( function ) + makePolyMonoSuffix( function, tyVars ); 600 } 601 142 602 std::string makeAdapterName( const std::string &mangleName ) { 143 603 return "_adapter" + mangleName; 144 604 } 145 605 146 bool isPolyRet( FunctionType *function, std::string &name, const TyVarMap &otherTyVars ) { 147 bool doTransform = false; 148 if ( ! function->get_returnVals().empty() ) { 149 if ( TypeInstType *typeInst = dynamic_cast< TypeInstType *>( function->get_returnVals().front()->get_type() ) ) { 150 151 // figure out if the return type is specified by a type parameter 152 for ( std::list< TypeDecl *>::const_iterator tyVar = function->get_forall().begin(); tyVar != function->get_forall().end(); ++tyVar ) { 153 if ( (*tyVar)->get_name() == typeInst->get_name() ) { 154 doTransform = true; 155 name = typeInst->get_name(); 156 break; 606 Pass1::Pass1() : useRetval( false ), tempNamer( "_temp" ) {} 607 608 /// Returns T if the given declaration is a function with parameter (T*) for some TypeInstType T, NULL otherwise 609 TypeInstType *isTypeInstPtrFn( DeclarationWithType *decl ) { 610 if ( FunctionType *funType = getFunctionType( decl->get_type() ) ) { 611 if ( funType->get_parameters().size() == 1 ) { 612 if ( PointerType *pointer = dynamic_cast< PointerType *>( funType->get_parameters().front()->get_type() ) ) { 613 if ( TypeInstType *refType = dynamic_cast< TypeInstType *>( pointer->get_base() ) ) { 614 return refType; 157 615 } // if 158 } // for159 if ( ! doTransform && otherTyVars.find( typeInst->get_name() ) != otherTyVars.end() ) {160 doTransform = true;161 616 } // if 162 617 } // if 163 618 } // if 164 return doTransform; 165 } 166 167 bool isPolyRet( FunctionType *function, std::string &name ) { 168 TyVarMap dummyTyVars; 169 return isPolyRet( function, name, dummyTyVars ); 170 } 171 172 bool isPolyRet( FunctionType *function, const TyVarMap &otherTyVars ) { 173 std::string dummyString; 174 return isPolyRet( function, dummyString, otherTyVars ); 175 } 176 177 Pass1::Pass1() 178 : useRetval( false ), tempNamer( "_temp" ) { 179 } 180 181 bool checkAssignment( DeclarationWithType *decl, std::string &name ) { 182 if ( decl->get_name() == "?=?" ) { 183 if ( PointerType *ptrType = dynamic_cast< PointerType *>( decl->get_type() ) ) { 184 if ( FunctionType *funType = dynamic_cast< FunctionType *>( ptrType->get_base() ) ) { 185 if ( funType->get_parameters().size() == 2 ) { 186 if ( PointerType *pointer = dynamic_cast< PointerType *>( funType->get_parameters().front()->get_type() ) ) { 187 if ( TypeInstType *typeInst = dynamic_cast< TypeInstType *>( pointer->get_base() ) ) { 188 name = typeInst->get_name(); 189 return true; 619 return 0; 620 } 621 622 /// Returns T if the given declaration is a function with parameters (T*, T) for some TypeInstType T, NULL otherwise 623 TypeInstType *isTypeInstPtrValFn( DeclarationWithType *decl ) { 624 if ( FunctionType *funType = getFunctionType( decl->get_type() ) ) { 625 if ( funType->get_parameters().size() == 2 ) { 626 if ( PointerType *pointer = dynamic_cast< PointerType *>( funType->get_parameters().front()->get_type() ) ) { 627 if ( TypeInstType *refType = dynamic_cast< TypeInstType *>( pointer->get_base() ) ) { 628 if ( TypeInstType *refType2 = dynamic_cast< TypeInstType *>( funType->get_parameters().back()->get_type() ) ) { 629 if ( refType->get_name() == refType2->get_name() ) { 630 return refType; 190 631 } // if 191 632 } // if … … 194 635 } // if 195 636 } // if 196 return false; 197 } 198 199 void Pass1::findAssignOps( const std::list< TypeDecl *> &forall ) { 200 assignOps.clear(); 637 return 0; 638 } 639 640 /// Returns T if the given declaration is (*?=?)(T *, T) for some TypeInstType T (return not checked, but maybe should be), NULL otherwise 641 TypeInstType *isTypeInstAssignment( DeclarationWithType *decl ) { 642 return decl->get_name() == "?=?" ? isTypeInstPtrValFn( decl ) : 0; 643 } 644 645 /// Returns T if the given declaration is (*?{})(T *) for some TypeInstType T (return not checked, but maybe should be), NULL otherwise 646 TypeInstType *isTypeInstCtor( DeclarationWithType *decl ) { 647 return decl->get_name() == "?{}" ? isTypeInstPtrFn( decl ) : 0; 648 } 649 650 /// Returns T if the given declaration is (*?{})(T *, T) for some TypeInstType T (return not checked, but maybe should be), NULL otherwise 651 TypeInstType *isTypeInstCopy( DeclarationWithType *decl ) { 652 return decl->get_name() == "?{}" ? isTypeInstPtrValFn( decl ) : 0; 653 } 654 655 /// Returns T if the given declaration is (*^?{})(T *) for some TypeInstType T (return not checked, but maybe should be), NULL otherwise 656 TypeInstType *isTypeInstDtor( DeclarationWithType *decl ) { 657 return decl->get_name() == "^?{}" ? isTypeInstPtrFn( decl ) : 0; 658 } 659 660 /// Returns T if the given declaration is a function with parameters (T*, T) for some type T, where neither parameter is cv-qualified, 661 /// NULL otherwise 662 Type *isNoCvPtrFn( DeclarationWithType *decl ) { 663 if ( FunctionType *funType = getFunctionType( decl->get_type() ) ) { 664 if ( funType->get_parameters().size() == 1 ) { 665 Type::Qualifiers defaultQualifiers; 666 Type *paramType = funType->get_parameters().front()->get_type(); 667 if ( paramType->get_qualifiers() != defaultQualifiers ) return 0; 668 669 if ( PointerType *pointerType = dynamic_cast< PointerType* >( paramType ) ) { 670 Type *baseType = pointerType->get_base(); 671 if ( baseType->get_qualifiers() == defaultQualifiers ) { 672 return baseType; 673 } // if 674 } // if 675 } // if 676 } // if 677 return 0; 678 } 679 680 /// Returns T if the given declaration is a function with parameters (T*, T) for some type T, where neither parameter is cv-qualified, 681 /// NULL otherwise 682 Type *isNoCvPtrValFn( DeclarationWithType *decl ) { 683 if ( FunctionType *funType = getFunctionType( decl->get_type() ) ) { 684 if ( funType->get_parameters().size() == 2 ) { 685 Type::Qualifiers defaultQualifiers; 686 Type *paramType1 = funType->get_parameters().front()->get_type(); 687 if ( paramType1->get_qualifiers() != defaultQualifiers ) return 0; 688 Type *paramType2 = funType->get_parameters().back()->get_type(); 689 if ( paramType2->get_qualifiers() != defaultQualifiers ) return 0; 690 691 if ( PointerType *pointerType = dynamic_cast< PointerType* >( paramType1 ) ) { 692 Type *baseType1 = pointerType->get_base(); 693 if ( baseType1->get_qualifiers() != defaultQualifiers ) return 0; 694 SymTab::Indexer dummy; 695 if ( ResolvExpr::typesCompatible( baseType1, paramType2, dummy ) ) { 696 return baseType1; 697 } // if 698 } // if 699 } // if 700 } // if 701 return 0; 702 } 703 704 /// returns T if the given declaration is: (*?=?)(T *, T) for some type T (return not checked, but maybe should be), NULL otherwise 705 /// Only picks assignments where neither parameter is cv-qualified 706 Type *isAssignment( DeclarationWithType *decl ) { 707 return decl->get_name() == "?=?" ? isNoCvPtrValFn( decl ) : 0; 708 } 709 710 /// returns T if the given declaration is: (*?{})(T *) for some type T, NULL otherwise 711 /// Only picks ctors where the parameter is not cv-qualified 712 Type *isCtor( DeclarationWithType *decl ) { 713 return decl->get_name() == "?{}" ? isNoCvPtrFn( decl ) : 0; 714 } 715 716 /// returns T if the given declaration is: (*?{})(T *, T) for some type T (return not checked, but maybe should be), NULL otherwise 717 /// Only picks copy constructors where neither parameter is cv-qualified 718 Type *isCopy( DeclarationWithType *decl ) { 719 return decl->get_name() == "?{}" ? isNoCvPtrValFn( decl ) : 0; 720 } 721 722 /// returns T if the given declaration is: (*?{})(T *) for some type T, NULL otherwise 723 /// Only picks ctors where the parameter is not cv-qualified 724 Type *isDtor( DeclarationWithType *decl ) { 725 return decl->get_name() == "^?{}" ? isNoCvPtrFn( decl ) : 0; 726 } 727 728 void Pass1::findTypeOps( const std::list< TypeDecl *> &forall ) { 729 // what if a nested function uses an assignment operator? 730 // assignOps.clear(); 201 731 for ( std::list< TypeDecl *>::const_iterator i = forall.begin(); i != forall.end(); ++i ) { 202 732 for ( std::list< DeclarationWithType *>::const_iterator assert = (*i)->get_assertions().begin(); assert != (*i)->get_assertions().end(); ++assert ) { 203 733 std::string typeName; 204 if ( checkAssignment( *assert, typeName ) ) { 205 assignOps[ typeName ] = *assert; 734 if ( TypeInstType *typeInst = isTypeInstAssignment( *assert ) ) { 735 assignOps[ typeInst->get_name() ] = *assert; 736 } else if ( TypeInstType *typeInst = isTypeInstCtor( *assert ) ) { 737 ctorOps[ typeInst->get_name() ] = *assert; 738 } else if ( TypeInstType *typeInst = isTypeInstCopy( *assert ) ) { 739 copyOps[ typeInst->get_name() ] = *assert; 740 } else if ( TypeInstType *typeInst = isTypeInstDtor( *assert ) ) { 741 dtorOps[ typeInst->get_name() ] = *assert; 206 742 } // if 207 743 } // for … … 210 746 211 747 DeclarationWithType *Pass1::mutate( FunctionDecl *functionDecl ) { 212 if ( functionDecl->get_statements() ) { 213 TyVarMap oldtyVars = scopeTyVars; 748 // if this is a assignment function, put it in the map for this scope 749 if ( Type *paramType = isAssignment( functionDecl ) ) { 750 if ( ! dynamic_cast< TypeInstType* >( paramType ) ) { 751 scopedAssignOps.insert( paramType, functionDecl ); 752 } 753 } else if ( Type *paramType = isCtor( functionDecl ) ) { 754 if ( ! dynamic_cast< TypeInstType* >( paramType ) ) { 755 scopedCtorOps.insert( paramType, functionDecl ); 756 } 757 } else if ( Type *paramType = isCopy( functionDecl ) ) { 758 if ( ! dynamic_cast< TypeInstType* >( paramType ) ) { 759 scopedCopyOps.insert( paramType, functionDecl ); 760 } 761 } else if ( Type *paramType = isDtor( functionDecl ) ) { 762 if ( ! dynamic_cast< TypeInstType* >( paramType ) ) { 763 scopedDtorOps.insert( paramType, functionDecl ); 764 } 765 } 766 767 if ( functionDecl->get_statements() ) { // empty routine body ? 768 doBeginScope(); 769 scopeTyVars.beginScope(); 770 assignOps.beginScope(); 771 ctorOps.beginScope(); 772 copyOps.beginScope(); 773 dtorOps.beginScope(); 774 214 775 DeclarationWithType *oldRetval = retval; 215 776 bool oldUseRetval = useRetval; 216 777 778 // process polymorphic return value 217 779 retval = 0; 218 std::string typeName; 219 if ( isPolyRet( functionDecl->get_functionType(), typeName ) && functionDecl->get_linkage() == LinkageSpec::Cforall ) { 780 if ( isPolyRet( functionDecl->get_functionType() ) && functionDecl->get_linkage() == LinkageSpec::Cforall ) { 220 781 retval = functionDecl->get_functionType()->get_returnVals().front(); 221 782 222 783 // give names to unnamed return values 223 784 if ( retval->get_name() == "" ) { … … 226 787 } // if 227 788 } // if 228 229 scopeTyVars.clear(); 230 /// std::cerr << "clear\n"; 789 790 FunctionType *functionType = functionDecl->get_functionType(); 231 791 makeTyVarMap( functionDecl->get_functionType(), scopeTyVars ); 232 findAssignOps( functionDecl->get_functionType()->get_forall() ); 792 findTypeOps( functionDecl->get_functionType()->get_forall() ); 793 794 std::list< DeclarationWithType *> ¶mList = functionType->get_parameters(); 795 std::list< FunctionType *> functions; 796 for ( std::list< TypeDecl *>::iterator tyVar = functionType->get_forall().begin(); tyVar != functionType->get_forall().end(); ++tyVar ) { 797 for ( std::list< DeclarationWithType *>::iterator assert = (*tyVar)->get_assertions().begin(); assert != (*tyVar)->get_assertions().end(); ++assert ) { 798 findFunction( (*assert)->get_type(), functions, scopeTyVars, needsAdapter ); 799 } // for 800 } // for 801 for ( std::list< DeclarationWithType *>::iterator arg = paramList.begin(); arg != paramList.end(); ++arg ) { 802 findFunction( (*arg)->get_type(), functions, scopeTyVars, needsAdapter ); 803 } // for 804 805 for ( std::list< FunctionType *>::iterator funType = functions.begin(); funType != functions.end(); ++funType ) { 806 std::string mangleName = mangleAdapterName( *funType, scopeTyVars ); 807 if ( adapters.find( mangleName ) == adapters.end() ) { 808 std::string adapterName = makeAdapterName( mangleName ); 809 adapters.insert( std::pair< std::string, DeclarationWithType *>( mangleName, new ObjectDecl( adapterName, DeclarationNode::NoStorageClass, LinkageSpec::C, 0, new PointerType( Type::Qualifiers(), makeAdapterType( *funType, scopeTyVars ) ), 0 ) ) ); 810 } // if 811 } // for 812 233 813 functionDecl->set_statements( functionDecl->get_statements()->acceptMutator( *this ) ); 234 235 scopeTyVars = oldtyVars; 236 /// std::cerr << "end FunctionDecl: "; 237 /// for ( TyVarMap::iterator i = scopeTyVars.begin(); i != scopeTyVars.end(); ++i ) { 238 /// std::cerr << i->first << " "; 239 /// } 240 /// std::cerr << "\n"; 814 815 scopeTyVars.endScope(); 816 assignOps.endScope(); 817 ctorOps.endScope(); 818 copyOps.endScope(); 819 dtorOps.endScope(); 241 820 retval = oldRetval; 242 821 useRetval = oldUseRetval; 243 //doEndScope();822 doEndScope(); 244 823 } // if 245 824 return functionDecl; … … 247 826 248 827 TypeDecl *Pass1::mutate( TypeDecl *typeDecl ) { 249 /// std::cerr << "add " << typeDecl->get_name() << "\n";250 828 scopeTyVars[ typeDecl->get_name() ] = typeDecl->get_kind(); 251 829 return Mutator::mutate( typeDecl ); … … 272 850 } 273 851 274 void Pass1::passTypeVars( ApplicationExpr *appExpr, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars ) { 852 void Pass1::passArgTypeVars( ApplicationExpr *appExpr, Type *parmType, Type *argBaseType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars, std::set< std::string > &seenTypes ) { 853 Type *polyType = isPolyType( parmType, exprTyVars ); 854 if ( polyType && ! dynamic_cast< TypeInstType* >( polyType ) ) { 855 std::string typeName = mangleType( polyType ); 856 if ( seenTypes.count( typeName ) ) return; 857 858 arg = appExpr->get_args().insert( arg, new SizeofExpr( argBaseType->clone() ) ); 859 arg++; 860 arg = appExpr->get_args().insert( arg, new AlignofExpr( argBaseType->clone() ) ); 861 arg++; 862 if ( dynamic_cast< StructInstType* >( polyType ) ) { 863 if ( StructInstType *argBaseStructType = dynamic_cast< StructInstType* >( argBaseType ) ) { 864 // zero-length arrays are forbidden by C, so don't pass offset for empty struct 865 if ( ! argBaseStructType->get_baseStruct()->get_members().empty() ) { 866 arg = appExpr->get_args().insert( arg, new OffsetPackExpr( argBaseStructType->clone() ) ); 867 arg++; 868 } 869 } else { 870 throw SemanticError( "Cannot pass non-struct type for generic struct" ); 871 } 872 } 873 874 seenTypes.insert( typeName ); 875 } 876 } 877 878 void Pass1::passTypeVars( ApplicationExpr *appExpr, ReferenceToType *polyRetType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars ) { 879 // pass size/align for type variables 275 880 for ( TyVarMap::const_iterator tyParm = exprTyVars.begin(); tyParm != exprTyVars.end(); ++tyParm ) { 276 881 ResolvExpr::EqvClass eqvClass; … … 281 886 arg = appExpr->get_args().insert( arg, new SizeofExpr( concrete->clone() ) ); 282 887 arg++; 888 arg = appExpr->get_args().insert( arg, new AlignofExpr( concrete->clone() ) ); 889 arg++; 283 890 } else { 284 throw SemanticError( "unbound type variable in application ", appExpr ); 891 /// xxx - should this be an assertion? 892 throw SemanticError( "unbound type variable: " + tyParm->first + " in application ", appExpr ); 285 893 } // if 286 894 } // if 287 895 } // for 896 897 // add size/align for generic types to parameter list 898 if ( appExpr->get_function()->get_results().empty() ) return; 899 FunctionType *funcType = getFunctionType( appExpr->get_function()->get_results().front() ); 900 assert( funcType ); 901 902 std::list< DeclarationWithType* >::const_iterator fnParm = funcType->get_parameters().begin(); 903 std::list< Expression* >::const_iterator fnArg = arg; 904 std::set< std::string > seenTypes; //< names for generic types we've seen 905 906 // a polymorphic return type may need to be added to the argument list 907 if ( polyRetType ) { 908 Type *concRetType = replaceWithConcrete( appExpr, polyRetType ); 909 passArgTypeVars( appExpr, polyRetType, concRetType, arg, exprTyVars, seenTypes ); 910 } 911 912 // add type information args for presently unseen types in parameter list 913 for ( ; fnParm != funcType->get_parameters().end() && fnArg != appExpr->get_args().end(); ++fnParm, ++fnArg ) { 914 VariableExpr *fnArgBase = getBaseVar( *fnArg ); 915 if ( ! fnArgBase || fnArgBase->get_results().empty() ) continue; 916 passArgTypeVars( appExpr, (*fnParm)->get_type(), fnArgBase->get_results().front(), arg, exprTyVars, seenTypes ); 917 } 288 918 } 289 919 … … 294 924 } 295 925 296 TypeInstType *isPolyType( Type *type, const TypeSubstitution *env, const TyVarMap &tyVars ) { 297 if ( TypeInstType *typeInst = dynamic_cast< TypeInstType *>( type ) ) { 298 if ( env ) { 299 if ( Type *newType = env->lookup( typeInst->get_name() ) ) { 300 return isPolyType( newType, env, tyVars ); 301 } // if 926 Expression *Pass1::addRetParam( ApplicationExpr *appExpr, FunctionType *function, Type *retType, std::list< Expression *>::iterator &arg ) { 927 // ***** Code Removal ***** After introducing a temporary variable for all return expressions, the following code appears superfluous. 928 // if ( useRetval ) { 929 // assert( retval ); 930 // arg = appExpr->get_args().insert( arg, new VariableExpr( retval ) ); 931 // arg++; 932 // } else { 933 934 // Create temporary to hold return value of polymorphic function and produce that temporary as a result 935 // using a comma expression. Possibly change comma expression into statement expression "{}" for multiple 936 // return values. 937 ObjectDecl *newObj = makeTemporary( retType->clone() ); 938 Expression *paramExpr = new VariableExpr( newObj ); 939 940 // If the type of the temporary is not polymorphic, box temporary by taking its address; 941 // otherwise the temporary is already boxed and can be used directly. 942 if ( ! isPolyType( newObj->get_type(), scopeTyVars, env ) ) { 943 paramExpr = new AddressExpr( paramExpr ); 944 } // if 945 arg = appExpr->get_args().insert( arg, paramExpr ); // add argument to function call 946 arg++; 947 // Build a comma expression to call the function and emulate a normal return. 948 CommaExpr *commaExpr = new CommaExpr( appExpr, new VariableExpr( newObj ) ); 949 commaExpr->set_env( appExpr->get_env() ); 950 appExpr->set_env( 0 ); 951 return commaExpr; 952 // } // if 953 // return appExpr; 954 } 955 956 void Pass1::replaceParametersWithConcrete( ApplicationExpr *appExpr, std::list< Expression* >& params ) { 957 for ( std::list< Expression* >::iterator param = params.begin(); param != params.end(); ++param ) { 958 TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param ); 959 assert(paramType && "Aggregate parameters should be type expressions"); 960 paramType->set_type( replaceWithConcrete( appExpr, paramType->get_type(), false ) ); 961 } 962 } 963 964 Type *Pass1::replaceWithConcrete( ApplicationExpr *appExpr, Type *type, bool doClone ) { 965 if ( TypeInstType *typeInst = dynamic_cast< TypeInstType * >( type ) ) { 966 Type *concrete = env->lookup( typeInst->get_name() ); 967 if ( concrete == 0 ) { 968 throw SemanticError( "Unbound type variable " + typeInst->get_name() + " in ", appExpr ); 302 969 } // if 303 if ( tyVars.find( typeInst->get_name() ) != tyVars.end() ) { 304 return typeInst; 305 } else { 306 return 0; 307 } // if 308 } else { 309 return 0; 310 } // if 311 } 312 313 Expression *Pass1::addRetParam( ApplicationExpr *appExpr, FunctionType *function, Type *retType, std::list< Expression *>::iterator &arg ) { 314 if ( useRetval ) { 315 assert( retval ); 316 arg = appExpr->get_args().insert( arg, new VariableExpr( retval ) ); 317 arg++; 318 } else { 319 ObjectDecl *newObj = makeTemporary( retType->clone() ); 320 Expression *paramExpr = new VariableExpr( newObj ); 321 if ( ! isPolyType( newObj->get_type(), env, scopeTyVars ) ) { 322 paramExpr = new AddressExpr( paramExpr ); 323 } // if 324 arg = appExpr->get_args().insert( arg, paramExpr ); 325 arg++; 326 /// stmtsToAdd.push_back( new ExprStmt( noLabels, appExpr ) ); 327 CommaExpr *commaExpr = new CommaExpr( appExpr, new VariableExpr( newObj ) ); 328 commaExpr->set_env( appExpr->get_env() ); 329 appExpr->set_env( 0 ); 330 return commaExpr; 331 } // if 332 return appExpr; 333 } 334 335 Expression *Pass1::addPolyRetParam( ApplicationExpr *appExpr, FunctionType *function, std::string typeName, std::list< Expression *>::iterator &arg ) { 336 ResolvExpr::EqvClass eqvClass; 970 return concrete; 971 } else if ( StructInstType *structType = dynamic_cast< StructInstType* >( type ) ) { 972 if ( doClone ) { 973 structType = structType->clone(); 974 } 975 replaceParametersWithConcrete( appExpr, structType->get_parameters() ); 976 return structType; 977 } else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( type ) ) { 978 if ( doClone ) { 979 unionType = unionType->clone(); 980 } 981 replaceParametersWithConcrete( appExpr, unionType->get_parameters() ); 982 return unionType; 983 } 984 return type; 985 } 986 987 Expression *Pass1::addPolyRetParam( ApplicationExpr *appExpr, FunctionType *function, ReferenceToType *polyType, std::list< Expression *>::iterator &arg ) { 337 988 assert( env ); 338 Type *concrete = env->lookup( typeName ); 339 if ( concrete == 0 ) { 340 throw SemanticError( "Unbound type variable " + typeName + " in ", appExpr ); 341 } // if 989 Type *concrete = replaceWithConcrete( appExpr, polyType ); 990 // add out-parameter for return value 342 991 return addRetParam( appExpr, function, concrete, arg ); 343 992 } … … 345 994 Expression *Pass1::applyAdapter( ApplicationExpr *appExpr, FunctionType *function, std::list< Expression *>::iterator &arg, const TyVarMap &tyVars ) { 346 995 Expression *ret = appExpr; 347 if ( ! function->get_returnVals().empty() && isPoly Val( function->get_returnVals().front()->get_type(), tyVars ) ) {996 if ( ! function->get_returnVals().empty() && isPolyType( function->get_returnVals().front()->get_type(), tyVars ) ) { 348 997 ret = addRetParam( appExpr, function, function->get_returnVals().front()->get_type(), arg ); 349 998 } // if 350 std::string mangleName = SymTab::Mangler::mangle( function);999 std::string mangleName = mangleAdapterName( function, tyVars ); 351 1000 std::string adapterName = makeAdapterName( mangleName ); 352 1001 353 appExpr->get_args().push_front( appExpr->get_function() ); 1002 // cast adaptee to void (*)(), since it may have any type inside a polymorphic function 1003 Type * adapteeType = new PointerType( Type::Qualifiers(), new FunctionType( Type::Qualifiers(), true ) ); 1004 appExpr->get_args().push_front( new CastExpr( appExpr->get_function(), adapteeType ) ); 354 1005 appExpr->set_function( new NameExpr( adapterName ) ); 355 1006 356 1007 return ret; 357 1008 } … … 359 1010 void Pass1::boxParam( Type *param, Expression *&arg, const TyVarMap &exprTyVars ) { 360 1011 assert( ! arg->get_results().empty() ); 361 /// if ( ! dynamic_cast< PointerType *>( arg->get_results().front() ) ) { 362 TypeInstType *typeInst = dynamic_cast< TypeInstType *>( param ); 363 if ( typeInst && exprTyVars.find( typeInst->get_name() ) != exprTyVars.end() ) { 364 if ( dynamic_cast< TypeInstType *>( arg->get_results().front() ) ) { 365 // if the argument's type is a type parameter, we don't need to box again! 1012 if ( isPolyType( param, exprTyVars ) ) { 1013 if ( isPolyType( arg->get_results().front() ) ) { 1014 // if the argument's type is polymorphic, we don't need to box again! 366 1015 return; 367 1016 } else if ( arg->get_results().front()->get_isLvalue() ) { 368 // VariableExpr and MemberExpr are lvalues 369 arg = new AddressExpr( arg ); 1017 // VariableExpr and MemberExpr are lvalues; need to check this isn't coming from the second arg of a comma expression though (not an lvalue) 1018 // xxx - need to test that this code is still reachable 1019 if ( CommaExpr *commaArg = dynamic_cast< CommaExpr* >( arg ) ) { 1020 commaArg->set_arg2( new AddressExpr( commaArg->get_arg2() ) ); 1021 } else { 1022 arg = new AddressExpr( arg ); 1023 } 370 1024 } else { 371 ObjectDecl *newObj = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, arg->get_results().front()->clone(), 0 ); 1025 // use type computed in unification to declare boxed variables 1026 Type * newType = param->clone(); 1027 if ( env ) env->apply( newType ); 1028 ObjectDecl *newObj = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, newType, 0 ); 372 1029 newObj->get_type()->get_qualifiers() = Type::Qualifiers(); // TODO: is this right??? 373 1030 stmtsToAdd.push_back( new DeclStmt( noLabels, newObj ) ); … … 379 1036 } // if 380 1037 } // if 381 /// } 382 } 383 1038 } 1039 1040 /// cast parameters to polymorphic functions so that types are replaced with 1041 /// void * if they are type parameters in the formal type. 1042 /// this gets rid of warnings from gcc. 384 1043 void addCast( Expression *&actual, Type *formal, const TyVarMap &tyVars ) { 385 Type *newType = formal->clone(); 386 std::list< FunctionType *> functions; 387 // instead of functions needing adapters, this really ought to look for 388 // any function mentioning a polymorphic type 389 findAndReplaceFunction( newType, functions, tyVars, needsAdapter ); 390 if ( ! functions.empty() ) { 1044 Type * newType = formal->clone(); 1045 if ( getFunctionType( newType ) ) { 1046 newType = ScrubTyVars::scrub( newType, tyVars ); 391 1047 actual = new CastExpr( actual, newType ); 392 } else {393 delete newType;394 1048 } // if 395 1049 } 396 1050 397 1051 void Pass1::boxParams( ApplicationExpr *appExpr, FunctionType *function, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars ) { 398 /// std::cout << "function is ";399 /// function->print( std::cout );400 1052 for ( std::list< DeclarationWithType *>::const_iterator param = function->get_parameters().begin(); param != function->get_parameters().end(); ++param, ++arg ) { 401 /// std::cout << "parameter is ";402 /// (*param)->print( std::fcout );403 /// std::cout << std::endl << "argument is ";404 /// (*arg)->print( std::cout );405 1053 assert( arg != appExpr->get_args().end() ); 406 1054 addCast( *arg, (*param)->get_type(), exprTyVars ); … … 414 1062 for ( std::list< DeclarationWithType *>::iterator assert = (*tyVar)->get_assertions().begin(); assert != (*tyVar)->get_assertions().end(); ++assert ) { 415 1063 InferredParams::const_iterator inferParam = appExpr->get_inferParams().find( (*assert)->get_uniqueId() ); 416 assert( inferParam != appExpr->get_inferParams().end() );1064 assert( inferParam != appExpr->get_inferParams().end() && "NOTE: Explicit casts of polymorphic functions to compatible monomorphic functions are currently unsupported" ); 417 1065 Expression *newExpr = inferParam->second.expr->clone(); 418 1066 addCast( newExpr, (*assert)->get_type(), tyVars ); … … 437 1085 // actually make the adapter type 438 1086 FunctionType *adapter = adaptee->clone(); 439 if ( ! adapter->get_returnVals().empty() && isPoly Val( adapter->get_returnVals().front()->get_type(), tyVars ) ) {1087 if ( ! adapter->get_returnVals().empty() && isPolyType( adapter->get_returnVals().front()->get_type(), tyVars ) ) { 440 1088 makeRetParm( adapter ); 441 1089 } // if … … 447 1095 assert( param ); 448 1096 assert( arg ); 449 /// std::cout << "arg type is "; 450 /// arg->get_type()->print( std::cout ); 451 /// std::cout << "param type is "; 452 /// param->get_type()->print( std::cout ); 453 /// std::cout << " tyVars are: "; 454 /// printTyVarMap( std::cout, tyVars ); 455 if ( isPolyVal( realParam->get_type(), tyVars ) ) { 456 /// if ( dynamic_cast< PointerType *>( arg->get_type() ) ) { 457 /// return new CastExpr( new VariableExpr( param ), arg->get_type()->clone() ); 458 /// } else { 459 UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) ); 460 deref->get_args().push_back( new CastExpr( new VariableExpr( param ), new PointerType( Type::Qualifiers(), arg->get_type()->clone() ) ) ); 461 deref->get_results().push_back( arg->get_type()->clone() ); 462 return deref; 463 /// } 1097 if ( isPolyType( realParam->get_type(), tyVars ) ) { 1098 if ( ! isPolyType( arg->get_type() ) ) { 1099 UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) ); 1100 deref->get_args().push_back( new CastExpr( new VariableExpr( param ), new PointerType( Type::Qualifiers(), arg->get_type()->clone() ) ) ); 1101 deref->get_results().push_back( arg->get_type()->clone() ); 1102 return deref; 1103 } // if 464 1104 } // if 465 1105 return new VariableExpr( param ); … … 477 1117 } 478 1118 479 480 481 1119 FunctionDecl *Pass1::makeAdapter( FunctionType *adaptee, FunctionType *realType, const std::string &mangleName, const TyVarMap &tyVars ) { 482 1120 FunctionType *adapterType = makeAdapterType( adaptee, tyVars ); … … 486 1124 ApplicationExpr *adapteeApp = new ApplicationExpr( new CastExpr( new VariableExpr( adapteeDecl ), new PointerType( Type::Qualifiers(), realType ) ) ); 487 1125 Statement *bodyStmt; 488 1126 489 1127 std::list< TypeDecl *>::iterator tyArg = realType->get_forall().begin(); 490 1128 std::list< TypeDecl *>::iterator tyParam = adapterType->get_forall().begin(); … … 500 1138 } // for 501 1139 } // for 502 1140 503 1141 std::list< DeclarationWithType *>::iterator arg = realType->get_parameters().begin(); 504 1142 std::list< DeclarationWithType *>::iterator param = adapterType->get_parameters().begin(); 505 1143 std::list< DeclarationWithType *>::iterator realParam = adaptee->get_parameters().begin(); 506 param++; // skip adaptee parameter 1144 param++; // skip adaptee parameter in the adapter type 507 1145 if ( realType->get_returnVals().empty() ) { 1146 // void return 508 1147 addAdapterParams( adapteeApp, arg, param, adapterType->get_parameters().end(), realParam, tyVars ); 509 1148 bodyStmt = new ExprStmt( noLabels, adapteeApp ); 510 } else if ( isPolyVal( adaptee->get_returnVals().front()->get_type(), tyVars ) ) { 1149 } else if ( isPolyType( adaptee->get_returnVals().front()->get_type(), tyVars ) ) { 1150 // return type T 511 1151 if ( (*param)->get_name() == "" ) { 512 1152 (*param)->set_name( "_ret" ); … … 544 1184 } // for 545 1185 546 // parameter function types for which an appropriate adapter has been generated. 547 // we cannot use the types after applying substitutions, since two different 548 // parameter types may be unified to the same type 1186 // parameter function types for which an appropriate adapter has been generated. we cannot use the types 1187 // after applying substitutions, since two different parameter types may be unified to the same type 549 1188 std::set< std::string > adaptersDone; 550 1189 … … 554 1193 std::string mangleName = SymTab::Mangler::mangle( realFunction ); 555 1194 556 // only attempt to create an adapter or pass one as a parameter if we haven't 557 // already done so for thispre-substitution parameter function type.1195 // only attempt to create an adapter or pass one as a parameter if we haven't already done so for this 1196 // pre-substitution parameter function type. 558 1197 if ( adaptersDone.find( mangleName ) == adaptersDone.end() ) { 559 std::string mangleName = SymTab::Mangler::mangle( realFunction );560 1198 adaptersDone.insert( adaptersDone.begin(), mangleName ); 561 562 // apply substitution to type variables to figure out what the 563 // adapter's type should look like 1199 1200 // apply substitution to type variables to figure out what the adapter's type should look like 564 1201 assert( env ); 565 1202 env->apply( realFunction ); 566 1203 mangleName = SymTab::Mangler::mangle( realFunction ); 567 568 if ( needsAdapter( realFunction, exprTyVars, true ) ) { 569 // the function still contains type variables, which means we are in a polymorphic 570 // context and the adapter function is a parameter - call the parameter and don't 571 // create a new adapter. 572 appExpr->get_args().push_front( new NameExpr( makeAdapterName ( mangleName ) ) ); 573 } else { 574 if ( isPolyRet( originalFunction, exprTyVars ) ) { 575 // if the return type involved polymorphic types, then 576 // the adapter will need to take those polymorphic types 577 // as pointers. Therefore, there can be two different 578 // functions with the same mangled name, so we need two adapter map 579 // stacks and also we need the mangled names to be different. 580 mangleName += "polyret_"; 581 } 582 583 AdapterMap & adapters = Pass1::adapters.top(); 584 AdapterMap::iterator adapter = adapters.find( mangleName ); 585 if ( adapter == adapters.end() ) { 586 // adapter has not been created yet in the current scope, so define it 587 FunctionDecl *newAdapter = makeAdapter( *funType, realFunction, mangleName, exprTyVars ); 588 adapter = adapters.insert( adapters.begin(), std::pair< std::string, FunctionDecl *>( mangleName, newAdapter ) ); 589 stmtsToAdd.push_back( new DeclStmt( noLabels, newAdapter ) ); 590 } // if 591 assert( adapter != adapters.end() ); 592 593 // add the appropriate adapter as a parameter 594 appExpr->get_args().push_front( new VariableExpr( adapter->second ) ); 1204 mangleName += makePolyMonoSuffix( originalFunction, exprTyVars ); 1205 1206 typedef ScopedMap< std::string, DeclarationWithType* >::iterator AdapterIter; 1207 AdapterIter adapter = adapters.find( mangleName ); 1208 if ( adapter == adapters.end() ) { 1209 // adapter has not been created yet in the current scope, so define it 1210 FunctionDecl *newAdapter = makeAdapter( *funType, realFunction, mangleName, exprTyVars ); 1211 std::pair< AdapterIter, bool > answer = adapters.insert( std::pair< std::string, DeclarationWithType *>( mangleName, newAdapter ) ); 1212 adapter = answer.first; 1213 stmtsToAdd.push_back( new DeclStmt( noLabels, newAdapter ) ); 595 1214 } // if 1215 assert( adapter != adapters.end() ); 1216 1217 // add the appropriate adapter as a parameter 1218 appExpr->get_args().push_front( new VariableExpr( adapter->second ) ); 596 1219 } // if 597 1220 } // for 598 } 599 600 TypeInstType *isPolyPtr( Type *type, const TypeSubstitution *env, const TyVarMap &tyVars ) { 601 if ( PointerType *ptr = dynamic_cast< PointerType *>( type ) ) { 602 return isPolyType( ptr->get_base(), env, tyVars ); 603 } else if ( env ) { 604 if ( TypeInstType *typeInst = dynamic_cast< TypeInstType *>( type ) ) { 605 if ( Type *newType = env->lookup( typeInst->get_name() ) ) { 606 return isPolyPtr( newType, env, tyVars ); 607 } // if 608 } // if 609 } // if 610 return 0; 611 } 612 613 TypeInstType *isPolyPtrPtr( Type *type, const TypeSubstitution *env, const TyVarMap &tyVars ) { 614 if ( PointerType *ptr = dynamic_cast< PointerType *>( type ) ) { 615 return isPolyPtr( ptr->get_base(), env, tyVars ); 616 } else if ( env ) { 617 if ( TypeInstType *typeInst = dynamic_cast< TypeInstType *>( type ) ) { 618 if ( Type *newType = env->lookup( typeInst->get_name() ) ) { 619 return isPolyPtrPtr( newType, env, tyVars ); 620 } // if 621 } // if 622 } // if 623 return 0; 624 } 625 626 Expression *makeIncrDecrExpr( ApplicationExpr *appExpr, std::string polyName, bool isIncr ) { 1221 } // passAdapters 1222 1223 Expression *makeIncrDecrExpr( ApplicationExpr *appExpr, Type *polyType, bool isIncr ) { 627 1224 NameExpr *opExpr; 628 1225 if ( isIncr ) { … … 637 1234 addAssign->get_args().push_back( appExpr->get_args().front() ); 638 1235 } // if 639 addAssign->get_args().push_back( new NameExpr( polyName) );1236 addAssign->get_args().push_back( new NameExpr( sizeofName( mangleType( polyType ) ) ) ); 640 1237 addAssign->get_results().front() = appExpr->get_results().front()->clone(); 641 1238 if ( appExpr->get_env() ) { … … 654 1251 assert( ! appExpr->get_results().empty() ); 655 1252 assert( appExpr->get_args().size() == 2 ); 656 Type InstType *typeInst1 = isPolyPtr( appExpr->get_args().front()->get_results().front(), env, scopeTyVars);657 Type InstType *typeInst2 = isPolyPtr( appExpr->get_args().back()->get_results().front(), env, scopeTyVars);658 assert( ! typeInst1 || ! typeInst2 );1253 Type *baseType1 = isPolyPtr( appExpr->get_args().front()->get_results().front(), scopeTyVars, env ); 1254 Type *baseType2 = isPolyPtr( appExpr->get_args().back()->get_results().front(), scopeTyVars, env ); 1255 assert( ! baseType1 || ! baseType2 ); // the arguments cannot both be polymorphic pointers 659 1256 UntypedExpr *ret = 0; 660 if ( typeInst1 || typeInst2 ) {1257 if ( baseType1 || baseType2 ) { // one of the arguments is a polymorphic pointer 661 1258 ret = new UntypedExpr( new NameExpr( "?+?" ) ); 662 1259 } // if 663 if ( typeInst1 ) {1260 if ( baseType1 ) { 664 1261 UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) ); 665 1262 multiply->get_args().push_back( appExpr->get_args().back() ); 666 multiply->get_args().push_back( new NameExpr( typeInst1->get_name() ) );1263 multiply->get_args().push_back( new SizeofExpr( baseType1->clone() ) ); 667 1264 ret->get_args().push_back( appExpr->get_args().front() ); 668 1265 ret->get_args().push_back( multiply ); 669 } else if ( typeInst2 ) {1266 } else if ( baseType2 ) { 670 1267 UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) ); 671 1268 multiply->get_args().push_back( appExpr->get_args().front() ); 672 multiply->get_args().push_back( new NameExpr( typeInst2->get_name() ) );1269 multiply->get_args().push_back( new SizeofExpr( baseType2->clone() ) ); 673 1270 ret->get_args().push_back( multiply ); 674 1271 ret->get_args().push_back( appExpr->get_args().back() ); 675 1272 } // if 676 if ( typeInst1 || typeInst2 ) {1273 if ( baseType1 || baseType2 ) { 677 1274 ret->get_results().push_front( appExpr->get_results().front()->clone() ); 678 1275 if ( appExpr->get_env() ) { … … 687 1284 assert( ! appExpr->get_results().empty() ); 688 1285 assert( ! appExpr->get_args().empty() ); 689 if ( isPolyType( appExpr->get_results().front(), env, scopeTyVars) ) {1286 if ( isPolyType( appExpr->get_results().front(), scopeTyVars, env ) ) { 690 1287 Expression *ret = appExpr->get_args().front(); 691 1288 delete ret->get_results().front(); … … 702 1299 assert( ! appExpr->get_results().empty() ); 703 1300 assert( appExpr->get_args().size() == 1 ); 704 if ( Type InstType *typeInst = isPolyPtr( appExpr->get_results().front(), env, scopeTyVars) ) {1301 if ( Type *baseType = isPolyPtr( appExpr->get_results().front(), scopeTyVars, env ) ) { 705 1302 Type *tempType = appExpr->get_results().front()->clone(); 706 1303 if ( env ) { … … 716 1313 assignExpr->get_args().push_back( appExpr->get_args().front()->clone() ); 717 1314 } // if 718 CommaExpr *firstComma = new CommaExpr( assignExpr, makeIncrDecrExpr( appExpr, typeInst->get_name(), varExpr->get_var()->get_name() == "?++" ) );1315 CommaExpr *firstComma = new CommaExpr( assignExpr, makeIncrDecrExpr( appExpr, baseType, varExpr->get_var()->get_name() == "?++" ) ); 719 1316 return new CommaExpr( firstComma, tempExpr ); 720 1317 } // if … … 722 1319 assert( ! appExpr->get_results().empty() ); 723 1320 assert( appExpr->get_args().size() == 1 ); 724 if ( Type InstType *typeInst = isPolyPtr( appExpr->get_results().front(), env, scopeTyVars) ) {725 return makeIncrDecrExpr( appExpr, typeInst->get_name(), varExpr->get_var()->get_name() == "++?" );1321 if ( Type *baseType = isPolyPtr( appExpr->get_results().front(), scopeTyVars, env ) ) { 1322 return makeIncrDecrExpr( appExpr, baseType, varExpr->get_var()->get_name() == "++?" ); 726 1323 } // if 727 1324 } else if ( varExpr->get_var()->get_name() == "?+?" || varExpr->get_var()->get_name() == "?-?" ) { 728 1325 assert( ! appExpr->get_results().empty() ); 729 1326 assert( appExpr->get_args().size() == 2 ); 730 Type InstType *typeInst1 = isPolyPtr( appExpr->get_args().front()->get_results().front(), env, scopeTyVars);731 Type InstType *typeInst2 = isPolyPtr( appExpr->get_args().back()->get_results().front(), env, scopeTyVars);732 if ( typeInst1 && typeInst2 ) {1327 Type *baseType1 = isPolyPtr( appExpr->get_args().front()->get_results().front(), scopeTyVars, env ); 1328 Type *baseType2 = isPolyPtr( appExpr->get_args().back()->get_results().front(), scopeTyVars, env ); 1329 if ( baseType1 && baseType2 ) { 733 1330 UntypedExpr *divide = new UntypedExpr( new NameExpr( "?/?" ) ); 734 1331 divide->get_args().push_back( appExpr ); 735 divide->get_args().push_back( new NameExpr( typeInst1->get_name() ) );1332 divide->get_args().push_back( new SizeofExpr( baseType1->clone() ) ); 736 1333 divide->get_results().push_front( appExpr->get_results().front()->clone() ); 737 1334 if ( appExpr->get_env() ) { … … 740 1337 } // if 741 1338 return divide; 742 } else if ( typeInst1 ) {1339 } else if ( baseType1 ) { 743 1340 UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) ); 744 1341 multiply->get_args().push_back( appExpr->get_args().back() ); 745 multiply->get_args().push_back( new NameExpr( typeInst1->get_name() ) );1342 multiply->get_args().push_back( new SizeofExpr( baseType1->clone() ) ); 746 1343 appExpr->get_args().back() = multiply; 747 } else if ( typeInst2 ) {1344 } else if ( baseType2 ) { 748 1345 UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) ); 749 1346 multiply->get_args().push_back( appExpr->get_args().front() ); 750 multiply->get_args().push_back( new NameExpr( typeInst2->get_name() ) );1347 multiply->get_args().push_back( new SizeofExpr( baseType2->clone() ) ); 751 1348 appExpr->get_args().front() = multiply; 752 1349 } // if … … 754 1351 assert( ! appExpr->get_results().empty() ); 755 1352 assert( appExpr->get_args().size() == 2 ); 756 Type InstType *typeInst = isPolyPtr( appExpr->get_results().front(), env, scopeTyVars);757 if ( typeInst) {1353 Type *baseType = isPolyPtr( appExpr->get_results().front(), scopeTyVars, env ); 1354 if ( baseType ) { 758 1355 UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) ); 759 1356 multiply->get_args().push_back( appExpr->get_args().back() ); 760 multiply->get_args().push_back( new NameExpr( typeInst->get_name() ) );1357 multiply->get_args().push_back( new SizeofExpr( baseType->clone() ) ); 761 1358 appExpr->get_args().back() = multiply; 762 1359 } // if … … 769 1366 770 1367 Expression *Pass1::mutate( ApplicationExpr *appExpr ) { 771 ///std::cerr << "mutate appExpr: ";772 ///for ( TyVarMap::iterator i = scopeTyVars.begin(); i != scopeTyVars.end(); ++i ) {773 ///std::cerr << i->first << " ";774 ///}775 ///std::cerr << "\n";1368 // std::cerr << "mutate appExpr: "; 1369 // for ( TyVarMap::iterator i = scopeTyVars.begin(); i != scopeTyVars.end(); ++i ) { 1370 // std::cerr << i->first << " "; 1371 // } 1372 // std::cerr << "\n"; 776 1373 bool oldUseRetval = useRetval; 777 1374 useRetval = false; … … 779 1376 mutateAll( appExpr->get_args(), *this ); 780 1377 useRetval = oldUseRetval; 781 1378 782 1379 assert( ! appExpr->get_function()->get_results().empty() ); 783 1380 PointerType *pointer = dynamic_cast< PointerType *>( appExpr->get_function()->get_results().front() ); … … 785 1382 FunctionType *function = dynamic_cast< FunctionType *>( pointer->get_base() ); 786 1383 assert( function ); 787 1384 788 1385 if ( Expression *newExpr = handleIntrinsics( appExpr ) ) { 789 1386 return newExpr; 790 1387 } // if 791 1388 792 1389 Expression *ret = appExpr; 793 1390 794 1391 std::list< Expression *>::iterator arg = appExpr->get_args().begin(); 795 1392 std::list< Expression *>::iterator paramBegin = appExpr->get_args().begin(); 796 797 std::string typeName; 798 if ( isPolyRet( function, typeName ) ) { 799 ret = addPolyRetParam( appExpr, function, typeName, arg ); 1393 1394 TyVarMap exprTyVars( (TypeDecl::Kind)-1 ); 1395 makeTyVarMap( function, exprTyVars ); 1396 ReferenceToType *polyRetType = isPolyRet( function ); 1397 1398 if ( polyRetType ) { 1399 ret = addPolyRetParam( appExpr, function, polyRetType, arg ); 800 1400 } else if ( needsAdapter( function, scopeTyVars ) ) { 801 /// std::cerr << "needs adapter: "; 802 /// for ( TyVarMap::iterator i = scopeTyVars.begin(); i != scopeTyVars.end(); ++i ) { 803 /// std::cerr << i->first << " "; 804 /// } 805 /// std::cerr << "\n"; 1401 // std::cerr << "needs adapter: "; 1402 // printTyVarMap( std::cerr, scopeTyVars ); 1403 // std::cerr << *env << std::endl; 806 1404 // change the application so it calls the adapter rather than the passed function 807 1405 ret = applyAdapter( appExpr, function, arg, scopeTyVars ); 808 1406 } // if 809 1407 arg = appExpr->get_args().begin(); 810 811 TyVarMap exprTyVars; 812 makeTyVarMap( function, exprTyVars ); 813 814 passTypeVars( appExpr, arg, exprTyVars ); 1408 1409 passTypeVars( appExpr, polyRetType, arg, exprTyVars ); 815 1410 addInferredParams( appExpr, function, arg, exprTyVars ); 816 1411 817 1412 arg = paramBegin; 818 1413 819 1414 boxParams( appExpr, function, arg, exprTyVars ); 820 821 1415 passAdapters( appExpr, function, exprTyVars ); 822 1416 … … 825 1419 826 1420 Expression *Pass1::mutate( UntypedExpr *expr ) { 827 if ( ! expr->get_results().empty() && isPolyType( expr->get_results().front(), env, scopeTyVars) ) {1421 if ( ! expr->get_results().empty() && isPolyType( expr->get_results().front(), scopeTyVars, env ) ) { 828 1422 if ( NameExpr *name = dynamic_cast< NameExpr *>( expr->get_function() ) ) { 829 1423 if ( name->get_name() == "*?" ) { … … 840 1434 Expression *Pass1::mutate( AddressExpr *addrExpr ) { 841 1435 assert( ! addrExpr->get_arg()->get_results().empty() ); 1436 1437 bool needs = false; 1438 if ( UntypedExpr *expr = dynamic_cast< UntypedExpr *>( addrExpr->get_arg() ) ) { 1439 if ( ! expr->get_results().empty() && isPolyType( expr->get_results().front(), scopeTyVars, env ) ) { 1440 if ( NameExpr *name = dynamic_cast< NameExpr *>( expr->get_function() ) ) { 1441 if ( name->get_name() == "*?" ) { 1442 if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr->get_args().front() ) ) { 1443 assert( ! appExpr->get_function()->get_results().empty() ); 1444 PointerType *pointer = dynamic_cast< PointerType *>( appExpr->get_function()->get_results().front() ); 1445 assert( pointer ); 1446 FunctionType *function = dynamic_cast< FunctionType *>( pointer->get_base() ); 1447 assert( function ); 1448 needs = needsAdapter( function, scopeTyVars ); 1449 } // if 1450 } // if 1451 } // if 1452 } // if 1453 } // if 1454 // isPolyType check needs to happen before mutating addrExpr arg, so pull it forward 1455 // out of the if condition. 1456 bool polytype = isPolyType( addrExpr->get_arg()->get_results().front(), scopeTyVars, env ); 842 1457 addrExpr->set_arg( mutateExpression( addrExpr->get_arg() ) ); 843 if ( isPolyType( addrExpr->get_arg()->get_results().front(), env, scopeTyVars )) {1458 if ( polytype || needs ) { 844 1459 Expression *ret = addrExpr->get_arg(); 845 1460 delete ret->get_results().front(); … … 853 1468 } 854 1469 855 Statement * Pass1::mutate(ReturnStmt *retStmt) { 856 // a cast expr on a polymorphic return value is either redundant or invalid 857 while ( CastExpr *castExpr = dynamic_cast< CastExpr *>( retStmt->get_expr() ) ) { 858 retStmt->set_expr( castExpr->get_arg() ); 859 retStmt->get_expr()->set_env( castExpr->get_env() ); 860 castExpr->set_env( 0 ); 861 castExpr->set_arg( 0 ); 862 delete castExpr; 863 } 864 if ( retval && retStmt->get_expr() ) { 865 assert( ! retStmt->get_expr()->get_results().empty() ); 866 if ( retStmt->get_expr()->get_results().front()->get_isLvalue() ) { 867 /// retStmt->set_expr( mutateExpression( retStmt->get_expr() ) ); 868 TypeInstType *typeInst = dynamic_cast< TypeInstType *>( retval->get_type() ); 869 assert( typeInst ); 870 std::map< std::string, DeclarationWithType *>::const_iterator assignIter = assignOps.find( typeInst->get_name() ); 1470 /// Wraps a function declaration in a new pointer-to-function variable expression 1471 VariableExpr *wrapFunctionDecl( DeclarationWithType *functionDecl ) { 1472 // line below cloned from FixFunction.cc 1473 // xxx - functionObj is never added to a list of declarations... 1474 ObjectDecl *functionObj = new ObjectDecl( functionDecl->get_name(), functionDecl->get_storageClass(), functionDecl->get_linkage(), 0, 1475 new PointerType( Type::Qualifiers(), functionDecl->get_type()->clone() ), 0 ); 1476 functionObj->set_mangleName( functionDecl->get_mangleName() ); 1477 functionObj->set_scopeLevel( functionDecl->get_scopeLevel() ); 1478 return new VariableExpr( functionObj ); 1479 } 1480 1481 /// Finds the operation declaration for a given type in one of the two maps 1482 DeclarationWithType* findOpForType( Type *formalType, const ScopedMap< std::string, DeclarationWithType* >& ops, ResolvExpr::TypeMap< DeclarationWithType >& scopedOps ) { 1483 if ( TypeInstType *formalTypeInstType = dynamic_cast< TypeInstType* >( formalType ) ) { 1484 ScopedMap< std::string, DeclarationWithType *>::const_iterator opIt = ops.find( formalTypeInstType->get_name() ); 1485 return opIt == ops.end() ? 0 : opIt->second; 1486 } else { 1487 return scopedOps.find( formalType ); 1488 } 1489 } 1490 1491 /// Adds an assertion parameter to the application expression for the actual assertion declaration valued with the assert op 1492 void addAssertionFor( ApplicationExpr *appExpr, DeclarationWithType *actualDecl, DeclarationWithType *assertOp ) { 1493 appExpr->get_inferParams()[ actualDecl->get_uniqueId() ] 1494 = ParamEntry( assertOp->get_uniqueId(), assertOp->get_type()->clone(), actualDecl->get_type()->clone(), wrapFunctionDecl( assertOp ) ); 1495 } 1496 1497 Statement * Pass1::mutate( ReturnStmt *returnStmt ) { 1498 if ( retval && returnStmt->get_expr() ) { 1499 assert( ! returnStmt->get_expr()->get_results().empty() ); 1500 // ***** Code Removal ***** After introducing a temporary variable for all return expressions, the following code appears superfluous. 1501 // if ( returnStmt->get_expr()->get_results().front()->get_isLvalue() ) { 1502 // by this point, a cast expr on a polymorphic return value is redundant 1503 while ( CastExpr *castExpr = dynamic_cast< CastExpr *>( returnStmt->get_expr() ) ) { 1504 returnStmt->set_expr( castExpr->get_arg() ); 1505 returnStmt->get_expr()->set_env( castExpr->get_env() ); 1506 castExpr->set_env( 0 ); 1507 castExpr->set_arg( 0 ); 1508 delete castExpr; 1509 } //while 1510 1511 // find assignment operator for (polymorphic) return type 1512 ApplicationExpr *assignExpr = 0; 1513 if ( TypeInstType *typeInst = dynamic_cast< TypeInstType *>( retval->get_type() ) ) { 1514 // find assignment operator for type variable 1515 ScopedMap< std::string, DeclarationWithType *>::const_iterator assignIter = assignOps.find( typeInst->get_name() ); 871 1516 if ( assignIter == assignOps.end() ) { 872 throw SemanticError( "Attempt to return dtype or ftype object in ", ret Stmt->get_expr() );1517 throw SemanticError( "Attempt to return dtype or ftype object in ", returnStmt->get_expr() ); 873 1518 } // if 874 ApplicationExpr *assignExpr = new ApplicationExpr( new VariableExpr( assignIter->second ) ); 875 Expression *retParm = new NameExpr( retval->get_name() ); 876 retParm->get_results().push_back( new PointerType( Type::Qualifiers(), retval->get_type()->clone() ) ); 877 assignExpr->get_args().push_back( retParm ); 878 assignExpr->get_args().push_back( retStmt->get_expr() ); 879 stmtsToAdd.push_back( new ExprStmt( noLabels, mutateExpression( assignExpr ) ) ); 880 } else { 881 useRetval = true; 882 stmtsToAdd.push_back( new ExprStmt( noLabels, mutateExpression( retStmt->get_expr() ) ) ); 883 useRetval = false; 884 } // if 885 retStmt->set_expr( 0 ); 1519 assignExpr = new ApplicationExpr( new VariableExpr( assignIter->second ) ); 1520 } else if ( ReferenceToType *refType = dynamic_cast< ReferenceToType *>( retval->get_type() ) ) { 1521 // find assignment operator for generic type 1522 DeclarationWithType *functionDecl = scopedAssignOps.find( refType ); 1523 if ( ! functionDecl ) { 1524 throw SemanticError( "Attempt to return dtype or ftype generic object in ", returnStmt->get_expr() ); 1525 } 1526 1527 // wrap it up in an application expression 1528 assignExpr = new ApplicationExpr( wrapFunctionDecl( functionDecl ) ); 1529 assignExpr->set_env( env->clone() ); 1530 1531 // find each of its needed secondary assignment operators 1532 std::list< Expression* > &tyParams = refType->get_parameters(); 1533 std::list< TypeDecl* > &forallParams = functionDecl->get_type()->get_forall(); 1534 std::list< Expression* >::const_iterator tyIt = tyParams.begin(); 1535 std::list< TypeDecl* >::const_iterator forallIt = forallParams.begin(); 1536 for ( ; tyIt != tyParams.end() && forallIt != forallParams.end(); ++tyIt, ++forallIt ) { 1537 // Add appropriate mapping to assignment expression environment 1538 TypeExpr *formalTypeExpr = dynamic_cast< TypeExpr* >( *tyIt ); 1539 assert( formalTypeExpr && "type parameters must be type expressions" ); 1540 Type *formalType = formalTypeExpr->get_type(); 1541 assignExpr->get_env()->add( (*forallIt)->get_name(), formalType ); 1542 1543 // skip non-otype parameters (ftype/dtype) 1544 if ( (*forallIt)->get_kind() != TypeDecl::Any ) continue; 1545 1546 // find otype operators for formal type 1547 DeclarationWithType *assertAssign = findOpForType( formalType, assignOps, scopedAssignOps ); 1548 if ( ! assertAssign ) throw SemanticError( "No assignment operation found for ", formalType ); 1549 1550 DeclarationWithType *assertCtor = findOpForType( formalType, ctorOps, scopedCtorOps ); 1551 if ( ! assertCtor ) throw SemanticError( "No default constructor found for ", formalType ); 1552 1553 DeclarationWithType *assertCopy = findOpForType( formalType, copyOps, scopedCopyOps ); 1554 if ( ! assertCopy ) throw SemanticError( "No copy constructor found for ", formalType ); 1555 1556 DeclarationWithType *assertDtor = findOpForType( formalType, dtorOps, scopedDtorOps ); 1557 if ( ! assertDtor ) throw SemanticError( "No destructor found for ", formalType ); 1558 1559 // add inferred parameters for otype operators to assignment expression 1560 // NOTE: Code here assumes that first four assertions are assign op, ctor, copy ctor, dtor, in that order 1561 std::list< DeclarationWithType* > &asserts = (*forallIt)->get_assertions(); 1562 assert( asserts.size() >= 4 && "Type param needs otype operator assertions" ); 1563 1564 std::list< DeclarationWithType* >::iterator actualIt = asserts.begin(); 1565 addAssertionFor( assignExpr, *actualIt, assertAssign ); 1566 ++actualIt; 1567 addAssertionFor( assignExpr, *actualIt, assertCtor ); 1568 ++actualIt; 1569 addAssertionFor( assignExpr, *actualIt, assertCopy ); 1570 ++actualIt; 1571 addAssertionFor( assignExpr, *actualIt, assertDtor ); 1572 1573 } 1574 } 1575 assert( assignExpr ); 1576 1577 // replace return statement with appropriate assignment to out parameter 1578 Expression *retParm = new NameExpr( retval->get_name() ); 1579 retParm->get_results().push_back( new PointerType( Type::Qualifiers(), retval->get_type()->clone() ) ); 1580 assignExpr->get_args().push_back( retParm ); 1581 assignExpr->get_args().push_back( returnStmt->get_expr() ); 1582 stmtsToAdd.push_back( new ExprStmt( noLabels, mutateExpression( assignExpr ) ) ); 1583 // } else { 1584 // useRetval = true; 1585 // stmtsToAdd.push_back( new ExprStmt( noLabels, mutateExpression( returnStmt->get_expr() ) ) ); 1586 // useRetval = false; 1587 // } // if 1588 returnStmt->set_expr( 0 ); 886 1589 } else { 887 ret Stmt->set_expr( mutateExpression( retStmt->get_expr() ) );1590 returnStmt->set_expr( mutateExpression( returnStmt->get_expr() ) ); 888 1591 } // if 889 return ret Stmt;1592 return returnStmt; 890 1593 } 891 1594 892 1595 Type * Pass1::mutate( PointerType *pointerType ) { 893 TyVarMap oldtyVars = scopeTyVars;1596 scopeTyVars.beginScope(); 894 1597 makeTyVarMap( pointerType, scopeTyVars ); 895 1598 896 1599 Type *ret = Mutator::mutate( pointerType ); 897 898 scopeTyVars = oldtyVars;1600 1601 scopeTyVars.endScope(); 899 1602 return ret; 900 1603 } 901 1604 902 1605 Type * Pass1::mutate( FunctionType *functionType ) { 903 TyVarMap oldtyVars = scopeTyVars;1606 scopeTyVars.beginScope(); 904 1607 makeTyVarMap( functionType, scopeTyVars ); 905 1608 906 1609 Type *ret = Mutator::mutate( functionType ); 907 908 scopeTyVars = oldtyVars;1610 1611 scopeTyVars.endScope(); 909 1612 return ret; 910 1613 } 911 1614 912 1615 void Pass1::doBeginScope() { 913 // actually, maybe this could (should?) push 914 // a copy of the current map 915 adapters.push(AdapterMap()); 1616 adapters.beginScope(); 1617 scopedAssignOps.beginScope(); 1618 scopedCtorOps.beginScope(); 1619 scopedCopyOps.beginScope(); 1620 scopedDtorOps.beginScope(); 916 1621 } 917 1622 918 1623 void Pass1::doEndScope() { 919 adapters.pop(); 1624 adapters.endScope(); 1625 scopedAssignOps.endScope(); 1626 scopedCtorOps.endScope(); 1627 scopedCopyOps.endScope(); 1628 scopedDtorOps.endScope(); 920 1629 } 921 1630 922 1631 ////////////////////////////////////////// Pass2 //////////////////////////////////////////////////// 923 924 Pass2::Pass2() {}925 1632 926 1633 void Pass2::addAdapters( FunctionType *functionType ) { … … 934 1641 std::set< std::string > adaptersDone; 935 1642 for ( std::list< FunctionType *>::iterator funType = functions.begin(); funType != functions.end(); ++funType ) { 936 std::string mangleName = SymTab::Mangler::mangle( *funType);1643 std::string mangleName = mangleAdapterName( *funType, scopeTyVars ); 937 1644 if ( adaptersDone.find( mangleName ) == adaptersDone.end() ) { 938 1645 std::string adapterName = makeAdapterName( mangleName ); … … 941 1648 } 942 1649 } 943 // /deleteAll( functions );1650 // deleteAll( functions ); 944 1651 } 945 1652 … … 973 1680 974 1681 Type * Pass2::mutate( PointerType *pointerType ) { 975 TyVarMap oldtyVars = scopeTyVars;1682 scopeTyVars.beginScope(); 976 1683 makeTyVarMap( pointerType, scopeTyVars ); 977 1684 978 1685 Type *ret = Mutator::mutate( pointerType ); 979 980 scopeTyVars = oldtyVars;1686 1687 scopeTyVars.endScope(); 981 1688 return ret; 982 1689 } 983 1690 984 1691 Type *Pass2::mutate( FunctionType *funcType ) { 985 TyVarMap oldtyVars = scopeTyVars;1692 scopeTyVars.beginScope(); 986 1693 makeTyVarMap( funcType, scopeTyVars ); 987 988 std::string typeName;989 if ( isPolyRet( funcType , typeName) ) {1694 1695 // move polymorphic return type to parameter list 1696 if ( isPolyRet( funcType ) ) { 990 1697 DeclarationWithType *ret = funcType->get_returnVals().front(); 991 1698 ret->set_type( new PointerType( Type::Qualifiers(), ret->get_type() ) ); … … 993 1700 funcType->get_returnVals().pop_front(); 994 1701 } 995 1702 1703 // add size/align and assertions for type parameters to parameter list 996 1704 std::list< DeclarationWithType *>::iterator last = funcType->get_parameters().begin(); 997 1705 std::list< DeclarationWithType *> inferredParams; 998 ObjectDecl *newObj = new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), 0 ); 999 /// ObjectDecl *newFunPtr = new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), new FunctionType( Type::Qualifiers(), true ) ), 0 ); 1706 ObjectDecl newObj( "", DeclarationNode::NoStorageClass, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), 0 ); 1707 ObjectDecl newPtr( "", DeclarationNode::NoStorageClass, LinkageSpec::C, 0, 1708 new PointerType( Type::Qualifiers(), new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) ), 0 ); 1000 1709 for ( std::list< TypeDecl *>::const_iterator tyParm = funcType->get_forall().begin(); tyParm != funcType->get_forall().end(); ++tyParm ) { 1001 ObjectDecl *thisParm; 1710 ObjectDecl *sizeParm, *alignParm; 1711 // add all size and alignment parameters to parameter list 1002 1712 if ( (*tyParm)->get_kind() == TypeDecl::Any ) { 1003 thisParm = newObj->clone(); 1004 thisParm->set_name( (*tyParm)->get_name() ); 1005 last = funcType->get_parameters().insert( last, thisParm ); 1713 TypeInstType parmType( Type::Qualifiers(), (*tyParm)->get_name(), *tyParm ); 1714 std::string parmName = mangleType( &parmType ); 1715 1716 sizeParm = newObj.clone(); 1717 sizeParm->set_name( sizeofName( parmName ) ); 1718 last = funcType->get_parameters().insert( last, sizeParm ); 1719 ++last; 1720 1721 alignParm = newObj.clone(); 1722 alignParm->set_name( alignofName( parmName ) ); 1723 last = funcType->get_parameters().insert( last, alignParm ); 1006 1724 ++last; 1007 1725 } 1726 // move all assertions into parameter list 1008 1727 for ( std::list< DeclarationWithType *>::iterator assert = (*tyParm)->get_assertions().begin(); assert != (*tyParm)->get_assertions().end(); ++assert ) { 1009 // /*assert = (*assert)->acceptMutator( *this );1728 // *assert = (*assert)->acceptMutator( *this ); 1010 1729 inferredParams.push_back( *assert ); 1011 1730 } 1012 1731 (*tyParm)->get_assertions().clear(); 1013 1732 } 1014 delete newObj; 1733 1734 // add size/align for generic parameter types to parameter list 1735 std::set< std::string > seenTypes; // sizeofName for generic types we've seen 1736 for ( std::list< DeclarationWithType* >::const_iterator fnParm = last; fnParm != funcType->get_parameters().end(); ++fnParm ) { 1737 Type *polyType = isPolyType( (*fnParm)->get_type(), scopeTyVars ); 1738 if ( polyType && ! dynamic_cast< TypeInstType* >( polyType ) ) { 1739 std::string typeName = mangleType( polyType ); 1740 if ( seenTypes.count( typeName ) ) continue; 1741 1742 ObjectDecl *sizeParm, *alignParm, *offsetParm; 1743 sizeParm = newObj.clone(); 1744 sizeParm->set_name( sizeofName( typeName ) ); 1745 last = funcType->get_parameters().insert( last, sizeParm ); 1746 ++last; 1747 1748 alignParm = newObj.clone(); 1749 alignParm->set_name( alignofName( typeName ) ); 1750 last = funcType->get_parameters().insert( last, alignParm ); 1751 ++last; 1752 1753 if ( StructInstType *polyBaseStruct = dynamic_cast< StructInstType* >( polyType ) ) { 1754 // NOTE zero-length arrays are illegal in C, so empty structs have no offset array 1755 if ( ! polyBaseStruct->get_baseStruct()->get_members().empty() ) { 1756 offsetParm = newPtr.clone(); 1757 offsetParm->set_name( offsetofName( typeName ) ); 1758 last = funcType->get_parameters().insert( last, offsetParm ); 1759 ++last; 1760 } 1761 } 1762 1763 seenTypes.insert( typeName ); 1764 } 1765 } 1766 1767 // splice assertion parameters into parameter list 1015 1768 funcType->get_parameters().splice( last, inferredParams ); 1016 1769 addAdapters( funcType ); 1017 1770 mutateAll( funcType->get_returnVals(), *this ); 1018 1771 mutateAll( funcType->get_parameters(), *this ); 1019 1020 scopeTyVars = oldtyVars;1772 1773 scopeTyVars.endScope(); 1021 1774 return funcType; 1775 } 1776 1777 //////////////////////////////////////// GenericInstantiator ////////////////////////////////////////////////// 1778 1779 /// Makes substitutions of params into baseParams; returns true if all parameters substituted for a concrete type 1780 bool makeSubstitutions( const std::list< TypeDecl* >& baseParams, const std::list< Expression* >& params, std::list< TypeExpr* >& out ) { 1781 bool allConcrete = true; // will finish the substitution list even if they're not all concrete 1782 1783 // substitute concrete types for given parameters, and incomplete types for placeholders 1784 std::list< TypeDecl* >::const_iterator baseParam = baseParams.begin(); 1785 std::list< Expression* >::const_iterator param = params.begin(); 1786 for ( ; baseParam != baseParams.end() && param != params.end(); ++baseParam, ++param ) { 1787 // switch ( (*baseParam)->get_kind() ) { 1788 // case TypeDecl::Any: { // any type is a valid substitution here; complete types can be used to instantiate generics 1789 TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param ); 1790 assert(paramType && "Aggregate parameters should be type expressions"); 1791 out.push_back( paramType->clone() ); 1792 // check that the substituted type isn't a type variable itself 1793 if ( dynamic_cast< TypeInstType* >( paramType->get_type() ) ) { 1794 allConcrete = false; 1795 } 1796 // break; 1797 // } 1798 // case TypeDecl::Dtype: // dtype can be consistently replaced with void [only pointers, which become void*] 1799 // out.push_back( new TypeExpr( new VoidType( Type::Qualifiers() ) ) ); 1800 // break; 1801 // case TypeDecl::Ftype: // pointer-to-ftype can be consistently replaced with void (*)(void) [similar to dtype] 1802 // out.push_back( new TypeExpr( new FunctionType( Type::Qualifiers(), false ) ) ); 1803 // break; 1804 // } 1805 } 1806 1807 // if any parameters left over, not done 1808 if ( baseParam != baseParams.end() ) return false; 1809 // // if not enough parameters given, substitute remaining incomplete types for placeholders 1810 // for ( ; baseParam != baseParams.end(); ++baseParam ) { 1811 // switch ( (*baseParam)->get_kind() ) { 1812 // case TypeDecl::Any: // no more substitutions here, fail early 1813 // return false; 1814 // case TypeDecl::Dtype: // dtype can be consistently replaced with void [only pointers, which become void*] 1815 // out.push_back( new TypeExpr( new VoidType( Type::Qualifiers() ) ) ); 1816 // break; 1817 // case TypeDecl::Ftype: // pointer-to-ftype can be consistently replaced with void (*)(void) [similar to dtype] 1818 // out.push_back( new TypeExpr( new FunctionType( Type::Qualifiers(), false ) ) ); 1819 // break; 1820 // } 1821 // } 1822 1823 return allConcrete; 1824 } 1825 1826 /// Substitutes types of members of in according to baseParams => typeSubs, appending the result to out 1827 void substituteMembers( const std::list< Declaration* >& in, const std::list< TypeDecl* >& baseParams, const std::list< TypeExpr* >& typeSubs, 1828 std::list< Declaration* >& out ) { 1829 // substitute types into new members 1830 TypeSubstitution subs( baseParams.begin(), baseParams.end(), typeSubs.begin() ); 1831 for ( std::list< Declaration* >::const_iterator member = in.begin(); member != in.end(); ++member ) { 1832 Declaration *newMember = (*member)->clone(); 1833 subs.apply(newMember); 1834 out.push_back( newMember ); 1835 } 1836 } 1837 1838 Type* GenericInstantiator::mutate( StructInstType *inst ) { 1839 // mutate subtypes 1840 Type *mutated = Mutator::mutate( inst ); 1841 inst = dynamic_cast< StructInstType* >( mutated ); 1842 if ( ! inst ) return mutated; 1843 1844 // exit early if no need for further mutation 1845 if ( inst->get_parameters().empty() ) return inst; 1846 assert( inst->get_baseParameters() && "Base struct has parameters" ); 1847 1848 // check if type can be concretely instantiated; put substitutions into typeSubs 1849 std::list< TypeExpr* > typeSubs; 1850 if ( ! makeSubstitutions( *inst->get_baseParameters(), inst->get_parameters(), typeSubs ) ) { 1851 deleteAll( typeSubs ); 1852 return inst; 1853 } 1854 1855 // make concrete instantiation of generic type 1856 StructDecl *concDecl = lookup( inst, typeSubs ); 1857 if ( ! concDecl ) { 1858 // set concDecl to new type, insert type declaration into statements to add 1859 concDecl = new StructDecl( typeNamer.newName( inst->get_name() ) ); 1860 substituteMembers( inst->get_baseStruct()->get_members(), *inst->get_baseParameters(), typeSubs, concDecl->get_members() ); 1861 DeclMutator::addDeclaration( concDecl ); 1862 insert( inst, typeSubs, concDecl ); 1863 } 1864 StructInstType *newInst = new StructInstType( inst->get_qualifiers(), concDecl->get_name() ); 1865 newInst->set_baseStruct( concDecl ); 1866 1867 deleteAll( typeSubs ); 1868 delete inst; 1869 return newInst; 1870 } 1871 1872 Type* GenericInstantiator::mutate( UnionInstType *inst ) { 1873 // mutate subtypes 1874 Type *mutated = Mutator::mutate( inst ); 1875 inst = dynamic_cast< UnionInstType* >( mutated ); 1876 if ( ! inst ) return mutated; 1877 1878 // exit early if no need for further mutation 1879 if ( inst->get_parameters().empty() ) return inst; 1880 assert( inst->get_baseParameters() && "Base union has parameters" ); 1881 1882 // check if type can be concretely instantiated; put substitutions into typeSubs 1883 std::list< TypeExpr* > typeSubs; 1884 if ( ! makeSubstitutions( *inst->get_baseParameters(), inst->get_parameters(), typeSubs ) ) { 1885 deleteAll( typeSubs ); 1886 return inst; 1887 } 1888 1889 // make concrete instantiation of generic type 1890 UnionDecl *concDecl = lookup( inst, typeSubs ); 1891 if ( ! concDecl ) { 1892 // set concDecl to new type, insert type declaration into statements to add 1893 concDecl = new UnionDecl( typeNamer.newName( inst->get_name() ) ); 1894 substituteMembers( inst->get_baseUnion()->get_members(), *inst->get_baseParameters(), typeSubs, concDecl->get_members() ); 1895 DeclMutator::addDeclaration( concDecl ); 1896 insert( inst, typeSubs, concDecl ); 1897 } 1898 UnionInstType *newInst = new UnionInstType( inst->get_qualifiers(), concDecl->get_name() ); 1899 newInst->set_baseUnion( concDecl ); 1900 1901 deleteAll( typeSubs ); 1902 delete inst; 1903 return newInst; 1904 } 1905 1906 // /// Gets the base struct or union declaration for a member expression; NULL if not applicable 1907 // AggregateDecl* getMemberBaseDecl( MemberExpr *memberExpr ) { 1908 // // get variable for member aggregate 1909 // VariableExpr *varExpr = dynamic_cast< VariableExpr* >( memberExpr->get_aggregate() ); 1910 // if ( ! varExpr ) return NULL; 1911 // 1912 // // get object for variable 1913 // ObjectDecl *objectDecl = dynamic_cast< ObjectDecl* >( varExpr->get_var() ); 1914 // if ( ! objectDecl ) return NULL; 1915 // 1916 // // get base declaration from object type 1917 // Type *objectType = objectDecl->get_type(); 1918 // StructInstType *structType = dynamic_cast< StructInstType* >( objectType ); 1919 // if ( structType ) return structType->get_baseStruct(); 1920 // UnionInstType *unionType = dynamic_cast< UnionInstType* >( objectType ); 1921 // if ( unionType ) return unionType->get_baseUnion(); 1922 // 1923 // return NULL; 1924 // } 1925 // 1926 // /// Finds the declaration with the given name, returning decls.end() if none such 1927 // std::list< Declaration* >::const_iterator findDeclNamed( const std::list< Declaration* > &decls, const std::string &name ) { 1928 // for( std::list< Declaration* >::const_iterator decl = decls.begin(); decl != decls.end(); ++decl ) { 1929 // if ( (*decl)->get_name() == name ) return decl; 1930 // } 1931 // return decls.end(); 1932 // } 1933 // 1934 // Expression* Instantiate::mutate( MemberExpr *memberExpr ) { 1935 // // mutate, exiting early if no longer MemberExpr 1936 // Expression *expr = Mutator::mutate( memberExpr ); 1937 // memberExpr = dynamic_cast< MemberExpr* >( expr ); 1938 // if ( ! memberExpr ) return expr; 1939 // 1940 // // get declaration of member and base declaration of member, exiting early if not found 1941 // AggregateDecl *memberBase = getMemberBaseDecl( memberExpr ); 1942 // if ( ! memberBase ) return memberExpr; 1943 // DeclarationWithType *memberDecl = memberExpr->get_member(); 1944 // std::list< Declaration* >::const_iterator baseIt = findDeclNamed( memberBase->get_members(), memberDecl->get_name() ); 1945 // if ( baseIt == memberBase->get_members().end() ) return memberExpr; 1946 // DeclarationWithType *baseDecl = dynamic_cast< DeclarationWithType* >( *baseIt ); 1947 // if ( ! baseDecl ) return memberExpr; 1948 // 1949 // // check if stated type of the member is not the type of the member's declaration; if so, need a cast 1950 // // this *SHOULD* be safe, I don't think anything but the void-replacements I put in for dtypes would make it past the typechecker 1951 // SymTab::Indexer dummy; 1952 // if ( ResolvExpr::typesCompatible( memberDecl->get_type(), baseDecl->get_type(), dummy ) ) return memberExpr; 1953 // else return new CastExpr( memberExpr, memberDecl->get_type() ); 1954 // } 1955 1956 void GenericInstantiator::doBeginScope() { 1957 DeclMutator::doBeginScope(); 1958 instantiations.beginScope(); 1959 } 1960 1961 void GenericInstantiator::doEndScope() { 1962 DeclMutator::doEndScope(); 1963 instantiations.endScope(); 1964 } 1965 1966 ////////////////////////////////////////// PolyGenericCalculator //////////////////////////////////////////////////// 1967 1968 void PolyGenericCalculator::beginTypeScope( Type *ty ) { 1969 scopeTyVars.beginScope(); 1970 makeTyVarMap( ty, scopeTyVars ); 1971 } 1972 1973 void PolyGenericCalculator::endTypeScope() { 1974 scopeTyVars.endScope(); 1975 } 1976 1977 template< typename DeclClass > 1978 DeclClass * PolyGenericCalculator::handleDecl( DeclClass *decl, Type *type ) { 1979 beginTypeScope( type ); 1980 knownLayouts.beginScope(); 1981 knownOffsets.beginScope(); 1982 1983 DeclClass *ret = static_cast< DeclClass *>( Mutator::mutate( decl ) ); 1984 1985 knownOffsets.endScope(); 1986 knownLayouts.endScope(); 1987 endTypeScope(); 1988 return ret; 1989 } 1990 1991 ObjectDecl * PolyGenericCalculator::mutate( ObjectDecl *objectDecl ) { 1992 return handleDecl( objectDecl, objectDecl->get_type() ); 1993 } 1994 1995 DeclarationWithType * PolyGenericCalculator::mutate( FunctionDecl *functionDecl ) { 1996 return handleDecl( functionDecl, functionDecl->get_functionType() ); 1997 } 1998 1999 TypedefDecl * PolyGenericCalculator::mutate( TypedefDecl *typedefDecl ) { 2000 return handleDecl( typedefDecl, typedefDecl->get_base() ); 2001 } 2002 2003 TypeDecl * PolyGenericCalculator::mutate( TypeDecl *typeDecl ) { 2004 scopeTyVars[ typeDecl->get_name() ] = typeDecl->get_kind(); 2005 return Mutator::mutate( typeDecl ); 2006 } 2007 2008 Type * PolyGenericCalculator::mutate( PointerType *pointerType ) { 2009 beginTypeScope( pointerType ); 2010 2011 Type *ret = Mutator::mutate( pointerType ); 2012 2013 endTypeScope(); 2014 return ret; 2015 } 2016 2017 Type * PolyGenericCalculator::mutate( FunctionType *funcType ) { 2018 beginTypeScope( funcType ); 2019 2020 // make sure that any type information passed into the function is accounted for 2021 for ( std::list< DeclarationWithType* >::const_iterator fnParm = funcType->get_parameters().begin(); fnParm != funcType->get_parameters().end(); ++fnParm ) { 2022 // condition here duplicates that in Pass2::mutate( FunctionType* ) 2023 Type *polyType = isPolyType( (*fnParm)->get_type(), scopeTyVars ); 2024 if ( polyType && ! dynamic_cast< TypeInstType* >( polyType ) ) { 2025 knownLayouts.insert( mangleType( polyType ) ); 2026 } 2027 } 2028 2029 Type *ret = Mutator::mutate( funcType ); 2030 2031 endTypeScope(); 2032 return ret; 2033 } 2034 2035 Statement *PolyGenericCalculator::mutate( DeclStmt *declStmt ) { 2036 if ( ObjectDecl *objectDecl = dynamic_cast< ObjectDecl *>( declStmt->get_decl() ) ) { 2037 if ( findGeneric( objectDecl->get_type() ) ) { 2038 // change initialization of a polymorphic value object 2039 // to allocate storage with alloca 2040 Type *declType = objectDecl->get_type(); 2041 UntypedExpr *alloc = new UntypedExpr( new NameExpr( "__builtin_alloca" ) ); 2042 alloc->get_args().push_back( new NameExpr( sizeofName( mangleType( declType ) ) ) ); 2043 2044 delete objectDecl->get_init(); 2045 2046 std::list<Expression*> designators; 2047 objectDecl->set_init( new SingleInit( alloc, designators, false ) ); // not constructed 2048 } 2049 } 2050 return Mutator::mutate( declStmt ); 2051 } 2052 2053 /// Finds the member in the base list that matches the given declaration; returns its index, or -1 if not present 2054 long findMember( DeclarationWithType *memberDecl, std::list< Declaration* > &baseDecls ) { 2055 long i = 0; 2056 for(std::list< Declaration* >::const_iterator decl = baseDecls.begin(); decl != baseDecls.end(); ++decl, ++i ) { 2057 if ( memberDecl->get_name() != (*decl)->get_name() ) continue; 2058 2059 if ( DeclarationWithType *declWithType = dynamic_cast< DeclarationWithType* >( *decl ) ) { 2060 if ( memberDecl->get_mangleName().empty() || declWithType->get_mangleName().empty() 2061 || memberDecl->get_mangleName() == declWithType->get_mangleName() ) return i; 2062 else continue; 2063 } else return i; 2064 } 2065 return -1; 2066 } 2067 2068 /// Returns an index expression into the offset array for a type 2069 Expression *makeOffsetIndex( Type *objectType, long i ) { 2070 std::stringstream offset_namer; 2071 offset_namer << i; 2072 ConstantExpr *fieldIndex = new ConstantExpr( Constant( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), offset_namer.str() ) ); 2073 UntypedExpr *fieldOffset = new UntypedExpr( new NameExpr( "?[?]" ) ); 2074 fieldOffset->get_args().push_back( new NameExpr( offsetofName( mangleType( objectType ) ) ) ); 2075 fieldOffset->get_args().push_back( fieldIndex ); 2076 return fieldOffset; 2077 } 2078 2079 /// Returns an expression dereferenced n times 2080 Expression *makeDerefdVar( Expression *derefdVar, long n ) { 2081 for ( int i = 1; i < n; ++i ) { 2082 UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) ); 2083 derefExpr->get_args().push_back( derefdVar ); 2084 // xxx - should set results on derefExpr 2085 derefdVar = derefExpr; 2086 } 2087 return derefdVar; 2088 } 2089 2090 Expression *PolyGenericCalculator::mutate( MemberExpr *memberExpr ) { 2091 // mutate, exiting early if no longer MemberExpr 2092 Expression *expr = Mutator::mutate( memberExpr ); 2093 memberExpr = dynamic_cast< MemberExpr* >( expr ); 2094 if ( ! memberExpr ) return expr; 2095 2096 // get declaration for base struct, exiting early if not found 2097 int varDepth; 2098 VariableExpr *varExpr = getBaseVar( memberExpr->get_aggregate(), &varDepth ); 2099 if ( ! varExpr ) return memberExpr; 2100 ObjectDecl *objectDecl = dynamic_cast< ObjectDecl* >( varExpr->get_var() ); 2101 if ( ! objectDecl ) return memberExpr; 2102 2103 // only mutate member expressions for polymorphic types 2104 int tyDepth; 2105 Type *objectType = hasPolyBase( objectDecl->get_type(), scopeTyVars, &tyDepth ); 2106 if ( ! objectType ) return memberExpr; 2107 findGeneric( objectType ); // ensure layout for this type is available 2108 2109 Expression *newMemberExpr = 0; 2110 if ( StructInstType *structType = dynamic_cast< StructInstType* >( objectType ) ) { 2111 // look up offset index 2112 long i = findMember( memberExpr->get_member(), structType->get_baseStruct()->get_members() ); 2113 if ( i == -1 ) return memberExpr; 2114 2115 // replace member expression with pointer to base plus offset 2116 UntypedExpr *fieldLoc = new UntypedExpr( new NameExpr( "?+?" ) ); 2117 fieldLoc->get_args().push_back( makeDerefdVar( varExpr->clone(), varDepth ) ); 2118 fieldLoc->get_args().push_back( makeOffsetIndex( objectType, i ) ); 2119 newMemberExpr = fieldLoc; 2120 } else if ( dynamic_cast< UnionInstType* >( objectType ) ) { 2121 // union members are all at offset zero, so build appropriately-dereferenced variable 2122 newMemberExpr = makeDerefdVar( varExpr->clone(), varDepth ); 2123 } else return memberExpr; 2124 assert( newMemberExpr ); 2125 2126 Type *memberType = memberExpr->get_member()->get_type(); 2127 if ( ! isPolyType( memberType, scopeTyVars ) ) { 2128 // Not all members of a polymorphic type are themselves of polymorphic type; in this case the member expression should be wrapped and dereferenced to form an lvalue 2129 CastExpr *ptrCastExpr = new CastExpr( newMemberExpr, new PointerType( Type::Qualifiers(), memberType->clone() ) ); 2130 UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) ); 2131 derefExpr->get_args().push_back( ptrCastExpr ); 2132 newMemberExpr = derefExpr; 2133 } 2134 2135 delete memberExpr; 2136 return newMemberExpr; 2137 } 2138 2139 ObjectDecl *PolyGenericCalculator::makeVar( const std::string &name, Type *type, Initializer *init ) { 2140 ObjectDecl *newObj = new ObjectDecl( name, DeclarationNode::NoStorageClass, LinkageSpec::C, 0, type, init ); 2141 stmtsToAdd.push_back( new DeclStmt( noLabels, newObj ) ); 2142 return newObj; 2143 } 2144 2145 void PolyGenericCalculator::addOtypeParamsToLayoutCall( UntypedExpr *layoutCall, const std::list< Type* > &otypeParams ) { 2146 for ( std::list< Type* >::const_iterator param = otypeParams.begin(); param != otypeParams.end(); ++param ) { 2147 if ( findGeneric( *param ) ) { 2148 // push size/align vars for a generic parameter back 2149 std::string paramName = mangleType( *param ); 2150 layoutCall->get_args().push_back( new NameExpr( sizeofName( paramName ) ) ); 2151 layoutCall->get_args().push_back( new NameExpr( alignofName( paramName ) ) ); 2152 } else { 2153 layoutCall->get_args().push_back( new SizeofExpr( (*param)->clone() ) ); 2154 layoutCall->get_args().push_back( new AlignofExpr( (*param)->clone() ) ); 2155 } 2156 } 2157 } 2158 2159 /// returns true if any of the otype parameters have a dynamic layout and puts all otype parameters in the output list 2160 bool findGenericParams( std::list< TypeDecl* > &baseParams, std::list< Expression* > &typeParams, std::list< Type* > &out ) { 2161 bool hasDynamicLayout = false; 2162 2163 std::list< TypeDecl* >::const_iterator baseParam = baseParams.begin(); 2164 std::list< Expression* >::const_iterator typeParam = typeParams.begin(); 2165 for ( ; baseParam != baseParams.end() && typeParam != typeParams.end(); ++baseParam, ++typeParam ) { 2166 // skip non-otype parameters 2167 if ( (*baseParam)->get_kind() != TypeDecl::Any ) continue; 2168 TypeExpr *typeExpr = dynamic_cast< TypeExpr* >( *typeParam ); 2169 assert( typeExpr && "all otype parameters should be type expressions" ); 2170 2171 Type *type = typeExpr->get_type(); 2172 out.push_back( type ); 2173 if ( isPolyType( type ) ) hasDynamicLayout = true; 2174 } 2175 assert( baseParam == baseParams.end() && typeParam == typeParams.end() ); 2176 2177 return hasDynamicLayout; 2178 } 2179 2180 bool PolyGenericCalculator::findGeneric( Type *ty ) { 2181 ty = replaceTypeInst( ty, env ); 2182 2183 if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( ty ) ) { 2184 if ( scopeTyVars.find( typeInst->get_name() ) != scopeTyVars.end() ) { 2185 // NOTE assumes here that getting put in the scopeTyVars included having the layout variables set 2186 return true; 2187 } 2188 return false; 2189 } else if ( StructInstType *structTy = dynamic_cast< StructInstType* >( ty ) ) { 2190 // check if this type already has a layout generated for it 2191 std::string typeName = mangleType( ty ); 2192 if ( knownLayouts.find( typeName ) != knownLayouts.end() ) return true; 2193 2194 // check if any of the type parameters have dynamic layout; if none do, this type is (or will be) monomorphized 2195 std::list< Type* > otypeParams; 2196 if ( ! findGenericParams( *structTy->get_baseParameters(), structTy->get_parameters(), otypeParams ) ) return false; 2197 2198 // insert local variables for layout and generate call to layout function 2199 knownLayouts.insert( typeName ); // done early so as not to interfere with the later addition of parameters to the layout call 2200 Type *layoutType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ); 2201 2202 int n_members = structTy->get_baseStruct()->get_members().size(); 2203 if ( n_members == 0 ) { 2204 // all empty structs have the same layout - size 1, align 1 2205 makeVar( sizeofName( typeName ), layoutType, new SingleInit( new ConstantExpr( Constant::from_ulong( (unsigned long)1 ) ) ) ); 2206 makeVar( alignofName( typeName ), layoutType->clone(), new SingleInit( new ConstantExpr( Constant::from_ulong( (unsigned long)1 ) ) ) ); 2207 // NOTE zero-length arrays are forbidden in C, so empty structs have no offsetof array 2208 } else { 2209 ObjectDecl *sizeVar = makeVar( sizeofName( typeName ), layoutType ); 2210 ObjectDecl *alignVar = makeVar( alignofName( typeName ), layoutType->clone() ); 2211 ObjectDecl *offsetVar = makeVar( offsetofName( typeName ), new ArrayType( Type::Qualifiers(), layoutType->clone(), new ConstantExpr( Constant::from_int( n_members ) ), false, false ) ); 2212 2213 // generate call to layout function 2214 UntypedExpr *layoutCall = new UntypedExpr( new NameExpr( layoutofName( structTy->get_baseStruct() ) ) ); 2215 layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( sizeVar ) ) ); 2216 layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( alignVar ) ) ); 2217 layoutCall->get_args().push_back( new VariableExpr( offsetVar ) ); 2218 addOtypeParamsToLayoutCall( layoutCall, otypeParams ); 2219 2220 stmtsToAdd.push_back( new ExprStmt( noLabels, layoutCall ) ); 2221 } 2222 2223 return true; 2224 } else if ( UnionInstType *unionTy = dynamic_cast< UnionInstType* >( ty ) ) { 2225 // check if this type already has a layout generated for it 2226 std::string typeName = mangleType( ty ); 2227 if ( knownLayouts.find( typeName ) != knownLayouts.end() ) return true; 2228 2229 // check if any of the type parameters have dynamic layout; if none do, this type is (or will be) monomorphized 2230 std::list< Type* > otypeParams; 2231 if ( ! findGenericParams( *unionTy->get_baseParameters(), unionTy->get_parameters(), otypeParams ) ) return false; 2232 2233 // insert local variables for layout and generate call to layout function 2234 knownLayouts.insert( typeName ); // done early so as not to interfere with the later addition of parameters to the layout call 2235 Type *layoutType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ); 2236 2237 ObjectDecl *sizeVar = makeVar( sizeofName( typeName ), layoutType ); 2238 ObjectDecl *alignVar = makeVar( alignofName( typeName ), layoutType->clone() ); 2239 2240 // generate call to layout function 2241 UntypedExpr *layoutCall = new UntypedExpr( new NameExpr( layoutofName( unionTy->get_baseUnion() ) ) ); 2242 layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( sizeVar ) ) ); 2243 layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( alignVar ) ) ); 2244 addOtypeParamsToLayoutCall( layoutCall, otypeParams ); 2245 2246 stmtsToAdd.push_back( new ExprStmt( noLabels, layoutCall ) ); 2247 2248 return true; 2249 } 2250 2251 return false; 2252 } 2253 2254 Expression *PolyGenericCalculator::mutate( SizeofExpr *sizeofExpr ) { 2255 Type *ty = sizeofExpr->get_type(); 2256 if ( findGeneric( ty ) ) { 2257 Expression *ret = new NameExpr( sizeofName( mangleType( ty ) ) ); 2258 delete sizeofExpr; 2259 return ret; 2260 } 2261 return sizeofExpr; 2262 } 2263 2264 Expression *PolyGenericCalculator::mutate( AlignofExpr *alignofExpr ) { 2265 Type *ty = alignofExpr->get_type(); 2266 if ( findGeneric( ty ) ) { 2267 Expression *ret = new NameExpr( alignofName( mangleType( ty ) ) ); 2268 delete alignofExpr; 2269 return ret; 2270 } 2271 return alignofExpr; 2272 } 2273 2274 Expression *PolyGenericCalculator::mutate( OffsetofExpr *offsetofExpr ) { 2275 // mutate, exiting early if no longer OffsetofExpr 2276 Expression *expr = Mutator::mutate( offsetofExpr ); 2277 offsetofExpr = dynamic_cast< OffsetofExpr* >( expr ); 2278 if ( ! offsetofExpr ) return expr; 2279 2280 // only mutate expressions for polymorphic structs/unions 2281 Type *ty = offsetofExpr->get_type(); 2282 if ( ! findGeneric( ty ) ) return offsetofExpr; 2283 2284 if ( StructInstType *structType = dynamic_cast< StructInstType* >( ty ) ) { 2285 // replace offsetof expression by index into offset array 2286 long i = findMember( offsetofExpr->get_member(), structType->get_baseStruct()->get_members() ); 2287 if ( i == -1 ) return offsetofExpr; 2288 2289 Expression *offsetInd = makeOffsetIndex( ty, i ); 2290 delete offsetofExpr; 2291 return offsetInd; 2292 } else if ( dynamic_cast< UnionInstType* >( ty ) ) { 2293 // all union members are at offset zero 2294 delete offsetofExpr; 2295 return new ConstantExpr( Constant( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), "0" ) ); 2296 } else return offsetofExpr; 2297 } 2298 2299 Expression *PolyGenericCalculator::mutate( OffsetPackExpr *offsetPackExpr ) { 2300 StructInstType *ty = offsetPackExpr->get_type(); 2301 2302 Expression *ret = 0; 2303 if ( findGeneric( ty ) ) { 2304 // pull offset back from generated type information 2305 ret = new NameExpr( offsetofName( mangleType( ty ) ) ); 2306 } else { 2307 std::string offsetName = offsetofName( mangleType( ty ) ); 2308 if ( knownOffsets.find( offsetName ) != knownOffsets.end() ) { 2309 // use the already-generated offsets for this type 2310 ret = new NameExpr( offsetName ); 2311 } else { 2312 knownOffsets.insert( offsetName ); 2313 2314 std::list< Declaration* > &baseMembers = ty->get_baseStruct()->get_members(); 2315 Type *offsetType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ); 2316 2317 // build initializer list for offset array 2318 std::list< Initializer* > inits; 2319 for ( std::list< Declaration* >::const_iterator member = baseMembers.begin(); member != baseMembers.end(); ++member ) { 2320 DeclarationWithType *memberDecl; 2321 if ( DeclarationWithType *origMember = dynamic_cast< DeclarationWithType* >( *member ) ) { 2322 memberDecl = origMember->clone(); 2323 } else { 2324 memberDecl = new ObjectDecl( (*member)->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, offsetType->clone(), 0 ); 2325 } 2326 inits.push_back( new SingleInit( new OffsetofExpr( ty->clone(), memberDecl ) ) ); 2327 } 2328 2329 // build the offset array and replace the pack with a reference to it 2330 ObjectDecl *offsetArray = makeVar( offsetName, new ArrayType( Type::Qualifiers(), offsetType, new ConstantExpr( Constant::from_ulong( baseMembers.size() ) ), false, false ), 2331 new ListInit( inits ) ); 2332 ret = new VariableExpr( offsetArray ); 2333 } 2334 } 2335 2336 delete offsetPackExpr; 2337 return ret; 2338 } 2339 2340 void PolyGenericCalculator::doBeginScope() { 2341 knownLayouts.beginScope(); 2342 knownOffsets.beginScope(); 2343 } 2344 2345 void PolyGenericCalculator::doEndScope() { 2346 knownLayouts.endScope(); 2347 knownOffsets.endScope(); 1022 2348 } 1023 2349 … … 1026 2352 template< typename DeclClass > 1027 2353 DeclClass * Pass3::handleDecl( DeclClass *decl, Type *type ) { 1028 TyVarMap oldtyVars = scopeTyVars;2354 scopeTyVars.beginScope(); 1029 2355 makeTyVarMap( type, scopeTyVars ); 1030 2356 1031 2357 DeclClass *ret = static_cast< DeclClass *>( Mutator::mutate( decl ) ); 1032 2358 ScrubTyVars::scrub( decl, scopeTyVars ); 1033 2359 1034 scopeTyVars = oldtyVars;2360 scopeTyVars.endScope(); 1035 2361 return ret; 1036 2362 } … … 1049 2375 1050 2376 TypeDecl * Pass3::mutate( TypeDecl *typeDecl ) { 1051 // /Initializer *init = 0;1052 // /std::list< Expression *> designators;1053 // /scopeTyVars[ typeDecl->get_name() ] = typeDecl->get_kind();1054 // /if ( typeDecl->get_base() ) {1055 // /init = new SimpleInit( new SizeofExpr( handleDecl( typeDecl, typeDecl->get_base() ) ), designators );1056 // /}1057 // /return new ObjectDecl( typeDecl->get_name(), Declaration::Extern, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::UnsignedInt ), init );2377 // Initializer *init = 0; 2378 // std::list< Expression *> designators; 2379 // scopeTyVars[ typeDecl->get_name() ] = typeDecl->get_kind(); 2380 // if ( typeDecl->get_base() ) { 2381 // init = new SimpleInit( new SizeofExpr( handleDecl( typeDecl, typeDecl->get_base() ) ), designators ); 2382 // } 2383 // return new ObjectDecl( typeDecl->get_name(), Declaration::Extern, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::UnsignedInt ), init ); 1058 2384 1059 2385 scopeTyVars[ typeDecl->get_name() ] = typeDecl->get_kind(); … … 1062 2388 1063 2389 Type * Pass3::mutate( PointerType *pointerType ) { 1064 TyVarMap oldtyVars = scopeTyVars;2390 scopeTyVars.beginScope(); 1065 2391 makeTyVarMap( pointerType, scopeTyVars ); 1066 2392 1067 2393 Type *ret = Mutator::mutate( pointerType ); 1068 1069 scopeTyVars = oldtyVars;2394 2395 scopeTyVars.endScope(); 1070 2396 return ret; 1071 2397 } 1072 2398 1073 2399 Type * Pass3::mutate( FunctionType *functionType ) { 1074 TyVarMap oldtyVars = scopeTyVars;2400 scopeTyVars.beginScope(); 1075 2401 makeTyVarMap( functionType, scopeTyVars ); 1076 2402 1077 2403 Type *ret = Mutator::mutate( functionType ); 1078 1079 scopeTyVars = oldtyVars;2404 2405 scopeTyVars.endScope(); 1080 2406 return ret; 1081 }1082 1083 Statement *Pass3::mutate( DeclStmt *declStmt ) {1084 if ( ObjectDecl *objectDecl = dynamic_cast< ObjectDecl *>( declStmt->get_decl() ) ) {1085 if ( isPolyVal( objectDecl->get_type(), scopeTyVars ) ) {1086 // change initialization of a polymorphic value object1087 // to allocate storage with alloca1088 TypeInstType *typeInst = dynamic_cast< TypeInstType *>( objectDecl->get_type() );1089 assert( typeInst );1090 UntypedExpr *alloc = new UntypedExpr( new NameExpr( "__builtin_alloca" ) );1091 alloc->get_args().push_back( new NameExpr( typeInst->get_name() ) );1092 1093 delete objectDecl->get_init();1094 1095 std::list<Expression*> designators;1096 objectDecl->set_init( new SingleInit( alloc, designators ) );1097 }1098 }1099 return Mutator::mutate( declStmt );1100 2407 } 1101 2408 } // anonymous namespace
Note:
See TracChangeset
for help on using the changeset viewer.