Changeset a117f7c
- Timestamp:
- Oct 19, 2017, 11:13:12 AM (7 years ago)
- Branches:
- ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
- Children:
- b4748db
- Parents:
- be151bf
- git-author:
- Rob Schluntz <rschlunt@…> (10/12/17 16:31:19)
- git-committer:
- Rob Schluntz <rschlunt@…> (10/19/17 11:13:12)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/SymTab/Autogen.cc
rbe151bf ra117f7c 43 43 namespace SymTab { 44 44 Type * SizeType = 0; 45 typedef ScopedMap< std::string, bool > TypeMap; 46 47 /// Data used to generate functions generically. Specifically, the name of the generated function, a function which generates the routine protoype, and a map which contains data to determine whether a function should be generated. 45 46 /// Data used to generate functions generically. Specifically, the name of the generated function and a function which generates the routine protoype 48 47 struct FuncData { 49 48 typedef FunctionType * (*TypeGen)( Type * ); 50 FuncData( const std::string & fname, const TypeGen & genType , TypeMap & map ) : fname( fname ), genType( genType ), map( map) {}49 FuncData( const std::string & fname, const TypeGen & genType ) : fname( fname ), genType( genType ) {} 51 50 std::string fname; 52 51 TypeGen genType; 53 TypeMap & map;54 52 }; 55 53 … … 70 68 71 69 private: 70 72 71 GenPoly::ScopedSet< std::string > structsDone; 73 72 unsigned int functionNesting = 0; // current level of nested functions 74 /// Note: the following maps could be ScopedSets, but it should be easier to work 75 /// deleted functions in if they are maps, since the value false can be inserted 76 /// at the current scope without affecting outer scopes or requiring copies. 77 TypeMap copyable, assignable, constructable, destructable; 73 74 InitTweak::ManagedTypes managedTypes; 78 75 std::vector< FuncData > data; 79 76 }; … … 81 78 /// generates routines for tuple types. 82 79 struct AutogenTupleRoutines : public WithDeclsToAdd, public WithVisitorRef<AutogenTupleRoutines>, public WithGuards, public WithShortCircuiting { 83 void previsit( FunctionDecl * functionDecl );84 85 void postvisit( TupleType * tupleType );86 87 void previsit( CompoundStmt * compoundStmt );80 void previsit( FunctionDecl * functionDecl ); 81 82 void postvisit( TupleType * tupleType ); 83 84 void previsit( CompoundStmt * compoundStmt ); 88 85 89 86 private: … … 99 96 // AutogenTupleRoutines tupleGenerator; 100 97 // acceptAll( translationUnit, tupleGenerator ); 98 } 99 100 //============================================================================================= 101 // FuncGenerator definitions 102 //============================================================================================= 103 class FuncGenerator { 104 public: 105 std::list< Declaration * > definitions, forwards; 106 107 FuncGenerator( Type * type, unsigned int functionNesting, const std::vector< FuncData > & data, SymTab::Indexer & indexer ) : type( type ), functionNesting( functionNesting ), data( data ), indexer( indexer ) {} 108 109 virtual bool shouldAutogen() const = 0; 110 void genStandardFuncs(); 111 virtual void genFieldCtors() = 0; 112 protected: 113 Type * type; 114 unsigned int functionNesting; 115 const std::vector< FuncData > & data; 116 SymTab::Indexer & indexer; 117 118 virtual void genFuncBody( FunctionDecl * dcl ) = 0; 119 virtual bool isConcurrentType() const = 0; 120 121 void resolve( FunctionDecl * dcl ); 122 void generatePrototypes( std::list< FunctionDecl * > & newFuncs ); 123 }; 124 125 class StructFuncGenerator : public FuncGenerator { 126 StructDecl * aggregateDecl; 127 public: 128 StructFuncGenerator( StructDecl * aggregateDecl, StructInstType * refType, const std::vector< FuncData > & data, unsigned int functionNesting, SymTab::Indexer & indexer ) : FuncGenerator( refType, functionNesting, data, indexer ), aggregateDecl( aggregateDecl) {} 129 130 virtual bool shouldAutogen() const override; 131 virtual bool isConcurrentType() const override; 132 133 virtual void genFuncBody( FunctionDecl * dcl ) override; 134 virtual void genFieldCtors() override; 135 136 private: 137 /// generates a single struct member operation (constructor call, destructor call, assignment call) 138 void makeMemberOp( ObjectDecl * dstParam, Expression * src, DeclarationWithType * field, FunctionDecl * func, bool forward = true ); 139 140 /// generates the body of a struct function by iterating the struct members (via parameters) - generates default ctor, copy ctor, assignment, and dtor bodies, but NOT field ctor bodies 141 template<typename Iterator> 142 void makeFunctionBody( Iterator member, Iterator end, FunctionDecl * func, bool forward = true ); 143 144 /// generate the body of a constructor which takes parameters that match fields, e.g. 145 /// void ?{}(A *, int) and void?{}(A *, int, int) for a struct A which has two int fields. 146 template<typename Iterator> 147 void makeFieldCtorBody( Iterator member, Iterator end, FunctionDecl * func ); 148 }; 149 150 class TypeFuncGenerator : public FuncGenerator { 151 TypeDecl * typeDecl; 152 public: 153 TypeFuncGenerator( TypeDecl * typeDecl, TypeInstType * refType, unsigned int functionNesting, const std::vector<FuncData> & data, SymTab::Indexer & indexer ) : FuncGenerator( refType, functionNesting, data, indexer ), typeDecl( typeDecl ) {} 154 155 virtual bool shouldAutogen() const override; 156 virtual void genFuncBody( FunctionDecl * dcl ) override; 157 virtual bool isConcurrentType() const override; 158 virtual void genFieldCtors() override; 159 }; 160 161 //============================================================================================= 162 // helper functions 163 //============================================================================================= 164 void generateFunctions( FuncGenerator & gen, std::list< Declaration * > & declsToAdd ) { 165 if ( ! gen.shouldAutogen() ) return; 166 167 // generate each of the functions based on the supplied FuncData objects 168 gen.genStandardFuncs(); 169 gen.genFieldCtors(); 170 171 declsToAdd.splice( declsToAdd.end(), gen.forwards ); 172 declsToAdd.splice( declsToAdd.end(), gen.definitions ); 101 173 } 102 174 … … 149 221 decl->fixUniqueId(); 150 222 return decl; 151 }152 153 /// inserts base type of first argument into map if pred(funcDecl) is true154 void insert( FunctionDecl *funcDecl, TypeMap & map, FunctionDecl * (*pred)(Declaration *) ) {155 // insert type into constructable, etc. map if appropriate156 if ( pred( funcDecl ) ) {157 FunctionType * ftype = funcDecl->get_functionType();158 assert( ! ftype->get_parameters().empty() );159 Type * t = InitTweak::getPointerBase( ftype->get_parameters().front()->get_type() );160 assert( t );161 map.insert( Mangler::mangleType( t ), true );162 }163 }164 165 /// using map and t, determines if is constructable, etc.166 bool lookup( const TypeMap & map, Type * t ) {167 assertf( t, "Autogenerate lookup was given non-type: %s", toString( t ).c_str() );168 if ( dynamic_cast< PointerType * >( t ) ) {169 // will need more complicated checking if we want this to work with pointer types, since currently170 return true;171 } else if ( ArrayType * at = dynamic_cast< ArrayType * >( t ) ) {172 // an array's constructor, etc. is generated on the fly based on the base type's constructor, etc.173 return lookup( map, at->get_base() );174 }175 TypeMap::const_iterator it = map.find( Mangler::mangleType( t ) );176 if ( it != map.end() ) return it->second;177 // something that does not appear in the map is by default not constructable, etc.178 return false;179 }180 181 /// using map and aggr, examines each member to determine if constructor, etc. should be generated182 template<typename Container>183 bool shouldGenerate( const TypeMap & map, const Container & container ) {184 for ( Type * t : container ) {185 if ( ! lookup( map, t ) ) return false;186 }187 return true;188 }189 190 /// data structure for abstracting the generation of special functions191 template< typename OutputIterator, typename Container >192 struct FuncGenerator {193 const Container & container;194 Type *refType;195 unsigned int functionNesting;196 OutputIterator out;197 FuncGenerator( const Container & container, Type *refType, unsigned int functionNesting, OutputIterator out ) : container( container ), refType( refType ), functionNesting( functionNesting ), out( out ) {}198 199 const std::list< TypeDecl * > getGenericParams( Type * t ) {200 std::list< TypeDecl * > * ret = nullptr;201 if ( StructInstType * inst = dynamic_cast< StructInstType * > ( t ) ) {202 ret = inst->get_baseParameters();203 } else if ( UnionInstType * inst = dynamic_cast< UnionInstType * >( t ) ) {204 ret = inst->get_baseParameters();205 }206 return ret ? *ret : std::list< TypeDecl * >();207 }208 209 /// generates a function (?{}, ?=?, ^?{}) based on the data argument and members. If function is generated, inserts the type into the map.210 void gen( const FuncData & data, bool concurrent_type ) {211 // Make function polymorphic in same parameters as generic struct, if applicable212 std::list< TypeDecl * > typeParams = getGenericParams( refType ); // List of type variables to be placed on the generated functions213 214 FunctionType * ftype = data.genType( refType );215 216 if ( concurrent_type && CodeGen::isDestructor( data.fname ) ) {217 ftype->parameters.front()->get_type()->set_mutex( true );218 }219 220 cloneAll( typeParams, ftype->forall );221 *out++ = genFunc( data.fname, ftype, functionNesting );222 data.map.insert( Mangler::mangleType( refType ), true );223 }224 };225 226 template< typename OutputIterator, typename Container >227 FuncGenerator<OutputIterator, Container> makeFuncGenerator( const Container & container, Type *refType, unsigned int functionNesting, OutputIterator out ) {228 return FuncGenerator<OutputIterator, Container>( container, refType, functionNesting, out );229 223 } 230 224 … … 296 290 } 297 291 298 /// generates a single struct member operation (constructor call, destructor call, assignment call) 299 void makeStructMemberOp( ObjectDecl * dstParam, Expression * src, DeclarationWithType * field, FunctionDecl * func, bool forward = true ) { 292 Type * declToType( Declaration * decl ) { 293 if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType * >( decl ) ) { 294 return dwt->get_type(); 295 } 296 return nullptr; 297 } 298 299 Type * declToTypeDeclBase( Declaration * decl ) { 300 if ( TypeDecl * td = dynamic_cast< TypeDecl * >( decl ) ) { 301 return td->base; 302 } 303 return nullptr; 304 } 305 306 const std::list< TypeDecl * > getGenericParams( Type * t ) { 307 std::list< TypeDecl * > * ret = nullptr; 308 if ( StructInstType * inst = dynamic_cast< StructInstType * > ( t ) ) { 309 ret = inst->get_baseParameters(); 310 } else if ( UnionInstType * inst = dynamic_cast< UnionInstType * >( t ) ) { 311 ret = inst->get_baseParameters(); 312 } 313 return ret ? *ret : std::list< TypeDecl * >(); 314 } 315 316 //============================================================================================= 317 // FuncGenerator member definitions 318 //============================================================================================= 319 void FuncGenerator::genStandardFuncs() { 320 std::list< FunctionDecl * > newFuncs; 321 generatePrototypes( newFuncs ); 322 323 for ( FunctionDecl * dcl : newFuncs ) { 324 genFuncBody( dcl ); 325 resolve( dcl ); 326 } 327 } 328 329 void FuncGenerator::generatePrototypes( std::list< FunctionDecl * > & newFuncs ) { 330 bool concurrent_type = isConcurrentType(); 331 for ( const FuncData & data : data ) { 332 // generate a function (?{}, ?=?, ^?{}) based on the current FuncData. 333 FunctionType * ftype = data.genType( type ); 334 335 // destructor for concurrent type must be mutex 336 if ( concurrent_type && CodeGen::isDestructor( data.fname ) ) { 337 ftype->parameters.front()->get_type()->set_mutex( true ); 338 } 339 340 // Make function polymorphic in same parameters as generic struct, if applicable 341 std::list< TypeDecl * > typeParams = getGenericParams( type ); // List of type variables to be placed on the generated functions 342 cloneAll( typeParams, ftype->forall ); 343 344 newFuncs.push_back( genFunc( data.fname, ftype, functionNesting ) ); 345 } 346 } 347 348 void FuncGenerator::resolve( FunctionDecl * dcl ) { 349 try { 350 ResolvExpr::resolveDecl( dcl, indexer ); 351 if ( functionNesting == 0 ) { 352 // forward declare if top-level struct, so that 353 // type is complete as soon as its body ends 354 // Note: this is necessary if we want structs which contain 355 // generic (otype) structs as members. 356 addForwardDecl( dcl, forwards ); 357 } 358 definitions.push_back( dcl ); 359 indexer.addId( dcl ); 360 } catch ( SemanticError err ) { 361 // okay if decl does not resolve - that means the function should not be generated 362 delete dcl; 363 } 364 } 365 366 bool StructFuncGenerator::shouldAutogen() const { 367 // Builtins do not use autogeneration. 368 return ! aggregateDecl->linkage.is_builtin; 369 } 370 bool StructFuncGenerator::isConcurrentType() const { return aggregateDecl->is_thread() || aggregateDecl->is_monitor(); } 371 372 void StructFuncGenerator::genFuncBody( FunctionDecl * dcl ) { 373 // generate appropriate calls to member ctor, assignment 374 // destructor needs to do everything in reverse, so pass "forward" based on whether the function is a destructor 375 if ( ! CodeGen::isDestructor( dcl->get_name() ) ) { 376 makeFunctionBody( aggregateDecl->members.begin(), aggregateDecl->members.end(), dcl ); 377 } else { 378 makeFunctionBody( aggregateDecl->members.rbegin(), aggregateDecl->members.rend(), dcl, false ); 379 } 380 if ( CodeGen::isAssignment( dcl->name ) ) { 381 // assignment needs to return a value 382 FunctionType * assignType = dcl->type; 383 assert( assignType->parameters.size() == 2 ); 384 assert( assignType->returnVals.size() == 1 ); 385 ObjectDecl * srcParam = strict_dynamic_cast< ObjectDecl * >( assignType->parameters.back() ); 386 ObjectDecl * retParam = strict_dynamic_cast< ObjectDecl * >( assignType->returnVals.front() ); 387 388 dcl->statements->push_back( new ExprStmt( noLabels, new UntypedExpr( new NameExpr("?{}"), { new VariableExpr( retParam ), new VariableExpr( srcParam ) } ) ) ); 389 dcl->statements->push_back( new ReturnStmt( noLabels, new VariableExpr( retParam ) ) ); 390 } 391 } 392 393 void StructFuncGenerator::genFieldCtors() { 394 // field ctors are only generated if default constructor and copy constructor are both generated 395 unsigned numCtors = std::count_if( definitions.begin(), definitions.end(), [](Declaration * dcl) { return CodeGen::isConstructor( dcl->get_name() ); } ); 396 397 // create constructors which take each member type as a parameter. 398 // for example, for struct A { int x, y; }; generate 399 // void ?{}(A *, int) and void ?{}(A *, int, int) 400 // Field constructors are only generated if default and copy constructor 401 // are generated, since they need access to both 402 if ( numCtors == 2 ) { 403 const auto & typeParams = aggregateDecl->parameters; 404 FunctionType * memCtorType = genDefaultType( type ); 405 cloneAll( typeParams, memCtorType->forall ); 406 for ( Declaration * member : aggregateDecl->members ) { 407 DeclarationWithType * field = strict_dynamic_cast<DeclarationWithType *>( member ); 408 if ( isUnnamedBitfield( dynamic_cast< ObjectDecl * > ( field ) ) ) { 409 // don't make a function whose parameter is an unnamed bitfield 410 continue; 411 } 412 memCtorType->parameters.push_back( new ObjectDecl( field->name, Type::StorageClasses(), LinkageSpec::Cforall, 0, field->get_type()->clone(), 0 ) ); 413 FunctionDecl * ctor = genFunc( "?{}", memCtorType->clone(), functionNesting ); 414 makeFieldCtorBody( aggregateDecl->members.begin(), aggregateDecl->members.end(), ctor ); 415 resolve( ctor ); 416 } 417 delete memCtorType; 418 } 419 } 420 421 void StructFuncGenerator::makeMemberOp( ObjectDecl * dstParam, Expression * src, DeclarationWithType * field, FunctionDecl * func, bool forward ) { 300 422 InitTweak::InitExpander srcParam( src ); 301 423 … … 305 427 } 306 428 307 /// generates the body of a struct function by iterating the struct members (via parameters) - generates default ctor, copy ctor, assignment, and dtor bodies, but NOT field ctor bodies308 429 template<typename Iterator> 309 void makeStructFunctionBody( Iterator member, Iterator end, FunctionDecl * func, bool forward = true) {430 void StructFuncGenerator::makeFunctionBody( Iterator member, Iterator end, FunctionDecl * func, bool forward ) { 310 431 for ( ; member != end; ++member ) { 311 432 if ( DeclarationWithType *field = dynamic_cast< DeclarationWithType * >( *member ) ) { // otherwise some form of type declaration, e.g. Aggregate … … 332 453 333 454 Expression *srcselect = srcParam ? new MemberExpr( field, new VariableExpr( srcParam ) ) : nullptr; 334 make StructMemberOp( dstParam, srcselect, field, func, forward );455 makeMemberOp( dstParam, srcselect, field, func, forward ); 335 456 } // if 336 457 } // for 337 } // makeStructFunctionBody 338 339 /// generate the body of a constructor which takes parameters that match fields, e.g. 340 /// void ?{}(A *, int) and void?{}(A *, int, int) for a struct A which has two int fields. 458 } // makeFunctionBody 459 341 460 template<typename Iterator> 342 void makeStructFieldCtorBody( Iterator member, Iterator end, FunctionDecl * func ) {343 FunctionType * ftype = func-> get_functionType();344 std::list<DeclarationWithType*> & params = ftype-> get_parameters();461 void StructFuncGenerator::makeFieldCtorBody( Iterator member, Iterator end, FunctionDecl * func ) { 462 FunctionType * ftype = func->type; 463 std::list<DeclarationWithType*> & params = ftype->parameters; 345 464 assert( params.size() >= 2 ); // should not call this function for default ctor, etc. 346 465 … … 357 476 // matching parameter, initialize field with copy ctor 358 477 Expression *srcselect = new VariableExpr(*parameter); 359 make StructMemberOp( dstParam, srcselect, field, func );478 makeMemberOp( dstParam, srcselect, field, func ); 360 479 ++parameter; 361 480 } else { 362 481 // no matching parameter, initialize field with default ctor 363 make StructMemberOp( dstParam, nullptr, field, func );482 makeMemberOp( dstParam, nullptr, field, func ); 364 483 } 365 484 } 366 485 } 367 }368 369 Type * declToType( Declaration * decl ) {370 if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType * >( decl ) ) {371 return dwt->get_type();372 }373 return nullptr;374 }375 376 /// generates struct constructors, destructor, and assignment functions377 void makeStructFunctions( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting, std::list< Declaration * > & declsToAdd, const std::vector< FuncData > & data, SymTab::Indexer & indexer ) {378 // Builtins do not use autogeneration.379 if ( LinkageSpec::isBuiltin( aggregateDecl->get_linkage() ) ) {380 return;381 }382 383 // generate each of the functions based on the supplied FuncData objects384 std::list< FunctionDecl * > newFuncs;385 // structure that iterates aggregate decl members, returning their types386 auto generator = makeFuncGenerator( lazy_map( aggregateDecl->members, declToType ), refType, functionNesting, back_inserter( newFuncs ) );387 for ( const FuncData & d : data ) {388 generator.gen( d, aggregateDecl->is_thread() || aggregateDecl->is_monitor() );389 }390 391 std::list< Declaration * > definitions, forwards;392 for ( FunctionDecl * dcl : newFuncs ) {393 // generate appropriate calls to member ctor, assignment394 // destructor needs to do everything in reverse, so pass "forward" based on whether the function is a destructor395 if ( ! CodeGen::isDestructor( dcl->get_name() ) ) {396 makeStructFunctionBody( aggregateDecl->members.begin(), aggregateDecl->members.end(), dcl );397 } else {398 makeStructFunctionBody( aggregateDecl->members.rbegin(), aggregateDecl->members.rend(), dcl, false );399 }400 if ( CodeGen::isAssignment( dcl->name ) ) {401 // assignment needs to return a value402 FunctionType * assignType = dcl->get_functionType();403 assert( assignType->parameters.size() == 2 );404 assert( assignType->returnVals.size() == 1 );405 ObjectDecl * srcParam = strict_dynamic_cast< ObjectDecl * >( assignType->parameters.back() );406 ObjectDecl * retParam = strict_dynamic_cast< ObjectDecl * >( assignType->returnVals.front() );407 408 dcl->statements->push_back( new ExprStmt( noLabels, new UntypedExpr( new NameExpr("?{}"), { new VariableExpr( retParam ), new VariableExpr( srcParam ) } ) ) );409 dcl->statements->push_back( new ReturnStmt( noLabels, new VariableExpr( retParam ) ) );410 }411 412 try {413 ResolvExpr::resolveDecl( dcl, indexer );414 } catch ( SemanticError err ) {415 // okay if decl does not resolve - that means the function should not be generated416 delete dcl;417 continue;418 }419 420 if ( functionNesting == 0 ) {421 // forward declare if top-level struct, so that422 // type is complete as soon as its body ends423 // Note: this is necessary if we want structs which contain424 // generic (otype) structs as members.425 addForwardDecl( dcl, forwards );426 }427 definitions.push_back( dcl );428 indexer.addId( dcl );429 }430 431 // field ctors are only generated if default constructor and copy constructor are both generated432 unsigned numCtors = std::count_if( definitions.begin(), definitions.end(), [](Declaration * dcl) { return CodeGen::isConstructor( dcl->get_name() ); } );433 434 // create constructors which take each member type as a parameter.435 // for example, for struct A { int x, y; }; generate436 // void ?{}(A *, int) and void ?{}(A *, int, int)437 // Field constructors are only generated if default and copy constructor438 // are generated, since they need access to both439 if ( numCtors == 2 ) {440 const auto & typeParams = aggregateDecl->parameters;441 FunctionType * memCtorType = genDefaultType( refType );442 cloneAll( typeParams, memCtorType->forall );443 for ( Declaration * member : aggregateDecl->members ) {444 DeclarationWithType * field = dynamic_cast<DeclarationWithType *>( member );445 assert( field );446 if ( isUnnamedBitfield( dynamic_cast< ObjectDecl * > ( field ) ) ) {447 // don't make a function whose parameter is an unnamed bitfield448 continue;449 }450 memCtorType->get_parameters().push_back( new ObjectDecl( field->get_name(), Type::StorageClasses(), LinkageSpec::Cforall, 0, field->get_type()->clone(), 0 ) );451 FunctionDecl * ctor = genFunc( "?{}", memCtorType->clone(), functionNesting );452 makeStructFieldCtorBody( aggregateDecl->members.begin(), aggregateDecl->members.end(), ctor );453 454 try {455 ResolvExpr::resolveDecl( ctor, indexer );456 } catch ( SemanticError err ) {457 // okay if decl does not resolve - that means the function should not be generated458 delete ctor;459 continue;460 }461 definitions.push_back( ctor );462 }463 delete memCtorType;464 }465 466 declsToAdd.splice( declsToAdd.end(), forwards );467 declsToAdd.splice( declsToAdd.end(), definitions );468 486 } 469 487 … … 564 582 } 565 583 584 bool TypeFuncGenerator::shouldAutogen() const { return true; }; 585 586 void TypeFuncGenerator::genFuncBody( FunctionDecl * dcl ) { 587 FunctionType * ftype = dcl->type; 588 assertf( ftype->parameters.size() == 1 || ftype->parameters.size() == 2, "Incorrect number of parameters in autogenerated typedecl function: %zd", ftype->parameters.size() ); 589 DeclarationWithType * dst = ftype->parameters.front(); 590 DeclarationWithType * src = ftype->parameters.size() == 2 ? ftype->parameters.back() : nullptr; 591 // generate appropriate calls to member ctor, assignment 592 UntypedExpr * expr = new UntypedExpr( new NameExpr( dcl->name ) ); 593 expr->args.push_back( new CastExpr( new VariableExpr( dst ), new ReferenceType( Type::Qualifiers(), typeDecl->base->clone() ) ) ); 594 if ( src ) expr->args.push_back( new CastExpr( new VariableExpr( src ), typeDecl->base->clone() ) ); 595 dcl->statements->kids.push_back( new ExprStmt( noLabels, expr ) ); 596 if ( CodeGen::isAssignment( dcl->get_name() ) ) { 597 // assignment needs to return a value 598 FunctionType * assignType = dcl->type; 599 assert( assignType->parameters.size() == 2 ); 600 ObjectDecl * srcParam = strict_dynamic_cast< ObjectDecl * >( assignType->parameters.back() ); 601 dcl->statements->kids.push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) ); 602 } 603 }; 604 605 // xxx - should reach in and determine if base type is concurrent? 606 bool TypeFuncGenerator::isConcurrentType() const { return false; }; 607 608 // opaque types do not have field constructors 609 void TypeFuncGenerator::genFieldCtors() { return; }; 610 611 //============================================================================================= 612 // Visitor definitions 613 //============================================================================================= 566 614 AutogenerateRoutines::AutogenerateRoutines() { 567 615 // the order here determines the order that these functions are generated. 568 616 // assignment should come last since it uses copy constructor in return. 569 data.emplace_back( "?{}", genDefaultType , constructable);570 data.emplace_back( "?{}", genCopyType , copyable);571 data.emplace_back( "^?{}", genDefaultType , destructable);572 data.emplace_back( "?=?", genAssignType , assignable);617 data.emplace_back( "?{}", genDefaultType ); 618 data.emplace_back( "?{}", genCopyType ); 619 data.emplace_back( "^?{}", genDefaultType ); 620 data.emplace_back( "?=?", genAssignType ); 573 621 } 574 622 … … 584 632 void AutogenerateRoutines::previsit( StructDecl * structDecl ) { 585 633 visit_children = false; 586 if ( structDecl->has_body() && structsDone.find( structDecl->name ) == structsDone.end()) {634 if ( structDecl->has_body() ) { 587 635 StructInstType structInst( Type::Qualifiers(), structDecl->name ); 636 structInst.set_baseStruct( structDecl ); 588 637 for ( TypeDecl * typeDecl : structDecl->parameters ) { 589 // need to visit assertions so that they are added to the appropriate maps590 // acceptAll( typeDecl->assertions, *visitor );591 638 structInst.parameters.push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeDecl->name, typeDecl ) ) ); 592 639 } 593 structInst.set_baseStruct( structDecl ); 594 makeStructFunctions( structDecl, &structInst, functionNesting, declsToAddAfter, data, indexer ); 595 structsDone.insert( structDecl->name ); 640 StructFuncGenerator gen( structDecl, &structInst, data, functionNesting, indexer ); 641 generateFunctions( gen, declsToAddAfter ); 596 642 } // if 597 643 } … … 599 645 void AutogenerateRoutines::previsit( UnionDecl * unionDecl ) { 600 646 visit_children = false; 601 if ( unionDecl->has_body() /* && unionsDone.find( unionDecl->name ) == unionsDone.end() */) {647 if ( unionDecl->has_body() ) { 602 648 UnionInstType unionInst( Type::Qualifiers(), unionDecl->get_name() ); 603 649 unionInst.set_baseUnion( unionDecl ); … … 609 655 } 610 656 611 Type * declToTypeDeclBase( Declaration * decl ) {612 if ( TypeDecl * td = dynamic_cast< TypeDecl * >( decl ) ) {613 return td->base;614 }615 return nullptr;616 }617 618 657 // generate ctor/dtors/assign for typedecls, e.g., otype T = int *; 619 658 void AutogenerateRoutines::previsit( TypeDecl * typeDecl ) { … … 621 660 if ( ! typeDecl->base ) return; 622 661 623 // generate each of the functions based on the supplied FuncData objects624 std::list< FunctionDecl * > newFuncs;625 std::list< Declaration * > tds { typeDecl };626 662 TypeInstType refType( Type::Qualifiers(), typeDecl->name, typeDecl ); 627 auto generator = makeFuncGenerator( lazy_map( tds, declToTypeDeclBase ), &refType, functionNesting, back_inserter( newFuncs ) ); 628 for ( const FuncData & d : data ) { 629 generator.gen( d, false ); 630 } 631 632 if ( functionNesting == 0 ) { 633 // forward declare if top-level struct, so that 634 // type is complete as soon as its body ends 635 // Note: this is necessary if we want structs which contain 636 // generic (otype) structs as members. 637 for ( FunctionDecl * dcl : newFuncs ) { 638 addForwardDecl( dcl, declsToAddAfter ); 639 } 640 } 641 642 for ( FunctionDecl * dcl : newFuncs ) { 643 FunctionType * ftype = dcl->type; 644 assertf( ftype->parameters.size() == 1 || ftype->parameters.size() == 2, "Incorrect number of parameters in autogenerated typedecl function: %zd", ftype->parameters.size() ); 645 DeclarationWithType * dst = ftype->parameters.front(); 646 DeclarationWithType * src = ftype->parameters.size() == 2 ? ftype->parameters.back() : nullptr; 647 // generate appropriate calls to member ctor, assignment 648 // destructor needs to do everything in reverse, so pass "forward" based on whether the function is a destructor 649 UntypedExpr * expr = new UntypedExpr( new NameExpr( dcl->name ) ); 650 expr->args.push_back( new CastExpr( new VariableExpr( dst ), new ReferenceType( Type::Qualifiers(), typeDecl->base->clone() ) ) ); 651 if ( src ) expr->args.push_back( new CastExpr( new VariableExpr( src ), typeDecl->base->clone() ) ); 652 dcl->statements->kids.push_back( new ExprStmt( noLabels, expr ) ); 653 if ( CodeGen::isAssignment( dcl->get_name() ) ) { 654 // assignment needs to return a value 655 FunctionType * assignType = dcl->type; 656 assert( assignType->parameters.size() == 2 ); 657 ObjectDecl * srcParam = strict_dynamic_cast< ObjectDecl * >( assignType->parameters.back() ); 658 dcl->statements->kids.push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) ); 659 } 660 declsToAddAfter.push_back( dcl ); 661 } 663 TypeFuncGenerator gen( typeDecl, &refType, functionNesting, data, indexer ); 664 generateFunctions( gen, declsToAddAfter ); 662 665 } 663 666 … … 680 683 visit_children = false; 681 684 // record the existence of this function as appropriate 682 insert( functionDecl, constructable, InitTweak::isDefaultConstructor ); 683 insert( functionDecl, assignable, InitTweak::isAssignment ); 684 insert( functionDecl, copyable, InitTweak::isCopyConstructor ); 685 insert( functionDecl, destructable, InitTweak::isDestructor ); 685 managedTypes.handleDWT( functionDecl ); 686 686 687 687 maybeAccept( functionDecl->type, *visitor ); … … 692 692 693 693 void AutogenerateRoutines::previsit( CompoundStmt * ) { 694 GuardScope( constructable ); 695 GuardScope( assignable ); 696 GuardScope( copyable ); 697 GuardScope( destructable ); 694 GuardScope( managedTypes ); 698 695 GuardScope( structsDone ); 699 696 }
Note: See TracChangeset
for help on using the changeset viewer.