Changes in / [aea7168:73bf8cf2]
- Location:
- src
- Files:
-
- 19 edited
Legend:
- Unmodified
- Added
- Removed
-
src/CodeGen/CodeGenerator.cc
raea7168 r73bf8cf2 271 271 printDesignators( init->get_designators() ); 272 272 output << "{ "; 273 if ( init->begin _initializers() == init->end_initializers() ) {273 if ( init->begin() == init->end() ) { 274 274 // illegal to leave initializer list empty for scalar initializers, but always legal to have 0 275 275 output << "0"; 276 276 } else { 277 genCommaList( init->begin _initializers(), init->end_initializers() );277 genCommaList( init->begin(), init->end() ); 278 278 } 279 279 output << " }"; -
src/GenPoly/DeclMutator.h
raea7168 r73bf8cf2 28 28 class DeclMutator : public Mutator { 29 29 public: 30 typedef Mutator Parent; 31 30 32 DeclMutator(); 31 33 virtual ~DeclMutator(); 32 34 35 using Parent::mutate; 33 36 virtual CompoundStmt* mutate(CompoundStmt *compoundStmt); 34 37 virtual Statement* mutate(IfStmt *ifStmt); … … 42 45 /// Mutates a list of declarations with this visitor 43 46 void mutateDeclarationList(std::list< Declaration* >& decls); 44 47 45 48 /// Called on entry to a new scope; overriders should call this as a super-class call 46 49 virtual void doBeginScope(); -
src/GenPoly/Specialize.cc
raea7168 r73bf8cf2 31 31 #include "Common/UniqueName.h" 32 32 #include "Common/utility.h" 33 #include "InitTweak/InitTweak.h" 33 34 34 35 namespace GenPoly { … … 184 185 mutateAll( appExpr->get_args(), *this ); 185 186 186 // create thunks for the inferred parameters 187 for ( InferredParams::iterator inferParam = appExpr->get_inferParams().begin(); inferParam != appExpr->get_inferParams().end(); ++inferParam ) { 188 inferParam->second.expr = doSpecialization( inferParam->second.formalType, inferParam->second.expr, &appExpr->get_inferParams() ); 189 } 190 191 handleExplicitParams( appExpr ); 187 if ( ! InitTweak::isIntrinsicCallExpr( appExpr ) ) { 188 // create thunks for the inferred parameters 189 // don't need to do this for intrinsic calls, because they aren't actually passed 190 for ( InferredParams::iterator inferParam = appExpr->get_inferParams().begin(); inferParam != appExpr->get_inferParams().end(); ++inferParam ) { 191 inferParam->second.expr = doSpecialization( inferParam->second.formalType, inferParam->second.expr, &appExpr->get_inferParams() ); 192 } 193 194 handleExplicitParams( appExpr ); 195 } 192 196 193 197 return appExpr; -
src/InitTweak/FixGlobalInit.cc
raea7168 r73bf8cf2 46 46 FunctionDecl * destroyFunction; 47 47 }; 48 49 class ConstExprChecker : public Visitor {50 public:51 ConstExprChecker() : isConstExpr( true ) {}52 53 virtual void visit( ApplicationExpr *applicationExpr ) { isConstExpr = false; }54 virtual void visit( UntypedExpr *untypedExpr ) { isConstExpr = false; }55 virtual void visit( NameExpr *nameExpr ) { isConstExpr = false; }56 virtual void visit( CastExpr *castExpr ) { isConstExpr = false; }57 virtual void visit( LabelAddressExpr *labAddressExpr ) { isConstExpr = false; }58 virtual void visit( UntypedMemberExpr *memberExpr ) { isConstExpr = false; }59 virtual void visit( MemberExpr *memberExpr ) { isConstExpr = false; }60 virtual void visit( VariableExpr *variableExpr ) { isConstExpr = false; }61 virtual void visit( ConstantExpr *constantExpr ) { /* bottom out */ }62 // these might be okay?63 // virtual void visit( SizeofExpr *sizeofExpr );64 // virtual void visit( AlignofExpr *alignofExpr );65 // virtual void visit( UntypedOffsetofExpr *offsetofExpr );66 // virtual void visit( OffsetofExpr *offsetofExpr );67 // virtual void visit( OffsetPackExpr *offsetPackExpr );68 // virtual void visit( AttrExpr *attrExpr );69 // virtual void visit( CommaExpr *commaExpr );70 // virtual void visit( LogicalExpr *logicalExpr );71 // virtual void visit( ConditionalExpr *conditionalExpr );72 virtual void visit( TupleExpr *tupleExpr ) { isConstExpr = false; }73 virtual void visit( SolvedTupleExpr *tupleExpr ) { isConstExpr = false; }74 virtual void visit( TypeExpr *typeExpr ) { isConstExpr = false; }75 virtual void visit( AsmExpr *asmExpr ) { isConstExpr = false; }76 virtual void visit( UntypedValofExpr *valofExpr ) { isConstExpr = false; }77 virtual void visit( CompoundLiteralExpr *compLitExpr ) { isConstExpr = false; }78 79 bool isConstExpr;80 };81 82 bool isConstExpr( Initializer * init ) {83 if ( init ) {84 ConstExprChecker checker;85 init->accept( checker );86 return checker.isConstExpr;87 } // if88 // for all intents and purposes, no initializer means const expr89 return true;90 }91 48 92 49 void fixGlobalInit( std::list< Declaration * > & translationUnit, const std::string & name, bool inLibrary ) { … … 140 97 std::list< Statement * > & destroyStatements = destroyFunction->get_statements()->get_kids(); 141 98 142 if ( ! tryConstruct( objDecl ) ) return; // don't construct @= or designated objects143 if ( objDecl->get_storageClass() == DeclarationNode::Extern ) return;144 99 // C allows you to initialize objects with constant expressions 145 100 // xxx - this is an optimization. Need to first resolve constructors before we decide … … 147 102 // if ( isConstExpr( objDecl->get_init() ) ) return; 148 103 149 if ( dynamic_cast< ArrayType * > ( objDecl->get_type() ) ) { 150 // xxx - initialize each element of the array 151 } else { 152 // steal initializer from object and attach it to a new temporary 153 ObjectDecl *newObj = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, objDecl->get_type()->clone(), objDecl->get_init() ); 154 objDecl->set_init( NULL ); 155 initStatements.push_back( new DeclStmt( noLabels, newObj ) ); 104 if ( ConstructorInit * ctorInit = dynamic_cast< ConstructorInit * >( objDecl->get_init() ) ) { 105 // a decision should have been made by the resolver, so ctor and init are not both non-NULL 106 assert( ! ctorInit->get_ctor() || ! ctorInit->get_init() ); 156 107 157 // copy construct objDecl using temporary 158 UntypedExpr * init = new UntypedExpr( new NameExpr( "?{}" ) ); 159 init->get_args().push_back( new AddressExpr( new VariableExpr( objDecl ) ) ); 160 init->get_args().push_back( new VariableExpr( newObj ) ); 161 initStatements.push_back( new ImplicitCtorDtorStmt( new ExprStmt( noLabels, init ) ) ); 162 163 // add destructor calls to global destroy function 164 UntypedExpr * destroy = new UntypedExpr( new NameExpr( "^?{}" ) ); 165 destroy->get_args().push_back( new AddressExpr( new VariableExpr( objDecl ) ) ); 166 destroyStatements.push_front( new ImplicitCtorDtorStmt( new ExprStmt( noLabels, destroy ) ) ); 108 Statement * dtor = ctorInit->get_dtor(); 109 if ( dtor && ! isInstrinsicSingleArgCallStmt( dtor ) ) { 110 // don't need to call intrinsic dtor, because it does nothing, but 111 // non-intrinsic dtors must be called 112 destroyStatements.push_front( dtor ); 113 ctorInit->set_dtor( NULL ); 114 } // if 115 if ( Statement * ctor = ctorInit->get_ctor() ) { 116 initStatements.push_back( ctor ); 117 objDecl->set_init( NULL ); 118 ctorInit->set_ctor( NULL ); 119 } else if ( Initializer * init = ctorInit->get_init() ) { 120 objDecl->set_init( init ); 121 ctorInit->set_init( NULL ); 122 } else { 123 // no constructor and no initializer, which is okay 124 objDecl->set_init( NULL ); 125 } // if 126 delete ctorInit; 167 127 } // if 168 128 } -
src/InitTweak/FixInit.cc
raea7168 r73bf8cf2 18 18 #include <iterator> 19 19 #include <algorithm> 20 #include "InitTweak.h" 20 21 #include "FixInit.h" 21 #include " InitTweak.h"22 #include "FixGlobalInit.h" 22 23 #include "ResolvExpr/Resolver.h" 23 24 #include "ResolvExpr/typeops.h" … … 83 84 }; 84 85 86 // debug 85 87 struct printSet { 86 88 typedef ObjDeclCollector::ObjectSet ObjectSet; … … 159 161 160 162 virtual DeclarationWithType * mutate( ObjectDecl *objDecl ); 163 164 std::list< Declaration * > staticDtorDecls; 161 165 }; 162 166 … … 171 175 } // namespace 172 176 173 void fix( std::list< Declaration * > & translationUnit ) { 177 void fix( std::list< Declaration * > & translationUnit, const std::string & filename, bool inLibrary ) { 178 // fixes ConstructorInit for global variables. should happen before fixInitializers. 179 InitTweak::fixGlobalInit( translationUnit, filename, inLibrary ); 180 174 181 InsertImplicitCalls::insert( translationUnit ); 175 182 ResolveCopyCtors::resolveImplicitCalls( translationUnit ); … … 194 201 void FixInit::fixInitializers( std::list< Declaration * > & translationUnit ) { 195 202 FixInit fixer; 196 mutateAll( translationUnit, fixer ); 203 204 // can't use mutateAll, because need to insert declarations at top-level 205 // can't use DeclMutator, because sometimes need to insert IfStmt, etc. 206 SemanticError errors; 207 for ( std::list< Declaration * >::iterator i = translationUnit.begin(); i != translationUnit.end(); ++i ) { 208 try { 209 *i = maybeMutate( *i, fixer ); 210 // if (! fixer.staticDtorDecls.empty() ) { 211 translationUnit.splice( i, fixer.staticDtorDecls ); 212 // } 213 } catch( SemanticError &e ) { 214 errors.append( e ); 215 } // try 216 } // for 217 if ( ! errors.isEmpty() ) { 218 throw errors; 219 } // if 197 220 } 198 221 … … 422 445 if ( Statement * ctor = ctorInit->get_ctor() ) { 423 446 if ( objDecl->get_storageClass() == DeclarationNode::Static ) { 447 // originally wanted to take advantage of gcc nested functions, but 448 // we get memory errors with this approach. To remedy this, create a 449 // global static pointer that is set to refer to the object and make 450 // the dtor-caller function global so that. 451 // 424 452 // generate: 425 // static bool __objName_uninitialized = true; 426 // if (__objName_uninitialized) { 427 // __ctor(__objName); 428 // void dtor_atexit() { 429 // __dtor(__objName); 453 // T * __objName_static_ptrN; 454 // void __objName_dtor_atexitN() { 455 // __dtor(__objName_static_ptrN); 456 // } 457 // int f(...) { 458 // ... 459 // static T __objName; 460 // static bool __objName_uninitialized = true; 461 // if (__objName_uninitialized) { 462 // __objName_ptr = &__objName; 463 // __ctor(__objName); 464 // on_exit(__objName_dtor_atexitN, &__objName); 465 // __objName_uninitialized = false; 430 466 // } 431 // on_exit(dtorOnExit, &__objName); 432 // __objName_uninitialized = false; 467 // ... 433 468 // } 434 469 435 // generate first line 470 static UniqueName ptrNamer( "_static_ptr" ); 471 static UniqueName dtorCallerNamer( "_dtor_atexit" ); 472 473 // T * __objName_ptrN 474 ObjectDecl * objPtr = new ObjectDecl( objDecl->get_mangleName() + ptrNamer.newName(), DeclarationNode::Static, LinkageSpec::C, 0, new PointerType( Type::Qualifiers(), objDecl->get_type()->clone() ), 0 ); 475 objPtr->fixUniqueId(); 476 477 // void __objName_dtor_atexitN(...) {...} 478 // need to modify dtor call so that it refers to objPtr, since function will be global 479 Statement * dtorStmt = ctorInit->get_dtor()->clone(); 480 ApplicationExpr * dtor = dynamic_cast< ApplicationExpr * >( InitTweak::getCtorDtorCall( dtorStmt ) ); 481 assert( dtor ); 482 delete dtor->get_args().front(); 483 dtor->get_args().front() = new VariableExpr( objPtr ); 484 485 FunctionDecl * dtorCaller = new FunctionDecl( objDecl->get_mangleName() + dtorCallerNamer.newName(), DeclarationNode::Static, LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt( noLabels ), false, false ); 486 dtorCaller->fixUniqueId(); 487 dtorCaller->get_statements()->get_kids().push_back( dtorStmt ); 488 489 // static bool __objName_uninitialized = true 436 490 BasicType * boolType = new BasicType( Type::Qualifiers(), BasicType::Bool ); 437 491 SingleInit * boolInitExpr = new SingleInit( new ConstantExpr( Constant( boolType->clone(), "1" ) ), noDesignators ); … … 439 493 isUninitializedVar->fixUniqueId(); 440 494 441 // void dtor_atexit(...) {...}442 FunctionDecl * dtorCaller = new FunctionDecl( objDecl->get_mangleName() + "_dtor_atexit", DeclarationNode::NoStorageClass, LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt( noLabels ), false, false);443 dtorCaller->fixUniqueId();444 dtorCaller->get_statements()->get_kids().push_back( ctorInit->get_dtor()->clone() );445 446 // on_exit(dtor_atexit);495 // __objName_static_ptrN = &__objName; 496 UntypedExpr * ptrAssign = new UntypedExpr( new NameExpr( "?=?" ) ); 497 ptrAssign->get_args().push_back( new VariableExpr( objPtr ) ); 498 ptrAssign->get_args().push_back( new AddressExpr( new VariableExpr( objDecl ) ) ); 499 500 // atexit(dtor_atexit); 447 501 UntypedExpr * callAtexit = new UntypedExpr( new NameExpr( "atexit" ) ); 448 502 callAtexit->get_args().push_back( new VariableExpr( dtorCaller ) ); … … 457 511 std::list< Statement * > & body = initStmts->get_kids(); 458 512 body.push_back( ctor ); 459 body.push_back( new DeclStmt( noLabels, dtorCaller) );513 body.push_back( new ExprStmt( noLabels, ptrAssign ) ); 460 514 body.push_back( new ExprStmt( noLabels, callAtexit ) ); 461 515 body.push_back( new ExprStmt( noLabels, setTrue ) ); … … 465 519 stmtsToAddAfter.push_back( new DeclStmt( noLabels, isUninitializedVar ) ); 466 520 stmtsToAddAfter.push_back( ifStmt ); 521 522 // add pointer and dtor caller decls to list of decls that will be added into global scope 523 staticDtorDecls.push_back( objPtr ); 524 staticDtorDecls.push_back( dtorCaller ); 467 525 } else { 468 526 stmtsToAddAfter.push_back( ctor ); -
src/InitTweak/FixInit.h
raea7168 r73bf8cf2 27 27 /// replace constructor initializers with expression statements 28 28 /// and unwrap basic C-style initializers 29 void fix( std::list< Declaration * > & translationUnit );29 void fix( std::list< Declaration * > & translationUnit, const std::string & name, bool inLibrary ); 30 30 } // namespace 31 31 -
src/InitTweak/GenInit.cc
raea7168 r73bf8cf2 26 26 #include "SymTab/Autogen.h" 27 27 #include "GenPoly/PolyMutator.h" 28 #include "GenPoly/DeclMutator.h" 28 29 29 30 namespace InitTweak { … … 55 56 public: 56 57 /// create constructor and destructor statements for object declarations. 57 /// Destructors are inserted directly into the code, whereas constructors58 /// will be added in after the resolver has run so that the initializer expression59 /// is only removed if a constructor is found58 /// the actual call statements will be added in after the resolver has run 59 /// so that the initializer expression is only removed if a constructor is found 60 /// and the same destructor call is inserted in all of the appropriate locations. 60 61 static void generateCtorDtor( std::list< Declaration * > &translationUnit ); 61 62 CtorDtor() : inFunction( false ) {}63 62 64 63 virtual DeclarationWithType * mutate( ObjectDecl * ); 65 64 virtual DeclarationWithType * mutate( FunctionDecl *functionDecl ); 66 virtual Declaration* mutate( StructDecl *aggregateDecl ); 67 virtual Declaration* mutate( UnionDecl *aggregateDecl ); 68 virtual Declaration* mutate( EnumDecl *aggregateDecl ); 69 virtual Declaration* mutate( TraitDecl *aggregateDecl ); 70 virtual TypeDecl* mutate( TypeDecl *typeDecl ); 71 virtual Declaration* mutate( TypedefDecl *typeDecl ); 72 73 virtual Type * mutate( FunctionType *funcType ); 65 // should not traverse into any of these declarations to find objects 66 // that need to be constructed or destructed 67 virtual Declaration* mutate( StructDecl *aggregateDecl ) { return aggregateDecl; } 68 virtual Declaration* mutate( UnionDecl *aggregateDecl ) { return aggregateDecl; } 69 virtual Declaration* mutate( EnumDecl *aggregateDecl ) { return aggregateDecl; } 70 virtual Declaration* mutate( TraitDecl *aggregateDecl ) { return aggregateDecl; } 71 virtual TypeDecl* mutate( TypeDecl *typeDecl ) { return typeDecl; } 72 virtual Declaration* mutate( TypedefDecl *typeDecl ) { return typeDecl; } 73 74 virtual Type * mutate( FunctionType *funcType ) { return funcType; } 74 75 75 76 protected: 76 bool inFunction; 77 }; 78 79 class HoistArrayDimension : public GenPoly::DeclMutator { 80 public: 81 typedef GenPoly::DeclMutator Parent; 82 83 /// hoist dimension from array types in object declaration so that it uses a single 84 /// const variable of type size_t, so that side effecting array dimensions are only 85 /// computed once. 86 static void hoistArrayDimension( std::list< Declaration * > & translationUnit ); 87 88 private: 89 virtual DeclarationWithType * mutate( ObjectDecl * objectDecl ); 90 virtual DeclarationWithType * mutate( FunctionDecl *functionDecl ); 91 // should not traverse into any of these declarations to find objects 92 // that need to be constructed or destructed 93 virtual Declaration* mutate( StructDecl *aggregateDecl ) { return aggregateDecl; } 94 virtual Declaration* mutate( UnionDecl *aggregateDecl ) { return aggregateDecl; } 95 virtual Declaration* mutate( EnumDecl *aggregateDecl ) { return aggregateDecl; } 96 virtual Declaration* mutate( TraitDecl *aggregateDecl ) { return aggregateDecl; } 97 virtual TypeDecl* mutate( TypeDecl *typeDecl ) { return typeDecl; } 98 virtual Declaration* mutate( TypedefDecl *typeDecl ) { return typeDecl; } 99 100 virtual Type* mutate( FunctionType *funcType ) { return funcType; } 101 102 void hoist( Type * type ); 103 104 DeclarationNode::StorageClass storageclass = DeclarationNode::NoStorageClass; 105 bool inFunction = false; 77 106 }; 78 107 79 108 void genInit( std::list< Declaration * > & translationUnit ) { 80 109 ReturnFixer::makeReturnTemp( translationUnit ); 110 HoistArrayDimension::hoistArrayDimension( translationUnit ); 81 111 CtorDtor::generateCtorDtor( translationUnit ); 82 112 } … … 124 154 } 125 155 156 // precompute array dimension expression, because constructor generation may duplicate it, 157 // which would be incorrect if it is a side-effecting computation. 158 void HoistArrayDimension::hoistArrayDimension( std::list< Declaration * > & translationUnit ) { 159 HoistArrayDimension hoister; 160 hoister.mutateDeclarationList( translationUnit ); 161 } 162 163 DeclarationWithType * HoistArrayDimension::mutate( ObjectDecl * objectDecl ) { 164 storageclass = objectDecl->get_storageClass(); 165 DeclarationWithType * temp = Parent::mutate( objectDecl ); 166 hoist( objectDecl->get_type() ); 167 storageclass = DeclarationNode::NoStorageClass; 168 return temp; 169 } 170 171 void HoistArrayDimension::hoist( Type * type ) { 172 // if in function, generate const size_t var 173 static UniqueName dimensionName( "_array_dim" ); 174 if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) { 175 if ( ! inFunction ) return; 176 177 if ( ! arrayType->get_dimension() ) return; // xxx - recursive call to hoist? 178 179 // don't need to hoist dimension if it's a constexpr - only need to if there's potential 180 // for side effects. 181 if ( isConstExpr( arrayType->get_dimension() ) ) return; 182 183 ObjectDecl * arrayDimension = new ObjectDecl( dimensionName.newName(), storageclass, LinkageSpec::C, 0, SymTab::SizeType->clone(), new SingleInit( arrayType->get_dimension() ) ); 184 arrayDimension->get_type()->set_isConst( true ); 185 186 arrayType->set_dimension( new VariableExpr( arrayDimension ) ); 187 addDeclaration( arrayDimension ); 188 189 hoist( arrayType->get_base() ); 190 return; 191 } 192 } 193 194 DeclarationWithType * HoistArrayDimension::mutate( FunctionDecl *functionDecl ) { 195 bool oldInFunc = inFunction; 196 inFunction = true; 197 DeclarationWithType * decl = Parent::mutate( functionDecl ); 198 inFunction = oldInFunc; 199 return decl; 200 } 126 201 127 202 void CtorDtor::generateCtorDtor( std::list< Declaration * > & translationUnit ) { … … 140 215 141 216 DeclarationWithType * CtorDtor::mutate( ObjectDecl * objDecl ) { 142 // hands off if designated or if @=217 // hands off if designated, if @=, or if extern 143 218 if ( tryConstruct( objDecl ) ) { 144 if ( inFunction ) { 145 if ( ArrayType * at = dynamic_cast< ArrayType * >( objDecl->get_type() ) ) { 146 // call into makeArrayFunction from validate.cc to generate calls to ctor/dtor for each element of array 147 // TODO: walk initializer and generate appropriate copy ctor if element has initializer 148 std::list< Expression * > args = makeInitList( objDecl->get_init() ); 149 if ( args.empty() ) { 150 std::list< Statement * > ctor; 151 std::list< Statement * > dtor; 152 153 SymTab::makeArrayFunction( NULL, new VariableExpr( objDecl ), at, "?{}", back_inserter( ctor ) ); 154 SymTab::makeArrayFunction( NULL, new VariableExpr( objDecl ), at, "^?{}", front_inserter( dtor ), false ); 155 156 // Currently makeArrayFunction produces a single Statement - a CompoundStmt 157 // which wraps everything that needs to happen. As such, it's technically 158 // possible to use a Statement ** in the above calls, but this is inherently 159 // unsafe, so instead we take the slightly less efficient route, but will be 160 // immediately informed if somehow the above assumption is broken. In this case, 161 // we could always wrap the list of statements at this point with a CompoundStmt, 162 // but it seems reasonable at the moment for this to be done by makeArrayFunction 163 // itself 164 assert( ctor.size() == 1 && dynamic_cast< ImplicitCtorDtorStmt * >( ctor.front() ) ); 165 assert( dtor.size() == 1 && dynamic_cast< ImplicitCtorDtorStmt * >( dtor.front() ) ); 166 objDecl->set_init( new ConstructorInit( ctor.front(), dtor.front(), objDecl->get_init() ) ); 167 } else { 168 // array came with an initializer list: initialize each element 169 // may have more initializers than elements in the array - need to check at each index that 170 // we haven't exceeded size. This requires precomputing the size because it might be a side-effecting 171 // computation. 172 // may have fewer initializers than eleemnts in the array - need to default construct 173 // remaining elements. 174 // might be able to merge this with the case above. 175 } 176 } else { 177 // it's sufficient to attempt to call the ctor/dtor for the given object and its initializer 178 Expression * ctor = makeCtorDtorExpr( "?{}", objDecl, makeInitList( objDecl->get_init() ) ); 179 Expression * dtor = makeCtorDtorExpr( "^?{}", objDecl, std::list< Expression * >() ); 180 181 // need to remember init expression, in case no ctors exist 182 // if ctor does exist, want to use ctor expression instead of init 183 // push this decision to the resolver 184 ExprStmt * ctorStmt = new ExprStmt( noLabels, ctor ); 185 ExprStmt * dtorStmt = new ExprStmt( noLabels, dtor ); 186 objDecl->set_init( new ConstructorInit( new ImplicitCtorDtorStmt( ctorStmt ), new ImplicitCtorDtorStmt( dtorStmt ), objDecl->get_init() ) ); 187 } 219 // call into genImplicitCall from Autogen.h to generate calls to ctor/dtor 220 // for each constructable object 221 std::list< Statement * > ctor; 222 std::list< Statement * > dtor; 223 224 InitExpander srcParam( objDecl->get_init() ); 225 InitExpander nullParam( (Initializer *)NULL ); 226 SymTab::genImplicitCall( srcParam, new VariableExpr( objDecl ), "?{}", back_inserter( ctor ), objDecl ); 227 SymTab::genImplicitCall( nullParam, new VariableExpr( objDecl ), "^?{}", front_inserter( dtor ), objDecl, false ); 228 229 // Currently genImplicitCall produces a single Statement - a CompoundStmt 230 // which wraps everything that needs to happen. As such, it's technically 231 // possible to use a Statement ** in the above calls, but this is inherently 232 // unsafe, so instead we take the slightly less efficient route, but will be 233 // immediately informed if somehow the above assumption is broken. In this case, 234 // we could always wrap the list of statements at this point with a CompoundStmt, 235 // but it seems reasonable at the moment for this to be done by genImplicitCall 236 // itself. It is possible that genImplicitCall produces no statements (e.g. if 237 // an array type does not have a dimension). In this case, it's fine to ignore 238 // the object for the purposes of construction. 239 assert( ctor.size() == dtor.size() && ctor.size() <= 1 ); 240 if ( ctor.size() == 1 ) { 241 // need to remember init expression, in case no ctors exist 242 // if ctor does exist, want to use ctor expression instead of init 243 // push this decision to the resolver 244 assert( dynamic_cast< ImplicitCtorDtorStmt * > ( ctor.front() ) && dynamic_cast< ImplicitCtorDtorStmt * > ( dtor.front() ) ); 245 objDecl->set_init( new ConstructorInit( ctor.front(), dtor.front(), objDecl->get_init() ) ); 188 246 } 189 247 } … … 193 251 DeclarationWithType * CtorDtor::mutate( FunctionDecl *functionDecl ) { 194 252 // parameters should not be constructed and destructed, so don't mutate FunctionType 195 bool oldInFunc = inFunction;196 253 mutateAll( functionDecl->get_oldDecls(), *this ); 197 inFunction = true;198 254 functionDecl->set_statements( maybeMutate( functionDecl->get_statements(), *this ) ); 199 inFunction = oldInFunc;200 255 return functionDecl; 201 256 } 202 203 // should not traverse into any of these declarations to find objects204 // that need to be constructed or destructed205 Declaration* CtorDtor::mutate( StructDecl *aggregateDecl ) { return aggregateDecl; }206 Declaration* CtorDtor::mutate( UnionDecl *aggregateDecl ) { return aggregateDecl; }207 Declaration* CtorDtor::mutate( EnumDecl *aggregateDecl ) { return aggregateDecl; }208 Declaration* CtorDtor::mutate( TraitDecl *aggregateDecl ) { return aggregateDecl; }209 TypeDecl* CtorDtor::mutate( TypeDecl *typeDecl ) { return typeDecl; }210 Declaration* CtorDtor::mutate( TypedefDecl *typeDecl ) { return typeDecl; }211 Type* CtorDtor::mutate( FunctionType *funcType ) { return funcType; }212 213 257 } // namespace InitTweak 214 258 -
src/InitTweak/InitTweak.cc
raea7168 r73bf8cf2 1 #include <algorithm> 1 2 #include "InitTweak.h" 2 3 #include "SynTree/Visitor.h" … … 20 21 }; 21 22 22 class Init Expander : public Visitor {23 class InitFlattener : public Visitor { 23 24 public: 24 InitExpander() {}25 25 virtual void visit( SingleInit * singleInit ); 26 26 virtual void visit( ListInit * listInit ); … … 28 28 }; 29 29 30 void Init Expander::visit( SingleInit * singleInit ) {30 void InitFlattener::visit( SingleInit * singleInit ) { 31 31 argList.push_back( singleInit->get_value()->clone() ); 32 32 } 33 33 34 void Init Expander::visit( ListInit * listInit ) {35 // xxx - for now, assume nonested list inits36 std::list<Initializer*>::iterator it = listInit->begin _initializers();37 for ( ; it != listInit->end _initializers(); ++it ) {34 void InitFlattener::visit( ListInit * listInit ) { 35 // flatten nested list inits 36 std::list<Initializer*>::iterator it = listInit->begin(); 37 for ( ; it != listInit->end(); ++it ) { 38 38 (*it)->accept( *this ); 39 39 } … … 42 42 43 43 std::list< Expression * > makeInitList( Initializer * init ) { 44 Init Expander expander;45 maybeAccept( init, expander );46 return expander.argList;44 InitFlattener flattener; 45 maybeAccept( init, flattener ); 46 return flattener.argList; 47 47 } 48 48 … … 53 53 } 54 54 55 class InitExpander::ExpanderImpl { 56 public: 57 virtual std::list< Expression * > next( std::list< Expression * > & indices ) = 0; 58 virtual Statement * buildListInit( UntypedExpr * callExpr, std::list< Expression * > & indices ) = 0; 59 }; 60 61 class InitImpl : public InitExpander::ExpanderImpl { 62 public: 63 InitImpl( Initializer * init ) : init( init ) {} 64 65 virtual std::list< Expression * > next( std::list< Expression * > & indices ) { 66 // this is wrong, but just a placeholder for now 67 // if ( ! flattened ) flatten( indices ); 68 // return ! inits.empty() ? makeInitList( inits.front() ) : std::list< Expression * >(); 69 return makeInitList( init ); 70 } 71 72 virtual Statement * buildListInit( UntypedExpr * callExpr, std::list< Expression * > & indices ); 73 private: 74 Initializer * init; 75 }; 76 77 class ExprImpl : public InitExpander::ExpanderImpl { 78 public: 79 ExprImpl( Expression * expr ) : arg( expr ) {} 80 81 virtual std::list< Expression * > next( std::list< Expression * > & indices ) { 82 std::list< Expression * > ret; 83 Expression * expr = maybeClone( arg ); 84 if ( expr ) { 85 for ( std::list< Expression * >::reverse_iterator it = indices.rbegin(); it != indices.rend(); ++it ) { 86 // go through indices and layer on subscript exprs ?[?] 87 ++it; 88 UntypedExpr * subscriptExpr = new UntypedExpr( new NameExpr( "?[?]") ); 89 subscriptExpr->get_args().push_back( expr ); 90 subscriptExpr->get_args().push_back( (*it)->clone() ); 91 expr = subscriptExpr; 92 } 93 ret.push_back( expr ); 94 } 95 return ret; 96 } 97 98 virtual Statement * buildListInit( UntypedExpr * callExpr, std::list< Expression * > & indices ); 99 private: 100 Expression * arg; 101 }; 102 103 InitExpander::InitExpander( Initializer * init ) : expander( new InitImpl( init ) ) {} 104 105 InitExpander::InitExpander( Expression * expr ) : expander( new ExprImpl( expr ) ) {} 106 107 std::list< Expression * > InitExpander::operator*() { 108 return cur; 109 } 110 111 InitExpander & InitExpander::operator++() { 112 cur = expander->next( indices ); 113 return *this; 114 } 115 116 // use array indices list to build switch statement 117 void InitExpander::addArrayIndex( Expression * index, Expression * dimension ) { 118 indices.push_back( index ); 119 indices.push_back( dimension ); 120 } 121 122 void InitExpander::clearArrayIndices() { 123 indices.clear(); 124 } 125 126 namespace { 127 template< typename OutIterator > 128 void dothething( UntypedExpr * callExpr, Expression * index, Expression * dimension, Initializer * init, OutIterator out ) { 129 UntypedExpr * cond = new UntypedExpr( new NameExpr( "?<?") ); 130 cond->get_args().push_back( index->clone() ); 131 cond->get_args().push_back( dimension->clone() ); 132 133 std::list< Expression * > args = makeInitList( init ); 134 callExpr->get_args().splice( callExpr->get_args().end(), args ); 135 136 *out++ = new IfStmt( noLabels, cond, new ExprStmt( noLabels, callExpr ), NULL ); 137 138 UntypedExpr * increment = new UntypedExpr( new NameExpr( "++?" ) ); 139 increment->get_args().push_back( new AddressExpr( index->clone() ) ); 140 *out++ = new ExprStmt( noLabels, increment ); 141 } 142 143 template< typename OutIterator > 144 void build( UntypedExpr * callExpr, InitExpander::IndexList::iterator idx, InitExpander::IndexList::iterator idxEnd, Initializer * init, OutIterator out ) { 145 if ( idx == idxEnd ) return; 146 Expression * index = *idx++; 147 assert( idx != idxEnd ); 148 Expression * dimension = *idx++; 149 150 if ( idx == idxEnd ) { 151 if ( ListInit * listInit = dynamic_cast< ListInit * >( init ) ) { 152 for ( Initializer * init : *listInit ) { 153 dothething( callExpr->clone(), index, dimension, init, out ); 154 } 155 } else { 156 dothething( callExpr->clone(), index, dimension, init, out ); 157 } 158 } else { 159 std::list< Statement * > branches; 160 161 unsigned long cond = 0; 162 ListInit * listInit = dynamic_cast< ListInit * >( init ); 163 if ( ! listInit ) { 164 // xxx - this shouldn't be an error, but need a way to 165 // terminate without creating output, so should catch this error 166 throw SemanticError( "unbalanced list initializers" ); 167 } 168 for ( Initializer * init : *listInit ) { 169 Expression * condition; 170 // check for designations 171 // if ( init-> ) { 172 condition = new ConstantExpr( Constant::from_ulong( cond ) ); 173 ++cond; 174 // } else { 175 // condition = // ... take designation 176 // cond = // ... take designation+1 177 // } 178 std::list< Statement * > stmts; 179 build( callExpr, idx, idxEnd, init, back_inserter( stmts ) ); 180 CaseStmt * caseStmt = new CaseStmt( noLabels, condition, stmts ); 181 branches.push_back( caseStmt ); 182 } 183 *out++ = new SwitchStmt( noLabels, index->clone(), branches ); 184 } 185 } 186 } 187 188 // if array came with an initializer list: initialize each element 189 // may have more initializers than elements in the array - need to check at each index that 190 // we haven't exceeded size. 191 // may have fewer initializers than elements in the array - need to default construct 192 // remaining elements. 193 // To accomplish this, generate switch statement, consuming all of expander's elements 194 Statement * InitImpl::buildListInit( UntypedExpr * dst, std::list< Expression * > & indices ) { 195 if ( ! init ) return NULL; 196 std::list< Statement * > results; 197 build( dst, indices.begin(), indices.end(), init, back_inserter( results ) ); 198 assert( results.size() <= 1 ); 199 if ( results.empty() ) { 200 return NULL; 201 } else { 202 init = NULL; // init was consumed in creating the list init 203 return results.front(); 204 } 205 return ! results.empty() ? results.front() : NULL; 206 } 207 208 Statement * ExprImpl::buildListInit( UntypedExpr * dst, std::list< Expression * > & indices ) { 209 return NULL; 210 } 211 212 Statement * InitExpander::buildListInit( UntypedExpr * dst ) { 213 return expander->buildListInit( dst, indices ); 214 } 215 55 216 bool tryConstruct( ObjectDecl * objDecl ) { 56 217 return ! LinkageSpec::isBuiltin( objDecl->get_linkage() ) && 57 218 (objDecl->get_init() == NULL || 58 219 ( objDecl->get_init() != NULL && objDecl->get_init()->get_maybeConstructed() )) && 59 ! isDesignated( objDecl->get_init() ); 220 ! isDesignated( objDecl->get_init() ) 221 && objDecl->get_storageClass() != DeclarationNode::Extern; 222 } 223 224 class CallFinder : public Visitor { 225 public: 226 typedef Visitor Parent; 227 CallFinder( const std::list< std::string > & names ) : names( names ) {} 228 229 virtual void visit( ApplicationExpr * appExpr ) { 230 handleCallExpr( appExpr ); 231 } 232 233 virtual void visit( UntypedExpr * untypedExpr ) { 234 handleCallExpr( untypedExpr ); 235 } 236 237 std::list< Expression * > * matches; 238 private: 239 const std::list< std::string > names; 240 241 template< typename CallExpr > 242 void handleCallExpr( CallExpr * expr ) { 243 Parent::visit( expr ); 244 std::string fname = getFunctionName( expr ); 245 if ( std::find( names.begin(), names.end(), fname ) != names.end() ) { 246 matches->push_back( expr ); 247 } 248 } 249 }; 250 251 void collectCtorDtorCalls( Statement * stmt, std::list< Expression * > & matches ) { 252 static CallFinder finder( std::list< std::string >{ "?{}", "^?{}" } ); 253 finder.matches = &matches; 254 maybeAccept( stmt, finder ); 60 255 } 61 256 62 257 Expression * getCtorDtorCall( Statement * stmt ) { 63 if ( stmt == NULL ) return NULL; 64 if ( ExprStmt * exprStmt = dynamic_cast< ExprStmt * >( stmt ) ) { 65 return exprStmt->get_expr(); 66 } else if ( CompoundStmt * compoundStmt = dynamic_cast< CompoundStmt * >( stmt ) ) { 67 // could also be a compound statement with a loop, in the case of an array 68 if( compoundStmt->get_kids().size() == 2 ) { 69 // loop variable and loop 70 ForStmt * forStmt = dynamic_cast< ForStmt * >( compoundStmt->get_kids().back() ); 71 assert( forStmt && forStmt->get_body() ); 72 return getCtorDtorCall( forStmt->get_body() ); 73 } else if ( compoundStmt->get_kids().size() == 1 ) { 74 // should be the call statement, but in any case there's only one option 75 return getCtorDtorCall( compoundStmt->get_kids().front() ); 76 } else { 77 assert( false && "too many statements in compoundStmt for getCtorDtorCall" ); 78 } 79 } if ( ImplicitCtorDtorStmt * impCtorDtorStmt = dynamic_cast< ImplicitCtorDtorStmt * > ( stmt ) ) { 80 return getCtorDtorCall( impCtorDtorStmt->get_callStmt() ); 81 } else { 82 // should never get here 83 assert( false && "encountered unknown call statement" ); 84 } 85 } 86 87 bool isInstrinsicSingleArgCallStmt( Statement * stmt ) { 88 Expression * callExpr = getCtorDtorCall( stmt ); 89 if ( ! callExpr ) return false; 90 ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( callExpr ); 91 assert( appExpr ); 92 VariableExpr * function = dynamic_cast< VariableExpr * >( appExpr->get_function() ); 258 std::list< Expression * > matches; 259 collectCtorDtorCalls( stmt, matches ); 260 assert( matches.size() <= 1 ); 261 return matches.size() == 1 ? matches.front() : NULL; 262 } 263 264 namespace { 265 VariableExpr * getCalledFunction( ApplicationExpr * appExpr ) { 266 assert( appExpr ); 267 // xxx - it's possible this can be other things, e.g. MemberExpr, so this is insufficient 268 return dynamic_cast< VariableExpr * >( appExpr->get_function() ); 269 } 270 } 271 272 ApplicationExpr * isIntrinsicCallExpr( Expression * expr ) { 273 ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr ); 274 if ( ! appExpr ) return NULL; 275 VariableExpr * function = getCalledFunction( appExpr ); 93 276 assert( function ); 94 277 // check for Intrinsic only - don't want to remove all overridable ctor/dtors because autogenerated ctor/dtor 95 278 // will call all member dtors, and some members may have a user defined dtor. 96 FunctionType * funcType = GenPoly::getFunctionType( function->get_var()->get_type() ); 97 assert( funcType ); 98 return function->get_var()->get_linkage() == LinkageSpec::Intrinsic && funcType->get_parameters().size() == 1; 279 return function->get_var()->get_linkage() == LinkageSpec::Intrinsic ? appExpr : NULL; 280 } 281 282 bool isInstrinsicSingleArgCallStmt( Statement * stmt ) { 283 std::list< Expression * > callExprs; 284 collectCtorDtorCalls( stmt, callExprs ); 285 // if ( callExprs.empty() ) return false; // xxx - do I still need this check? 286 return std::all_of( callExprs.begin(), callExprs.end(), []( Expression * callExpr ){ 287 if ( ApplicationExpr * appExpr = isIntrinsicCallExpr( callExpr ) ) { 288 assert( ! appExpr->get_function()->get_results().empty() ); 289 FunctionType *funcType = GenPoly::getFunctionType( appExpr->get_function()->get_results().front() ); 290 assert( funcType ); 291 return funcType->get_parameters().size() == 1; 292 } 293 return false; 294 }); 99 295 } 100 296 … … 160 356 else return NULL; 161 357 } 358 359 class ConstExprChecker : public Visitor { 360 public: 361 ConstExprChecker() : isConstExpr( true ) {} 362 363 virtual void visit( ApplicationExpr *applicationExpr ) { isConstExpr = false; } 364 virtual void visit( UntypedExpr *untypedExpr ) { isConstExpr = false; } 365 virtual void visit( NameExpr *nameExpr ) { isConstExpr = false; } 366 virtual void visit( CastExpr *castExpr ) { isConstExpr = false; } 367 virtual void visit( LabelAddressExpr *labAddressExpr ) { isConstExpr = false; } 368 virtual void visit( UntypedMemberExpr *memberExpr ) { isConstExpr = false; } 369 virtual void visit( MemberExpr *memberExpr ) { isConstExpr = false; } 370 virtual void visit( VariableExpr *variableExpr ) { isConstExpr = false; } 371 virtual void visit( ConstantExpr *constantExpr ) { /* bottom out */ } 372 // these might be okay? 373 // virtual void visit( SizeofExpr *sizeofExpr ); 374 // virtual void visit( AlignofExpr *alignofExpr ); 375 // virtual void visit( UntypedOffsetofExpr *offsetofExpr ); 376 // virtual void visit( OffsetofExpr *offsetofExpr ); 377 // virtual void visit( OffsetPackExpr *offsetPackExpr ); 378 // virtual void visit( AttrExpr *attrExpr ); 379 // virtual void visit( CommaExpr *commaExpr ); 380 // virtual void visit( LogicalExpr *logicalExpr ); 381 // virtual void visit( ConditionalExpr *conditionalExpr ); 382 virtual void visit( TupleExpr *tupleExpr ) { isConstExpr = false; } 383 virtual void visit( SolvedTupleExpr *tupleExpr ) { isConstExpr = false; } 384 virtual void visit( TypeExpr *typeExpr ) { isConstExpr = false; } 385 virtual void visit( AsmExpr *asmExpr ) { isConstExpr = false; } 386 virtual void visit( UntypedValofExpr *valofExpr ) { isConstExpr = false; } 387 virtual void visit( CompoundLiteralExpr *compLitExpr ) { isConstExpr = false; } 388 389 bool isConstExpr; 390 }; 391 392 bool isConstExpr( Expression * expr ) { 393 if ( expr ) { 394 ConstExprChecker checker; 395 expr->accept( checker ); 396 return checker.isConstExpr; 397 } 398 return true; 399 } 400 401 bool isConstExpr( Initializer * init ) { 402 if ( init ) { 403 ConstExprChecker checker; 404 init->accept( checker ); 405 return checker.isConstExpr; 406 } // if 407 // for all intents and purposes, no initializer means const expr 408 return true; 409 } 410 162 411 } -
src/InitTweak/InitTweak.h
raea7168 r73bf8cf2 26 26 // helper functions for initialization 27 27 namespace InitTweak { 28 29 28 /// transform Initializer into an argument list that can be passed to a call expression 29 std::list< Expression * > makeInitList( Initializer * init ); 30 30 31 32 31 /// True if the resolver should try to construct objDecl 32 bool tryConstruct( ObjectDecl * objDecl ); 33 33 34 35 34 /// True if the Initializer contains designations 35 bool isDesignated( Initializer * init ); 36 36 37 /// True if stmt is a call statement where the function called is intrinsic and takes one parameter. 38 /// Intended to be used for default ctor/dtor calls, but might have use elsewhere. 39 /// Currently has assertions that make it less than fully general. 40 bool isInstrinsicSingleArgCallStmt( Statement * expr ); 37 /// Non-Null if expr is a call expression whose target function is intrinsic 38 ApplicationExpr * isIntrinsicCallExpr( Expression * expr ); 41 39 42 /// get the Ctor/Dtor call expression from a Statement that looks like a generated ctor/dtor call 43 Expression * getCtorDtorCall( Statement * stmt ); 40 /// True if stmt is a call statement where the function called is intrinsic and takes one parameter. 41 /// Intended to be used for default ctor/dtor calls, but might have use elsewhere. 42 /// Currently has assertions that make it less than fully general. 43 bool isInstrinsicSingleArgCallStmt( Statement * expr ); 44 44 45 /// returns the name of the function being called 46 std::string getFunctionName( Expression * expr);45 /// get all Ctor/Dtor call expressions from a Statement 46 void collectCtorDtorCalls( Statement * stmt, std::list< Expression * > & matches ); 47 47 48 /// returns the argument to a call expression in position N indexed from 0 49 Expression *& getCallArg( Expression * callExpr, unsigned int pos);48 /// get the Ctor/Dtor call expression from a Statement that looks like a generated ctor/dtor call 49 Expression * getCtorDtorCall( Statement * stmt ); 50 50 51 /// returns the base type of a PointerType or ArrayType, else returns NULL 52 Type * getPointerBase( Type *);51 /// returns the name of the function being called 52 std::string getFunctionName( Expression * expr ); 53 53 54 /// returns the argument if it is a PointerType or ArrayType, else returns NULL 55 Type * isPointerType( Type * ); 54 /// returns the argument to a call expression in position N indexed from 0 55 Expression *& getCallArg( Expression * callExpr, unsigned int pos ); 56 57 /// returns the base type of a PointerType or ArrayType, else returns NULL 58 Type * getPointerBase( Type * ); 59 60 /// returns the argument if it is a PointerType or ArrayType, else returns NULL 61 Type * isPointerType( Type * ); 62 63 /// returns true if expr is trivially a compile-time constant 64 bool isConstExpr( Expression * expr ); 65 bool isConstExpr( Initializer * init ); 66 67 class InitExpander { 68 public: 69 // expand by stepping through init to get each list of arguments 70 InitExpander( Initializer * init ); 71 72 // always expand to expr 73 InitExpander( Expression * expr ); 74 75 // iterator-like interface 76 std::list< Expression * > operator*(); 77 InitExpander & operator++(); 78 79 // builds statement which has the same semantics as a C-style list initializer 80 // (for array initializers) using callExpr as the base expression to perform initialization 81 Statement * buildListInit( UntypedExpr * callExpr ); 82 void addArrayIndex( Expression * index, Expression * dimension ); 83 void clearArrayIndices(); 84 85 class ExpanderImpl; 86 private: 87 std::shared_ptr< ExpanderImpl > expander; 88 std::list< Expression * > cur; 89 90 // invariant: list of size 2N (elements come in pairs [index, dimension]) 91 typedef std::list< Expression * > IndexList; 92 IndexList indices; 93 }; 56 94 } // namespace 57 95 -
src/ResolvExpr/Resolver.cc
raea7168 r73bf8cf2 24 24 #include "SynTree/Initializer.h" 25 25 #include "SymTab/Indexer.h" 26 #include "SymTab/Autogen.h" 26 27 #include "Common/utility.h" 27 28 #include "InitTweak/InitTweak.h" … … 41 42 42 43 virtual void visit( ArrayType * at ); 44 virtual void visit( PointerType * at ); 43 45 44 46 virtual void visit( ExprStmt *exprStmt ); … … 52 54 virtual void visit( BranchStmt *branchStmt ); 53 55 virtual void visit( ReturnStmt *returnStmt ); 54 virtual void visit( ImplicitCtorDtorStmt * impCtorDtorStmt );55 56 56 57 virtual void visit( SingleInit *singleInit ); … … 59 60 private: 60 61 typedef std::list< Initializer * >::iterator InitIterator; 62 63 template< typename PtrType > 64 void handlePtrType( PtrType * type ); 61 65 62 66 void resolveAggrInit( AggregateDecl *, InitIterator &, InitIterator & ); … … 192 196 } 193 197 198 template< typename PtrType > 199 void Resolver::handlePtrType( PtrType * type ) { 200 if ( type->get_dimension() ) { 201 CastExpr *castExpr = new CastExpr( type->get_dimension(), SymTab::SizeType->clone() ); 202 Expression *newExpr = findSingleExpression( castExpr, *this ); 203 delete type->get_dimension(); 204 type->set_dimension( newExpr ); 205 } 206 } 207 194 208 void Resolver::visit( ArrayType * at ) { 195 if ( at->get_dimension() ) { 196 BasicType arrayLenType = BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ); 197 CastExpr *castExpr = new CastExpr( at->get_dimension(), arrayLenType.clone() ); 198 Expression *newExpr = findSingleExpression( castExpr, *this ); 199 delete at->get_dimension(); 200 at->set_dimension( newExpr ); 201 } 209 handlePtrType( at ); 202 210 Visitor::visit( at ); 211 } 212 213 void Resolver::visit( PointerType * pt ) { 214 handlePtrType( pt ); 215 Visitor::visit( pt ); 203 216 } 204 217 … … 422 435 423 436 void Resolver::visit( ListInit * listInit ) { 424 InitIterator iter = listInit->begin _initializers();425 InitIterator end = listInit->end _initializers();437 InitIterator iter = listInit->begin(); 438 InitIterator end = listInit->end(); 426 439 427 440 if ( ArrayType * at = dynamic_cast< ArrayType * >( initContext ) ) { … … 525 538 ctorInit->set_ctor( NULL ); 526 539 } 527 if ( InitTweak::isInstrinsicSingleArgCallStmt( ctorInit->get_ ctor() ) ) {540 if ( InitTweak::isInstrinsicSingleArgCallStmt( ctorInit->get_dtor() ) ) { 528 541 delete ctorInit->get_dtor(); 529 542 ctorInit->set_dtor( NULL ); 530 543 } 531 }532 533 void Resolver::visit( ImplicitCtorDtorStmt * impCtorDtorStmt ) {534 // before resolving ctor/dtor, need to remove type qualifiers from the first argument (the object being constructed).535 // Do this through a cast expression to greatly simplify the code.536 Expression * callExpr = InitTweak::getCtorDtorCall( impCtorDtorStmt );537 assert( callExpr );538 Expression *& constructee = InitTweak::getCallArg( callExpr, 0 );539 Type * type = 0;540 541 // need to find the type of the first argument, which is unfortunately not uniform since array construction542 // includes an untyped '+' expression.543 if ( UntypedExpr * plusExpr = dynamic_cast< UntypedExpr * >( constructee ) ) {544 // constructee is <array>+<index>545 // get Variable <array>, then get the base type of the VariableExpr - this is the type that needs to be fixed546 Expression * arr = InitTweak::getCallArg( plusExpr, 0 );547 assert( dynamic_cast< VariableExpr * >( arr ) || dynamic_cast< MemberExpr *>( arr ) );548 assert( arr && arr->get_results().size() == 1 );549 type = arr->get_results().front()->clone();550 } else {551 // otherwise, constructing a plain object, which means the object's address is being taken.552 // Need to get the type of the VariableExpr object, because the AddressExpr is rebuilt and uses the553 // type of the VariableExpr to do so.554 assert( constructee->get_results().size() == 1 );555 AddressExpr * addrExpr = dynamic_cast< AddressExpr * > ( constructee );556 assert( addrExpr && addrExpr->get_results().size() == 1 );557 type = addrExpr->get_results().front()->clone();558 }559 // cast to T* with qualifiers removed.560 // unfortunately, lvalue is considered a qualifier. For AddressExpr to resolve, its argument561 // must have an lvalue qualified type, so remove all qualifiers except lvalue. If we ever562 // remove lvalue as a qualifier, this can change to563 // type->get_qualifiers() = Type::Qualifiers();564 Type * base = InitTweak::getPointerBase( type );565 assert( base );566 base->get_qualifiers() -= Type::Qualifiers(true, true, true, false, true, true);567 // if pointer has lvalue qualifier, cast won't appear in output568 type->set_isLvalue( false );569 constructee = new CastExpr( constructee, type );570 571 // finally, resolve the ctor/dtor572 impCtorDtorStmt->get_callStmt()->accept( *this );573 544 } 574 545 } // namespace ResolvExpr -
src/SymTab/Autogen.cc
raea7168 r73bf8cf2 26 26 27 27 namespace SymTab { 28 Type * SizeType = 0; 29 28 30 class AutogenerateRoutines : public Visitor { 29 31 public: … … 59 61 bool isUnnamedBitfield( ObjectDecl * obj ) { 60 62 return obj != NULL && obj->get_name() == "" && obj->get_bitfieldWidth() != NULL; 61 }62 63 template< typename OutputIterator >64 void makeScalarFunction( Expression *src, ObjectDecl *dstParam, DeclarationWithType *member, std::string fname, OutputIterator out ) {65 ObjectDecl *obj = dynamic_cast<ObjectDecl *>( member );66 // unnamed bit fields are not copied as they cannot be accessed67 if ( isUnnamedBitfield( obj ) ) return;68 69 // want to be able to generate assignment, ctor, and dtor generically,70 // so fname is either ?=?, ?{}, or ^?{}71 UntypedExpr *fExpr = new UntypedExpr( new NameExpr( fname ) );72 73 UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );74 derefExpr->get_args().push_back( new VariableExpr( dstParam ) );75 76 // do something special for unnamed members77 Expression *dstselect = new AddressExpr( new MemberExpr( member, derefExpr ) );78 fExpr->get_args().push_back( dstselect );79 80 if ( src ) {81 fExpr->get_args().push_back( src );82 }83 84 Statement * callStmt = new ExprStmt( noLabels, fExpr );85 if ( (fname == "?{}" || fname == "^?{}") && ( !obj || ( obj && obj->get_bitfieldWidth() == NULL ) ) ) {86 // implicitly generated ctor/dtor calls should be wrapped87 // so that later passes are aware they were generated.88 // xxx - don't mark as an implicit ctor/dtor if obj is a bitfield,89 // because this causes the address to be taken at codegen, which is illegal in C.90 callStmt = new ImplicitCtorDtorStmt( callStmt );91 }92 *out++ = callStmt;93 63 } 94 64 … … 219 189 } 220 190 191 InitTweak::InitExpander srcParam( src ); 192 221 193 // assign to destination (and return value if generic) 222 if ( ArrayType *array = dynamic_cast< ArrayType * >( field->get_type() ) ) { 223 UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) ); 224 derefExpr->get_args().push_back( new VariableExpr( dstParam ) ); 225 Expression *dstselect = new MemberExpr( field, derefExpr ); 226 227 makeArrayFunction( src, dstselect, array, func->get_name(), back_inserter( func->get_statements()->get_kids() ), forward ); 228 if ( isGeneric && returnVal ) { 229 UntypedExpr *derefRet = new UntypedExpr( new NameExpr( "*?" ) ); 230 derefRet->get_args().push_back( new VariableExpr( returnVal ) ); 231 Expression *retselect = new MemberExpr( field, derefRet ); 232 233 makeArrayFunction( src, retselect, array, func->get_name(), back_inserter( func->get_statements()->get_kids() ), forward ); 234 } 235 } else { 236 makeScalarFunction( src, dstParam, field, func->get_name(), back_inserter( func->get_statements()->get_kids() ) ); 237 if ( isGeneric && returnVal ) makeScalarFunction( src, returnVal, field, func->get_name(), back_inserter( func->get_statements()->get_kids() ) ); 194 UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) ); 195 derefExpr->get_args().push_back( new VariableExpr( dstParam ) ); 196 Expression *dstselect = new MemberExpr( field, derefExpr ); 197 genImplicitCall( srcParam, dstselect, func->get_name(), back_inserter( func->get_statements()->get_kids() ), field, forward ); 198 199 if ( isGeneric && returnVal ) { 200 UntypedExpr *derefRet = new UntypedExpr( new NameExpr( "*?" ) ); 201 derefRet->get_args().push_back( new VariableExpr( returnVal ) ); 202 Expression *retselect = new MemberExpr( field, derefRet ); 203 genImplicitCall( srcParam, retselect, func->get_name(), back_inserter( func->get_statements()->get_kids() ), field, forward ); 238 204 } // if 239 205 } -
src/SymTab/Autogen.h
raea7168 r73bf8cf2 22 22 #include "SynTree/Declaration.h" 23 23 #include "SynTree/Initializer.h" 24 #include "InitTweak/InitTweak.h" 24 25 25 26 namespace SymTab { 26 27 27 /// Generates assignment operators, constructors, and destructor for aggregate types as required 28 void autogenerateRoutines( std::list< Declaration * > &translationUnit ); 28 29 29 // originally makeArrayAssignment - changed to Function because it is now used for ctors and dtors as well 30 // admittedly not a great name change. This used to live in Validate.cc, but has been moved so it can be reused elsewhere 30 /// returns true if obj's name is the empty string and it has a bitfield width 31 bool isUnnamedBitfield( ObjectDecl * obj ); 31 32 32 /// Store in out a loop which calls fname on each element of the array with srcParam and dstParam as arguments. 33 /// If forward is true, loop goes from 0 to N-1, else N-1 to 0 34 template< typename OutputIterator > 35 void makeArrayFunction( Expression *srcParam, Expression *dstParam, ArrayType *array, std::string fname, OutputIterator out, bool forward = true ) { 36 static UniqueName indexName( "_index" ); 33 /// size_t type - set when size_t typedef is seen. Useful in a few places, 34 /// such as in determining array dimension type 35 extern Type * SizeType; 37 36 38 // for a flexible array member nothing is done -- user must define own assignment 39 if ( ! array->get_dimension() ) return; 37 /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls. 38 template< typename OutputIterator > 39 void genCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast = false, bool forward = true ); 40 40 41 Expression * begin, * end, * update, * cmp; 42 if ( forward ) { 43 // generate: for ( int i = 0; i < 0; ++i ) 44 begin = new NameExpr( "0" ); 45 end = array->get_dimension()->clone(); 46 cmp = new NameExpr( "?<?" ); 47 update = new NameExpr( "++?" ); 48 } else { 49 // generate: for ( int i = N-1; i >= 0; --i ) 50 begin = new UntypedExpr( new NameExpr( "?-?" ) ); 51 ((UntypedExpr*)begin)->get_args().push_back( array->get_dimension()->clone() ); 52 ((UntypedExpr*)begin)->get_args().push_back( new NameExpr( "1" ) ); 53 end = new NameExpr( "0" ); 54 cmp = new NameExpr( "?>=?" ); 55 update = new NameExpr( "--?" ); 41 /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Should only be called with non-array types. 42 template< typename OutputIterator > 43 void genScalarCall( InitTweak::InitExpander & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast = false ) { 44 // want to be able to generate assignment, ctor, and dtor generically, 45 // so fname is either ?=?, ?{}, or ^?{} 46 UntypedExpr *fExpr = new UntypedExpr( new NameExpr( fname ) ); 47 48 // do something special for unnamed members 49 dstParam = new AddressExpr( dstParam ); 50 if ( addCast ) { 51 // cast to T* with qualifiers removed, so that qualified objects can be constructed 52 // and destructed with the same functions as non-qualified objects. 53 // unfortunately, lvalue is considered a qualifier. For AddressExpr to resolve, its argument 54 // must have an lvalue qualified type, so remove all qualifiers except lvalue. If we ever 55 // remove lvalue as a qualifier, this can change to 56 // type->get_qualifiers() = Type::Qualifiers(); 57 assert( type ); 58 Type * castType = type->clone(); 59 castType->get_qualifiers() -= Type::Qualifiers(true, true, true, false, true, true); 60 castType->set_isLvalue( true ); // xxx - might not need this 61 dstParam = new CastExpr( dstParam, new PointerType( Type::Qualifiers(), castType ) ); 62 } 63 fExpr->get_args().push_back( dstParam ); 64 65 Statement * listInit = srcParam.buildListInit( fExpr ); 66 if ( listInit ) { 67 *out++ = listInit; 56 68 } 57 69 58 ObjectDecl *index = new ObjectDecl( indexName.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), NULL ); 70 std::list< Expression * > args = *++srcParam; 71 fExpr->get_args().splice( fExpr->get_args().end(), args ); 59 72 60 UntypedExpr *init = new UntypedExpr( new NameExpr( "?=?" ) ); 61 init->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) ); 62 init->get_args().push_back( begin ); 63 index->set_init( new SingleInit( init, std::list<Expression*>() ) ); 73 *out++ = new ExprStmt( noLabels, fExpr ); 64 74 65 UntypedExpr *cond = new UntypedExpr( cmp ); 66 cond->get_args().push_back( new VariableExpr( index ) ); 67 cond->get_args().push_back( end ); 75 srcParam.clearArrayIndices(); 76 } 68 77 69 UntypedExpr *inc = new UntypedExpr( update ); 70 inc->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) ); 78 /// Store in out a loop which calls fname on each element of the array with srcParam and dstParam as arguments. 79 /// If forward is true, loop goes from 0 to N-1, else N-1 to 0 80 template< typename OutputIterator > 81 void genArrayCall( InitTweak::InitExpander & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, ArrayType *array, bool addCast = false, bool forward = true ) { 82 static UniqueName indexName( "_index" ); 71 83 72 // want to be able to generate assignment, ctor, and dtor generically, 73 // so fname is either ?=?, ?{}, or ^?{} 74 UntypedExpr *fExpr = new UntypedExpr( new NameExpr( fname ) ); 84 // for a flexible array member nothing is done -- user must define own assignment 85 if ( ! array->get_dimension() ) return ; 75 86 76 UntypedExpr *dstIndex = new UntypedExpr( new NameExpr( "?+?" ) ); 77 dstIndex->get_args().push_back( dstParam ); 78 dstIndex->get_args().push_back( new VariableExpr( index ) ); 79 fExpr->get_args().push_back( dstIndex ); 87 Expression * begin, * end, * update, * cmp; 88 if ( forward ) { 89 // generate: for ( int i = 0; i < 0; ++i ) 90 begin = new NameExpr( "0" ); 91 end = array->get_dimension()->clone(); 92 cmp = new NameExpr( "?<?" ); 93 update = new NameExpr( "++?" ); 94 } else { 95 // generate: for ( int i = N-1; i >= 0; --i ) 96 begin = new UntypedExpr( new NameExpr( "?-?" ) ); 97 ((UntypedExpr*)begin)->get_args().push_back( array->get_dimension()->clone() ); 98 ((UntypedExpr*)begin)->get_args().push_back( new NameExpr( "1" ) ); 99 end = new NameExpr( "0" ); 100 cmp = new NameExpr( "?>=?" ); 101 update = new NameExpr( "--?" ); 102 } 80 103 81 // srcParam is NULL for default ctor/dtor 82 if ( srcParam ) { 83 UntypedExpr *srcIndex = new UntypedExpr( new NameExpr( "?[?]" ) ); 84 srcIndex->get_args().push_back( srcParam ); 85 srcIndex->get_args().push_back( new VariableExpr( index ) ); 86 fExpr->get_args().push_back( srcIndex ); 104 ObjectDecl *index = new ObjectDecl( indexName.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), NULL ); 105 106 UntypedExpr *init = new UntypedExpr( new NameExpr( "?=?" ) ); 107 init->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) ); 108 init->get_args().push_back( begin ); 109 index->set_init( new SingleInit( init, std::list<Expression*>() ) ); 110 111 UntypedExpr *cond = new UntypedExpr( cmp ); 112 cond->get_args().push_back( new VariableExpr( index ) ); 113 cond->get_args().push_back( end ); 114 115 UntypedExpr *inc = new UntypedExpr( update ); 116 inc->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) ); 117 118 UntypedExpr *dstIndex = new UntypedExpr( new NameExpr( "?[?]" ) ); 119 dstIndex->get_args().push_back( dstParam ); 120 dstIndex->get_args().push_back( new VariableExpr( index ) ); 121 dstParam = dstIndex; 122 123 // srcParam must keep track of the array indices to build the 124 // source parameter and/or array list initializer 125 srcParam.addArrayIndex( new VariableExpr( index ), array->get_dimension()->clone() ); 126 127 // if ( srcParam ) { 128 // UntypedExpr *srcIndex = new UntypedExpr( new NameExpr( "?[?]" ) ); 129 // srcIndex->get_args().push_back( srcParam ); 130 // srcIndex->get_args().push_back( new VariableExpr( index ) ); 131 // srcParam = srcIndex; 132 // } 133 134 // for stmt's body, eventually containing call 135 CompoundStmt * body = new CompoundStmt( noLabels ); 136 genCall( srcParam, dstParam, fname, back_inserter( body->get_kids() ), array->get_base(), addCast, forward ); 137 138 // block containing for stmt and index variable 139 std::list<Statement *> initList; 140 CompoundStmt * block = new CompoundStmt( noLabels ); 141 block->get_kids().push_back( new DeclStmt( noLabels, index ) ); 142 block->get_kids().push_back( new ForStmt( noLabels, initList, cond, inc, body ) ); 143 144 *out++ = block; 145 } 146 147 template< typename OutputIterator > 148 void genCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast, bool forward ) { 149 if ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) { 150 genArrayCall( srcParam, dstParam, fname, out, at, addCast, forward ); 151 } else { 152 genScalarCall( srcParam, dstParam, fname, out, type, addCast ); 153 } 154 } 155 156 /// inserts into out a generated call expression to function fname with arguments dstParam 157 /// and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls. decl is the 158 /// object being constructed. The function wraps constructor and destructor calls in an 159 /// ImplicitCtorDtorStmt node. 160 template< typename OutputIterator > 161 void genImplicitCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, DeclarationWithType * decl, bool forward = true ) { 162 ObjectDecl *obj = dynamic_cast<ObjectDecl *>( decl ); 163 assert( obj ); 164 // unnamed bit fields are not copied as they cannot be accessed 165 if ( isUnnamedBitfield( obj ) ) return; 166 167 bool addCast = (fname == "?{}" || fname == "^?{}") && ( !obj || ( obj && obj->get_bitfieldWidth() == NULL ) ); 168 std::list< Statement * > stmts; 169 genCall( srcParam, dstParam, fname, back_inserter( stmts ), obj->get_type(), addCast, forward ); 170 171 // currently genCall should produce at most one element, but if that changes then the next line needs to be updated to grab the statement which contains the call 172 assert( stmts.size() <= 1 ); 173 if ( stmts.size() == 1 ) { 174 Statement * callStmt = stmts.front(); 175 if ( addCast ) { 176 // implicitly generated ctor/dtor calls should be wrapped 177 // so that later passes are aware they were generated. 178 // xxx - don't mark as an implicit ctor/dtor if obj is a bitfield, 179 // because this causes the address to be taken at codegen, which is illegal in C. 180 callStmt = new ImplicitCtorDtorStmt( callStmt ); 181 } 182 *out++ = callStmt; 87 183 } 88 89 std::list<Statement *> initList; 90 CompoundStmt * block = new CompoundStmt( noLabels ); 91 block->get_kids().push_back( new DeclStmt( noLabels, index ) ); 92 block->get_kids().push_back( new ForStmt( noLabels, initList, cond, inc, new ExprStmt( noLabels, fExpr ) ) ); 93 94 Statement * stmt = block; 95 if ( fname == "?{}" || fname == "^?{}" ) { 96 // implicitly generated ctor/dtor calls should be wrapped 97 // so that later passes are aware they were generated 98 stmt = new ImplicitCtorDtorStmt( stmt ); 99 } 100 *out++ = stmt; 101 } 184 } 102 185 } // namespace SymTab 103 186 #endif // AUTOGEN_H -
src/SymTab/FixFunction.cc
raea7168 r73bf8cf2 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // FixFunction.cc -- 7 // FixFunction.cc -- 8 8 // 9 9 // Author : Richard C. Bilson … … 44 44 45 45 Type * FixFunction::mutate(ArrayType *arrayType) { 46 PointerType *pointerType = new PointerType( arrayType->get_qualifiers(), maybeClone( arrayType->get_base()->clone() ), maybeClone( arrayType->get_dimension() ), arrayType->get_isVarLen(), arrayType->get_isStatic() ); 46 // need to recursively mutate the base type in order for multi-dimensional arrays to work. 47 PointerType *pointerType = new PointerType( arrayType->get_qualifiers(), arrayType->get_base()->clone()->acceptMutator( *this ), maybeClone( arrayType->get_dimension() ), arrayType->get_isVarLen(), arrayType->get_isStatic() ); 47 48 delete arrayType; 48 49 return pointerType; -
src/SymTab/Validate.cc
raea7168 r73bf8cf2 174 174 175 175 virtual void visit( FunctionDecl *funcDecl ); 176 };176 }; 177 177 178 178 class CompoundLiteral : public GenPoly::DeclMutator { … … 191 191 EliminateTypedef::eliminateTypedef( translationUnit ); 192 192 HoistStruct::hoistStruct( translationUnit ); 193 autogenerateRoutines( translationUnit ); // moved up, used to be below compoundLiteral - currently needs Pass1 193 194 acceptAll( translationUnit, pass1 ); 194 195 acceptAll( translationUnit, pass2 ); 195 196 ReturnChecker::checkFunctionReturns( translationUnit ); 196 mutateAll( translationUnit, compoundliteral ); 197 autogenerateRoutines( translationUnit ); 197 compoundliteral.mutateDeclarationList( translationUnit ); 198 198 acceptAll( translationUnit, pass3 ); 199 199 VerifyCtorDtor::verify( translationUnit ); … … 490 490 EliminateTypedef eliminator; 491 491 mutateAll( translationUnit, eliminator ); 492 if ( eliminator.typedefNames.count( "size_t" ) ) { 493 // grab and remember declaration of size_t 494 SizeType = eliminator.typedefNames["size_t"].first->get_base()->clone(); 495 } else { 496 // xxx - missing global typedef for size_t - default to long unsigned int, even though that may be wrong 497 // eventually should have a warning for this case. 498 SizeType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ); 499 } 492 500 filter( translationUnit, isTypedef, true ); 501 493 502 } 494 503 … … 518 527 Declaration *EliminateTypedef::mutate( TypedefDecl * tyDecl ) { 519 528 Declaration *ret = Mutator::mutate( tyDecl ); 529 520 530 if ( typedefNames.count( tyDecl->get_name() ) == 1 && typedefNames[ tyDecl->get_name() ].second == scopeLevel ) { 521 531 // typedef to the same name from the same scope -
src/SynTree/Expression.cc
raea7168 r73bf8cf2 344 344 } 345 345 346 //// is this right? It's cloning the member, but the member is a declaration so probably shouldn't be cloned... 346 347 MemberExpr::MemberExpr( const MemberExpr &other ) : 347 Expression( other ), member( maybeClone( other.member )), aggregate( maybeClone( other.aggregate ) ) {348 Expression( other ), member( other.member ), aggregate( maybeClone( other.aggregate ) ) { 348 349 } 349 350 350 351 MemberExpr::~MemberExpr() { 351 delete member;352 // delete member; 352 353 delete aggregate; 353 354 } -
src/SynTree/Initializer.h
raea7168 r73bf8cf2 93 93 std::list<Initializer*> &get_initializers() { return initializers; } 94 94 95 std::list<Initializer*>::iterator begin_initializers() { return initializers.begin(); } 96 std::list<Initializer*>::iterator end_initializers() { return initializers.end(); } 95 typedef std::list<Initializer*>::iterator iterator; 96 iterator begin() { return initializers.begin(); } 97 iterator end() { return initializers.end(); } 97 98 98 99 virtual ListInit *clone() const { return new ListInit( *this ); } -
src/main.cc
raea7168 r73bf8cf2 42 42 #include "InitTweak/GenInit.h" 43 43 #include "InitTweak/FixInit.h" 44 #include "InitTweak/FixGlobalInit.h"45 44 //#include "Explain/GenProlog.h" 46 45 //#include "Try/Visit.h" … … 282 281 OPTPRINT( "fixNames" ) 283 282 CodeGen::fixNames( translationUnit ); 284 OPTPRINT( "fixGlobalInit" );285 InitTweak::fixGlobalInit( translationUnit, filename, libcfap || treep );286 283 OPTPRINT( "tweakInit" ) 287 284 InitTweak::genInit( translationUnit ); … … 304 301 } 305 302 303 // fix ObjectDecl - replaces ConstructorInit nodes 306 304 OPTPRINT( "fixInit" ) 307 // fix ObjectDecl - replaces ConstructorInit nodes 308 InitTweak::fix( translationUnit ); 305 InitTweak::fix( translationUnit, filename, libcfap || treep ); 309 306 if ( ctorinitp ) { 310 307 dump ( translationUnit ); -
src/tests/.expect/64/extension.txt
raea7168 r73bf8cf2 100 100 ((void)((__extension__ __a__i_2 , __extension__ __b__i_2) , __extension__ __c__i_2)); 101 101 } 102 __attribute__ ((constructor(),)) static void _init_extension(void){103 int _global_init0;104 ((void)((*((int *)(&__a__i_1)))=_global_init0) /* ?{} */);105 int _global_init1;106 ((void)((*((int *)(&__b__i_1)))=_global_init1) /* ?{} */);107 int _global_init2;108 ((void)((*((int *)(&__c__i_1)))=_global_init2) /* ?{} */);109 }110 __attribute__ ((destructor(),)) static void _destroy_extension(void){111 ((void)((*((int *)(&__c__i_1)))) /* ^?{} */);112 ((void)((*((int *)(&__b__i_1)))) /* ^?{} */);113 ((void)((*((int *)(&__a__i_1)))) /* ^?{} */);114 } -
src/tests/init_once.c
raea7168 r73bf8cf2 92 92 init_once y = x; 93 93 94 void static_variable() { 95 static init_once x; 96 } 97 94 98 int main() { 95 99 // local variables … … 179 183 } 180 184 } 185 186 // function-scoped static variable 187 for (int i = 0; i < 10; i++) { 188 static_variable(); 189 } 181 190 } 182 191
Note:
See TracChangeset
for help on using the changeset viewer.