Changes in src/GenPoly/Box.cc [4e284ea6:4067aa8]
- File:
-
- 1 edited
-
src/GenPoly/Box.cc (modified) (13 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/GenPoly/Box.cc
r4e284ea6 r4067aa8 14 14 // 15 15 16 #include <algorithm>17 #include <iterator>18 #include <list>19 #include <map>20 16 #include <set> 21 17 #include <stack> 22 18 #include <string> 23 #include < utility>24 #include < vector>19 #include <iterator> 20 #include <algorithm> 25 21 #include <cassert> 26 22 27 23 #include "Box.h" 28 #include " DeclMutator.h"24 #include "InstantiateGeneric.h" 29 25 #include "PolyMutator.h" 30 26 #include "FindFunction.h" 31 #include "ScopedMap.h"32 27 #include "ScrubTyVars.h" 33 28 … … 35 30 36 31 #include "SynTree/Constant.h" 37 #include "SynTree/ Declaration.h"32 #include "SynTree/Type.h" 38 33 #include "SynTree/Expression.h" 39 34 #include "SynTree/Initializer.h" 35 #include "SynTree/Statement.h" 40 36 #include "SynTree/Mutator.h" 41 #include "SynTree/Statement.h"42 #include "SynTree/Type.h"43 #include "SynTree/TypeSubstitution.h"44 37 45 38 #include "ResolvExpr/TypeEnvironment.h" … … 47 40 #include "ResolvExpr/typeops.h" 48 41 49 #include "SymTab/Indexer.h"50 42 #include "SymTab/Mangler.h" 51 43 … … 62 54 FunctionType *makeAdapterType( FunctionType *adaptee, const TyVarMap &tyVars ); 63 55 64 /// Key for a unique concrete type; generic base type paired with type parameter list65 struct ConcreteType {66 ConcreteType() : base(NULL), params() {}67 68 ConcreteType(AggregateDecl *_base, const std::list< Type* >& _params) : base(_base), params() { cloneAll(_params, params); }69 70 ConcreteType(const ConcreteType& that) : base(that.base), params() { cloneAll(that.params, params); }71 72 /// Extracts types from a list of TypeExpr*73 ConcreteType(AggregateDecl *_base, const std::list< TypeExpr* >& _params) : base(_base), params() {74 for ( std::list< TypeExpr* >::const_iterator param = _params.begin(); param != _params.end(); ++param ) {75 params.push_back( (*param)->get_type()->clone() );76 }77 }78 79 ConcreteType& operator= (const ConcreteType& that) {80 deleteAll( params );81 params.clear();82 83 base = that.base;84 cloneAll( that.params, params );85 86 return *this;87 }88 89 ~ConcreteType() { deleteAll( params ); }90 91 bool operator== (const ConcreteType& that) const {92 if ( base != that.base ) return false;93 94 SymTab::Indexer dummy;95 if ( params.size() != that.params.size() ) return false;96 for ( std::list< Type* >::const_iterator it = params.begin(), jt = that.params.begin(); it != params.end(); ++it, ++jt ) {97 if ( ! ResolvExpr::typesCompatible( *it, *jt, dummy ) ) return false;98 }99 return true;100 }101 102 AggregateDecl *base; ///< Base generic type103 std::list< Type* > params; ///< Instantiation parameters104 };105 106 /// Maps a concrete type to the some value, accounting for scope107 template< typename Value >108 class InstantiationMap {109 /// Information about a specific instantiation of a generic type110 struct Instantiation {111 ConcreteType key; ///< Instantiation parameters for this type112 Value *value; ///< Value for this instantiation113 114 Instantiation() : key(), value(0) {}115 Instantiation(const ConcreteType &_key, Value *_value) : key(_key), value(_value) {}116 };117 /// Map of generic types to instantiations of them118 typedef std::map< AggregateDecl*, std::vector< Instantiation > > Scope;119 120 std::vector< Scope > scopes; ///< list of scopes, from outermost to innermost121 122 public:123 /// Starts a new scope124 void beginScope() {125 Scope scope;126 scopes.push_back(scope);127 }128 129 /// Ends a scope130 void endScope() {131 scopes.pop_back();132 }133 134 /// Default constructor initializes with one scope135 InstantiationMap() { beginScope(); }136 137 // private:138 /// Gets the value for the concrete instantiation of this type, assuming it has already been instantiated in the current scope.139 /// Returns NULL on none such.140 Value *lookup( AggregateDecl *generic, const std::list< TypeExpr* >& params ) {141 ConcreteType key(generic, params);142 // scan scopes from innermost out143 for ( typename std::vector< Scope >::const_reverse_iterator scope = scopes.rbegin(); scope != scopes.rend(); ++scope ) {144 // skip scope if no instantiations of this generic type145 typename Scope::const_iterator insts = scope->find( generic );146 if ( insts == scope->end() ) continue;147 // look through instantiations for matches to concrete type148 for ( typename std::vector< Instantiation >::const_iterator inst = insts->second.begin(); inst != insts->second.end(); ++inst ) {149 if ( inst->key == key ) return inst->value;150 }151 }152 // no matching instantiation found153 return 0;154 }155 public:156 // StructDecl* lookup( StructInstType *inst, const std::list< TypeExpr* > &typeSubs ) { return (StructDecl*)lookup( inst->get_baseStruct(), typeSubs ); }157 // UnionDecl* lookup( UnionInstType *inst, const std::list< TypeExpr* > &typeSubs ) { return (UnionDecl*)lookup( inst->get_baseUnion(), typeSubs ); }158 159 // private:160 /// Adds a value for a concrete type to the current scope161 void insert( AggregateDecl *generic, const std::list< TypeExpr* > ¶ms, Value *value ) {162 ConcreteType key(generic, params);163 scopes.back()[generic].push_back( Instantiation( key, value ) );164 }165 // public:166 // void insert( StructInstType *inst, const std::list< TypeExpr* > &typeSubs, StructDecl *decl ) { insert( inst->get_baseStruct(), typeSubs, decl ); }167 // void insert( UnionInstType *inst, const std::list< TypeExpr* > &typeSubs, UnionDecl *decl ) { insert( inst->get_baseUnion(), typeSubs, decl ); }168 };169 170 /// Adds layout-generation functions to polymorphic types171 class LayoutFunctionBuilder : public DeclMutator {172 unsigned int functionNesting; // current level of nested functions173 public:174 LayoutFunctionBuilder() : functionNesting( 0 ) {}175 176 virtual DeclarationWithType *mutate( FunctionDecl *functionDecl );177 virtual Declaration *mutate( StructDecl *structDecl );178 virtual Declaration *mutate( UnionDecl *unionDecl );179 };180 181 56 /// Replaces polymorphic return types with out-parameters, replaces calls to polymorphic functions with adapter calls as needed, and adds appropriate type variables to the function call 182 57 class Pass1 : public PolyMutator { … … 225 100 ObjectDecl *makeTemporary( Type *type ); 226 101 102 typedef std::map< std::string, DeclarationWithType *> AdapterMap; 227 103 std::map< std::string, DeclarationWithType *> assignOps; 228 104 ResolvExpr::TypeMap< DeclarationWithType > scopedAssignOps; 229 ScopedMap< std::string, DeclarationWithType*> adapters;105 std::stack< AdapterMap > adapters; 230 106 DeclarationWithType *retval; 231 107 bool useRetval; … … 248 124 249 125 std::map< UniqueId, std::string > adapterName; 250 };251 252 /// Mutator pass that replaces concrete instantiations of generic types with actual struct declarations, scoped appropriately253 class GenericInstantiator : public DeclMutator {254 /// Map of (generic type, parameter list) pairs to concrete type instantiations255 InstantiationMap< AggregateDecl > instantiations;256 /// Namer for concrete types257 UniqueName typeNamer;258 259 public:260 GenericInstantiator() : DeclMutator(), instantiations(), typeNamer("_conc_") {}261 262 virtual Type* mutate( StructInstType *inst );263 virtual Type* mutate( UnionInstType *inst );264 265 // virtual Expression* mutate( MemberExpr *memberExpr );266 267 virtual void doBeginScope();268 virtual void doEndScope();269 private:270 /// Wrap instantiation lookup for structs271 StructDecl* lookup( StructInstType *inst, const std::list< TypeExpr* > &typeSubs ) { return (StructDecl*)instantiations.lookup( inst->get_baseStruct(), typeSubs ); }272 /// Wrap instantiation lookup for unions273 UnionDecl* lookup( UnionInstType *inst, const std::list< TypeExpr* > &typeSubs ) { return (UnionDecl*)instantiations.lookup( inst->get_baseUnion(), typeSubs ); }274 /// Wrap instantiation insertion for structs275 void insert( StructInstType *inst, const std::list< TypeExpr* > &typeSubs, StructDecl *decl ) { instantiations.insert( inst->get_baseStruct(), typeSubs, decl ); }276 /// Wrap instantiation insertion for unions277 void insert( UnionInstType *inst, const std::list< TypeExpr* > &typeSubs, UnionDecl *decl ) { instantiations.insert( inst->get_baseUnion(), typeSubs, decl ); }278 126 }; 279 127 … … 311 159 } // anonymous namespace 312 160 161 void printAllNotBuiltin( const std::list< Declaration *>& translationUnit, std::ostream &os ) { 162 for ( std::list< Declaration *>::const_iterator i = translationUnit.begin(); i != translationUnit.end(); ++i ) { 163 if ( ! LinkageSpec::isBuiltin( (*i)->get_linkage() ) ) { 164 (*i)->print( os ); 165 os << std::endl; 166 } // if 167 } // for 168 } 169 313 170 /// version of mutateAll with special handling for translation unit so you can check the end of the prelude when debugging 314 171 template< typename MutatorType > … … 338 195 339 196 void box( std::list< Declaration *>& translationUnit ) { 340 LayoutFunctionBuilder layoutBuilder;341 197 Pass1 pass1; 342 198 Pass2 pass2; 343 GenericInstantiator instantiator;344 199 MemberExprFixer memberFixer; 345 200 Pass3 pass3; 346 347 layoutBuilder.mutateDeclarationList( translationUnit );348 201 mutateTranslationUnit/*All*/( translationUnit, pass1 ); 349 202 mutateTranslationUnit/*All*/( translationUnit, pass2 ); 350 // instantiateGeneric( translationUnit ); 351 instantiator.mutateDeclarationList( translationUnit ); 203 instantiateGeneric( translationUnit ); 352 204 mutateTranslationUnit/*All*/( translationUnit, memberFixer ); 353 205 mutateTranslationUnit/*All*/( translationUnit, pass3 ); 354 206 } 355 207 356 ////////////////////////////////// LayoutFunctionBuilder ////////////////////////////////////////////357 358 DeclarationWithType *LayoutFunctionBuilder::mutate( FunctionDecl *functionDecl ) {359 functionDecl->set_functionType( maybeMutate( functionDecl->get_functionType(), *this ) );360 mutateAll( functionDecl->get_oldDecls(), *this );361 ++functionNesting;362 functionDecl->set_statements( maybeMutate( functionDecl->get_statements(), *this ) );363 --functionNesting;364 return functionDecl;365 }366 367 /// Get a list of type declarations that will affect a layout function368 std::list< TypeDecl* > takeOtypeOnly( std::list< TypeDecl* > &decls ) {369 std::list< TypeDecl * > otypeDecls;370 371 for ( std::list< TypeDecl* >::const_iterator decl = decls.begin(); decl != decls.end(); ++decl ) {372 if ( (*decl)->get_kind() == TypeDecl::Any ) {373 otypeDecls.push_back( *decl );374 }375 }376 377 return otypeDecls;378 }379 380 /// Adds parameters for otype layout to a function type381 void addOtypeParams( FunctionType *layoutFnType, std::list< TypeDecl* > &otypeParams ) {382 BasicType sizeAlignType( Type::Qualifiers(), BasicType::LongUnsignedInt );383 384 for ( std::list< TypeDecl* >::const_iterator param = otypeParams.begin(); param != otypeParams.end(); ++param ) {385 TypeInstType paramType( Type::Qualifiers(), (*param)->get_name(), *param );386 layoutFnType->get_parameters().push_back( new ObjectDecl( sizeofName( ¶mType ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignType.clone(), 0 ) );387 layoutFnType->get_parameters().push_back( new ObjectDecl( alignofName( ¶mType ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignType.clone(), 0 ) );388 }389 }390 391 /// Builds a layout function declaration392 FunctionDecl *buildLayoutFunctionDecl( const std::string &typeName, unsigned int functionNesting, FunctionType *layoutFnType ) {393 // Routines at global scope marked "static" to prevent multiple definitions is separate translation units394 // because each unit generates copies of the default routines for each aggregate.395 FunctionDecl *layoutDecl = new FunctionDecl(396 "__layoutof_" + typeName, functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, layoutFnType, new CompoundStmt( noLabels ), true, false );397 layoutDecl->fixUniqueId();398 return layoutDecl;399 }400 401 /// Makes a unary operation402 Expression *makeOp( const std::string &name, Expression *arg ) {403 UntypedExpr *expr = new UntypedExpr( new NameExpr( name ) );404 expr->get_args().push_back( arg );405 return expr;406 }407 408 /// Makes a binary operation409 Expression *makeOp( const std::string &name, Expression *lhs, Expression *rhs ) {410 UntypedExpr *expr = new UntypedExpr( new NameExpr( name ) );411 expr->get_args().push_back( lhs );412 expr->get_args().push_back( rhs );413 return expr;414 }415 416 /// Returns the dereference of a local pointer variable417 Expression *derefVar( ObjectDecl *var ) {418 return makeOp( "*?", new VariableExpr( var ) );419 }420 421 /// makes an if-statement with a single-expression if-block and no then block422 Statement *makeCond( Expression *cond, Expression *ifPart ) {423 return new IfStmt( noLabels, cond, new ExprStmt( noLabels, ifPart ), 0 );424 }425 426 /// makes a statement that assigns rhs to lhs if lhs < rhs427 Statement *makeAssignMax( Expression *lhs, Expression *rhs ) {428 return makeCond( makeOp( "?<?", lhs, rhs ), makeOp( "?=?", lhs->clone(), rhs->clone() ) );429 }430 431 /// makes a statement that aligns lhs to rhs (rhs should be an integer power of two)432 Statement *makeAlignTo( Expression *lhs, Expression *rhs ) {433 // check that the lhs is zeroed out to the level of rhs434 Expression *ifCond = makeOp( "?&?", lhs, makeOp( "?-?", rhs, new ConstantExpr( Constant( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), "1" ) ) ) );435 // if not aligned, increment to alignment436 Expression *ifExpr = makeOp( "?+=?", lhs->clone(), makeOp( "?-?", rhs->clone(), ifCond->clone() ) );437 return makeCond( ifCond, ifExpr );438 }439 440 /// adds an expression to a compound statement441 void addExpr( CompoundStmt *stmts, Expression *expr ) {442 stmts->get_kids().push_back( new ExprStmt( noLabels, expr ) );443 }444 445 /// adds a statement to a compound statement446 void addStmt( CompoundStmt *stmts, Statement *stmt ) {447 stmts->get_kids().push_back( stmt );448 }449 450 Declaration *LayoutFunctionBuilder::mutate( StructDecl *structDecl ) {451 // do not generate layout function for "empty" tag structs452 if ( structDecl->get_members().empty() ) return structDecl;453 454 // get parameters that can change layout, exiting early if none455 std::list< TypeDecl* > otypeParams = takeOtypeOnly( structDecl->get_parameters() );456 if ( otypeParams.empty() ) return structDecl;457 458 // build layout function signature459 FunctionType *layoutFnType = new FunctionType( Type::Qualifiers(), false );460 BasicType *sizeAlignType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );461 PointerType *sizeAlignOutType = new PointerType( Type::Qualifiers(), sizeAlignType );462 463 ObjectDecl *sizeParam = new ObjectDecl( "__sizeof_" + structDecl->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType, 0 );464 layoutFnType->get_parameters().push_back( sizeParam );465 ObjectDecl *alignParam = new ObjectDecl( "__alignof_" + structDecl->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType->clone(), 0 );466 layoutFnType->get_parameters().push_back( alignParam );467 ObjectDecl *offsetParam = new ObjectDecl( "__offsetof_" + structDecl->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType->clone(), 0 );468 layoutFnType->get_parameters().push_back( offsetParam );469 addOtypeParams( layoutFnType, otypeParams );470 471 // build function decl472 FunctionDecl *layoutDecl = buildLayoutFunctionDecl( structDecl->get_name(), functionNesting, layoutFnType );473 474 // calculate struct layout in function body475 476 // initialize size and alignment to 0 and 1 (will have at least one member to re-edit size477 addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( sizeParam ), new ConstantExpr( Constant( sizeAlignType->clone(), "0" ) ) ) );478 addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( alignParam ), new ConstantExpr( Constant( sizeAlignType->clone(), "1" ) ) ) );479 unsigned long n_members = 0;480 bool firstMember = true;481 for ( std::list< Declaration* >::const_iterator member = structDecl->get_members().begin(); member != structDecl->get_members().end(); ++member ) {482 DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( *member );483 assert( dwt );484 Type *memberType = dwt->get_type();485 486 if ( firstMember ) {487 firstMember = false;488 } else {489 // make sure all members after the first (automatically aligned at 0) are properly padded for alignment490 addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), new AlignofExpr( memberType->clone() ) ) );491 }492 493 // place current size in the current offset index494 addExpr( layoutDecl->get_statements(), makeOp( "?=?", makeOp( "?[?]", new VariableExpr( offsetParam ), new ConstantExpr( Constant::from( n_members ) ) ),495 derefVar( sizeParam ) ) );496 ++n_members;497 498 // add member size to current size499 addExpr( layoutDecl->get_statements(), makeOp( "?+=?", derefVar( sizeParam ), new SizeofExpr( memberType->clone() ) ) );500 501 // take max of member alignment and global alignment502 addStmt( layoutDecl->get_statements(), makeAssignMax( derefVar( alignParam ), new AlignofExpr( memberType->clone() ) ) );503 }504 // make sure the type is end-padded to a multiple of its alignment505 addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), derefVar( alignParam ) ) );506 507 addDeclarationAfter( layoutDecl );508 return structDecl;509 }510 511 Declaration *LayoutFunctionBuilder::mutate( UnionDecl *unionDecl ) {512 // do not generate layout function for "empty" tag unions513 if ( unionDecl->get_members().empty() ) return unionDecl;514 515 // get parameters that can change layout, exiting early if none516 std::list< TypeDecl* > otypeParams = takeOtypeOnly( unionDecl->get_parameters() );517 if ( otypeParams.empty() ) return unionDecl;518 519 // build layout function signature520 FunctionType *layoutFnType = new FunctionType( Type::Qualifiers(), false );521 BasicType *sizeAlignType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );522 PointerType *sizeAlignOutType = new PointerType( Type::Qualifiers(), sizeAlignType );523 524 ObjectDecl *sizeParam = new ObjectDecl( "__sizeof_" + unionDecl->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType, 0 );525 layoutFnType->get_parameters().push_back( sizeParam );526 ObjectDecl *alignParam = new ObjectDecl( "__alignof_" + unionDecl->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType->clone(), 0 );527 layoutFnType->get_parameters().push_back( alignParam );528 addOtypeParams( layoutFnType, otypeParams );529 530 // build function decl531 FunctionDecl *layoutDecl = buildLayoutFunctionDecl( unionDecl->get_name(), functionNesting, layoutFnType );532 533 // calculate union layout in function body534 addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( sizeParam ), new ConstantExpr( Constant( sizeAlignType->clone(), "1" ) ) ) );535 addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( alignParam ), new ConstantExpr( Constant( sizeAlignType->clone(), "1" ) ) ) );536 for ( std::list< Declaration* >::const_iterator member = unionDecl->get_members().begin(); member != unionDecl->get_members().end(); ++member ) {537 DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( *member );538 assert( dwt );539 Type *memberType = dwt->get_type();540 541 // take max member size and global size542 addStmt( layoutDecl->get_statements(), makeAssignMax( derefVar( sizeParam ), new SizeofExpr( memberType->clone() ) ) );543 544 // take max of member alignment and global alignment545 addStmt( layoutDecl->get_statements(), makeAssignMax( derefVar( alignParam ), new AlignofExpr( memberType->clone() ) ) );546 }547 // make sure the type is end-padded to a multiple of its alignment548 addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), derefVar( alignParam ) ) );549 550 addDeclarationAfter( layoutDecl );551 return unionDecl;552 }553 554 208 ////////////////////////////////////////// Pass1 //////////////////////////////////////////////////// 555 209 … … 591 245 } 592 246 593 Pass1::Pass1() : useRetval( false ), tempNamer( "_temp" ) {} 247 Pass1::Pass1() : useRetval( false ), tempNamer( "_temp" ) { 248 adapters.push(AdapterMap()); 249 } 594 250 595 251 /// Returns T if the given declaration is (*?=?)(T *, T) for some TypeInstType T (return not checked, but maybe should be), NULL otherwise … … 694 350 } // for 695 351 352 AdapterMap & adapters = Pass1::adapters.top(); 696 353 for ( std::list< FunctionType *>::iterator funType = functions.begin(); funType != functions.end(); ++funType ) { 697 354 std::string mangleName = mangleAdapterName( *funType, scopeTyVars ); … … 1115 772 mangleName += makePolyMonoSuffix( originalFunction, exprTyVars ); 1116 773 1117 typedef ScopedMap< std::string, DeclarationWithType* >::iterator AdapterIter;1118 Adapter Iter adapter = adapters.find( mangleName );774 AdapterMap & adapters = Pass1::adapters.top(); 775 AdapterMap::iterator adapter = adapters.find( mangleName ); 1119 776 if ( adapter == adapters.end() ) { 1120 777 // adapter has not been created yet in the current scope, so define it 1121 778 FunctionDecl *newAdapter = makeAdapter( *funType, realFunction, mangleName, exprTyVars ); 1122 std::pair< AdapterIter, bool > answer = adapters.insert( std::pair< std::string, DeclarationWithType *>( mangleName, newAdapter ) ); 1123 adapter = answer.first; 779 adapter = adapters.insert( adapters.begin(), std::pair< std::string, DeclarationWithType *>( mangleName, newAdapter ) ); 1124 780 stmtsToAdd.push_back( new DeclStmt( noLabels, newAdapter ) ); 1125 781 } // if … … 1500 1156 1501 1157 void Pass1::doBeginScope() { 1502 adapters.beginScope(); 1158 // push a copy of the current map 1159 adapters.push(adapters.top()); 1503 1160 scopedAssignOps.beginScope(); 1504 1161 } 1505 1162 1506 1163 void Pass1::doEndScope() { 1507 adapters. endScope();1164 adapters.pop(); 1508 1165 scopedAssignOps.endScope(); 1509 1166 } … … 1652 1309 } 1653 1310 1654 //////////////////////////////////////// GenericInstantiator //////////////////////////////////////////////////1655 1656 /// Makes substitutions of params into baseParams; returns true if all parameters substituted for a concrete type1657 bool makeSubstitutions( const std::list< TypeDecl* >& baseParams, const std::list< Expression* >& params, std::list< TypeExpr* >& out ) {1658 bool allConcrete = true; // will finish the substitution list even if they're not all concrete1659 1660 // substitute concrete types for given parameters, and incomplete types for placeholders1661 std::list< TypeDecl* >::const_iterator baseParam = baseParams.begin();1662 std::list< Expression* >::const_iterator param = params.begin();1663 for ( ; baseParam != baseParams.end() && param != params.end(); ++baseParam, ++param ) {1664 // switch ( (*baseParam)->get_kind() ) {1665 // case TypeDecl::Any: { // any type is a valid substitution here; complete types can be used to instantiate generics1666 TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );1667 assert(paramType && "Aggregate parameters should be type expressions");1668 out.push_back( paramType->clone() );1669 // check that the substituted type isn't a type variable itself1670 if ( dynamic_cast< TypeInstType* >( paramType->get_type() ) ) {1671 allConcrete = false;1672 }1673 // break;1674 // }1675 // case TypeDecl::Dtype: // dtype can be consistently replaced with void [only pointers, which become void*]1676 // out.push_back( new TypeExpr( new VoidType( Type::Qualifiers() ) ) );1677 // break;1678 // case TypeDecl::Ftype: // pointer-to-ftype can be consistently replaced with void (*)(void) [similar to dtype]1679 // out.push_back( new TypeExpr( new FunctionType( Type::Qualifiers(), false ) ) );1680 // break;1681 // }1682 }1683 1684 // if any parameters left over, not done1685 if ( baseParam != baseParams.end() ) return false;1686 // // if not enough parameters given, substitute remaining incomplete types for placeholders1687 // for ( ; baseParam != baseParams.end(); ++baseParam ) {1688 // switch ( (*baseParam)->get_kind() ) {1689 // case TypeDecl::Any: // no more substitutions here, fail early1690 // return false;1691 // case TypeDecl::Dtype: // dtype can be consistently replaced with void [only pointers, which become void*]1692 // out.push_back( new TypeExpr( new VoidType( Type::Qualifiers() ) ) );1693 // break;1694 // case TypeDecl::Ftype: // pointer-to-ftype can be consistently replaced with void (*)(void) [similar to dtype]1695 // out.push_back( new TypeExpr( new FunctionType( Type::Qualifiers(), false ) ) );1696 // break;1697 // }1698 // }1699 1700 return allConcrete;1701 }1702 1703 /// Substitutes types of members of in according to baseParams => typeSubs, appending the result to out1704 void substituteMembers( const std::list< Declaration* >& in, const std::list< TypeDecl* >& baseParams, const std::list< TypeExpr* >& typeSubs,1705 std::list< Declaration* >& out ) {1706 // substitute types into new members1707 TypeSubstitution subs( baseParams.begin(), baseParams.end(), typeSubs.begin() );1708 for ( std::list< Declaration* >::const_iterator member = in.begin(); member != in.end(); ++member ) {1709 Declaration *newMember = (*member)->clone();1710 subs.apply(newMember);1711 out.push_back( newMember );1712 }1713 }1714 1715 Type* GenericInstantiator::mutate( StructInstType *inst ) {1716 // mutate subtypes1717 Type *mutated = Mutator::mutate( inst );1718 inst = dynamic_cast< StructInstType* >( mutated );1719 if ( ! inst ) return mutated;1720 1721 // exit early if no need for further mutation1722 if ( inst->get_parameters().empty() ) return inst;1723 assert( inst->get_baseParameters() && "Base struct has parameters" );1724 1725 // check if type can be concretely instantiated; put substitutions into typeSubs1726 std::list< TypeExpr* > typeSubs;1727 if ( ! makeSubstitutions( *inst->get_baseParameters(), inst->get_parameters(), typeSubs ) ) {1728 deleteAll( typeSubs );1729 return inst;1730 }1731 1732 // make concrete instantiation of generic type1733 StructDecl *concDecl = lookup( inst, typeSubs );1734 if ( ! concDecl ) {1735 // set concDecl to new type, insert type declaration into statements to add1736 concDecl = new StructDecl( typeNamer.newName( inst->get_name() ) );1737 substituteMembers( inst->get_baseStruct()->get_members(), *inst->get_baseParameters(), typeSubs, concDecl->get_members() );1738 DeclMutator::addDeclaration( concDecl );1739 insert( inst, typeSubs, concDecl );1740 }1741 StructInstType *newInst = new StructInstType( inst->get_qualifiers(), concDecl->get_name() );1742 newInst->set_baseStruct( concDecl );1743 1744 deleteAll( typeSubs );1745 delete inst;1746 return newInst;1747 }1748 1749 Type* GenericInstantiator::mutate( UnionInstType *inst ) {1750 // mutate subtypes1751 Type *mutated = Mutator::mutate( inst );1752 inst = dynamic_cast< UnionInstType* >( mutated );1753 if ( ! inst ) return mutated;1754 1755 // exit early if no need for further mutation1756 if ( inst->get_parameters().empty() ) return inst;1757 assert( inst->get_baseParameters() && "Base union has parameters" );1758 1759 // check if type can be concretely instantiated; put substitutions into typeSubs1760 std::list< TypeExpr* > typeSubs;1761 if ( ! makeSubstitutions( *inst->get_baseParameters(), inst->get_parameters(), typeSubs ) ) {1762 deleteAll( typeSubs );1763 return inst;1764 }1765 1766 // make concrete instantiation of generic type1767 UnionDecl *concDecl = lookup( inst, typeSubs );1768 if ( ! concDecl ) {1769 // set concDecl to new type, insert type declaration into statements to add1770 concDecl = new UnionDecl( typeNamer.newName( inst->get_name() ) );1771 substituteMembers( inst->get_baseUnion()->get_members(), *inst->get_baseParameters(), typeSubs, concDecl->get_members() );1772 DeclMutator::addDeclaration( concDecl );1773 insert( inst, typeSubs, concDecl );1774 }1775 UnionInstType *newInst = new UnionInstType( inst->get_qualifiers(), concDecl->get_name() );1776 newInst->set_baseUnion( concDecl );1777 1778 deleteAll( typeSubs );1779 delete inst;1780 return newInst;1781 }1782 1783 // /// Gets the base struct or union declaration for a member expression; NULL if not applicable1784 // AggregateDecl* getMemberBaseDecl( MemberExpr *memberExpr ) {1785 // // get variable for member aggregate1786 // VariableExpr *varExpr = dynamic_cast< VariableExpr* >( memberExpr->get_aggregate() );1787 // if ( ! varExpr ) return NULL;1788 //1789 // // get object for variable1790 // ObjectDecl *objectDecl = dynamic_cast< ObjectDecl* >( varExpr->get_var() );1791 // if ( ! objectDecl ) return NULL;1792 //1793 // // get base declaration from object type1794 // Type *objectType = objectDecl->get_type();1795 // StructInstType *structType = dynamic_cast< StructInstType* >( objectType );1796 // if ( structType ) return structType->get_baseStruct();1797 // UnionInstType *unionType = dynamic_cast< UnionInstType* >( objectType );1798 // if ( unionType ) return unionType->get_baseUnion();1799 //1800 // return NULL;1801 // }1802 //1803 // /// Finds the declaration with the given name, returning decls.end() if none such1804 // std::list< Declaration* >::const_iterator findDeclNamed( const std::list< Declaration* > &decls, const std::string &name ) {1805 // for( std::list< Declaration* >::const_iterator decl = decls.begin(); decl != decls.end(); ++decl ) {1806 // if ( (*decl)->get_name() == name ) return decl;1807 // }1808 // return decls.end();1809 // }1810 //1811 // Expression* Instantiate::mutate( MemberExpr *memberExpr ) {1812 // // mutate, exiting early if no longer MemberExpr1813 // Expression *expr = Mutator::mutate( memberExpr );1814 // memberExpr = dynamic_cast< MemberExpr* >( expr );1815 // if ( ! memberExpr ) return expr;1816 //1817 // // get declaration of member and base declaration of member, exiting early if not found1818 // AggregateDecl *memberBase = getMemberBaseDecl( memberExpr );1819 // if ( ! memberBase ) return memberExpr;1820 // DeclarationWithType *memberDecl = memberExpr->get_member();1821 // std::list< Declaration* >::const_iterator baseIt = findDeclNamed( memberBase->get_members(), memberDecl->get_name() );1822 // if ( baseIt == memberBase->get_members().end() ) return memberExpr;1823 // DeclarationWithType *baseDecl = dynamic_cast< DeclarationWithType* >( *baseIt );1824 // if ( ! baseDecl ) return memberExpr;1825 //1826 // // check if stated type of the member is not the type of the member's declaration; if so, need a cast1827 // // this *SHOULD* be safe, I don't think anything but the void-replacements I put in for dtypes would make it past the typechecker1828 // SymTab::Indexer dummy;1829 // if ( ResolvExpr::typesCompatible( memberDecl->get_type(), baseDecl->get_type(), dummy ) ) return memberExpr;1830 // else return new CastExpr( memberExpr, memberDecl->get_type() );1831 // }1832 1833 void GenericInstantiator::doBeginScope() {1834 DeclMutator::doBeginScope();1835 instantiations.beginScope();1836 }1837 1838 void GenericInstantiator::doEndScope() {1839 DeclMutator::doEndScope();1840 instantiations.endScope();1841 }1842 1843 1311 ////////////////////////////////////////// MemberExprFixer //////////////////////////////////////////////////// 1844 1312
Note:
See TracChangeset
for help on using the changeset viewer.