Changes in / [1b0020a:dae881f]
- Location:
- src
- Files:
-
- 2 deleted
- 26 edited
-
CodeGen/CodeGenerator.cc (modified) (2 diffs)
-
GenPoly/DeclMutator.h (modified) (2 diffs)
-
GenPoly/Specialize.cc (modified) (2 diffs)
-
InitTweak/FixGlobalInit.cc (modified) (3 diffs)
-
InitTweak/FixInit.cc (modified) (11 diffs)
-
InitTweak/FixInit.h (modified) (1 diff)
-
InitTweak/GenInit.cc (modified) (5 diffs)
-
InitTweak/InitTweak.cc (modified) (7 diffs)
-
InitTweak/InitTweak.h (modified) (1 diff)
-
Parser/TypeData.cc (modified) (1 diff)
-
ResolvExpr/Resolver.cc (modified) (7 diffs)
-
SymTab/Autogen.cc (modified) (3 diffs)
-
SymTab/Autogen.h (modified) (1 diff)
-
SymTab/FixFunction.cc (modified) (2 diffs)
-
SymTab/Validate.cc (modified) (4 diffs)
-
SynTree/Declaration.cc (modified) (2 diffs)
-
SynTree/Declaration.h (modified) (6 diffs)
-
SynTree/DeclarationWithType.cc (modified) (1 diff)
-
SynTree/Expression.cc (modified) (1 diff)
-
SynTree/FunctionDecl.cc (modified) (4 diffs)
-
SynTree/Initializer.h (modified) (1 diff)
-
SynTree/Label.h (modified) (1 diff)
-
SynTree/ObjectDecl.cc (modified) (3 diffs)
-
main.cc (modified) (3 diffs)
-
tests/.expect/64/extension.txt (modified) (1 diff)
-
tests/.expect/multiDimension.txt (deleted)
-
tests/init_once.c (modified) (2 diffs)
-
tests/multiDimension.c (deleted)
Legend:
- Unmodified
- Added
- Removed
-
src/CodeGen/CodeGenerator.cc
r1b0020a rdae881f 148 148 void CodeGenerator::visit( ObjectDecl * objectDecl ) { 149 149 extension( objectDecl ); 150 genAttributes( objectDecl->get_attributes() );151 152 150 handleStorageClass( objectDecl ); 153 151 output << genType( objectDecl->get_type(), mangleName( objectDecl ) ); … … 273 271 printDesignators( init->get_designators() ); 274 272 output << "{ "; 275 if ( init->begin () == init->end() ) {273 if ( init->begin_initializers() == init->end_initializers() ) { 276 274 // illegal to leave initializer list empty for scalar initializers, but always legal to have 0 277 275 output << "0"; 278 276 } else { 279 genCommaList( init->begin (), init->end() );277 genCommaList( init->begin_initializers(), init->end_initializers() ); 280 278 } // if 281 279 output << " }"; -
src/GenPoly/DeclMutator.h
r1b0020a rdae881f 28 28 class DeclMutator : public Mutator { 29 29 public: 30 typedef Mutator Parent;31 32 30 DeclMutator(); 33 31 virtual ~DeclMutator(); 34 35 using Parent::mutate; 32 36 33 virtual CompoundStmt* mutate(CompoundStmt *compoundStmt); 37 34 virtual Statement* mutate(IfStmt *ifStmt); … … 45 42 /// Mutates a list of declarations with this visitor 46 43 void mutateDeclarationList(std::list< Declaration* >& decls); 47 44 48 45 /// Called on entry to a new scope; overriders should call this as a super-class call 49 46 virtual void doBeginScope(); -
src/GenPoly/Specialize.cc
r1b0020a rdae881f 31 31 #include "Common/UniqueName.h" 32 32 #include "Common/utility.h" 33 #include "InitTweak/InitTweak.h"34 33 35 34 namespace GenPoly { … … 185 184 mutateAll( appExpr->get_args(), *this ); 186 185 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 } 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 ); 196 192 197 193 return appExpr; -
src/InitTweak/FixGlobalInit.cc
r1b0020a rdae881f 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 } // if 88 // for all intents and purposes, no initializer means const expr 89 return true; 90 } 48 91 49 92 void fixGlobalInit( std::list< Declaration * > & translationUnit, const std::string & name, bool inLibrary ) { … … 97 140 std::list< Statement * > & destroyStatements = destroyFunction->get_statements()->get_kids(); 98 141 142 if ( ! tryConstruct( objDecl ) ) return; // don't construct @= or designated objects 143 if ( objDecl->get_storageClass() == DeclarationNode::Extern ) return; 99 144 // C allows you to initialize objects with constant expressions 100 145 // xxx - this is an optimization. Need to first resolve constructors before we decide … … 102 147 // if ( isConstExpr( objDecl->get_init() ) ) return; 103 148 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() ); 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 ) ); 107 156 108 Statement * dtor = ctorInit->get_dtor(); 109 if ( dtor && ! isIntrinsicSingleArgCallStmt( 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; 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 ) ) ); 127 167 } // if 128 168 } -
src/InitTweak/FixInit.cc
r1b0020a rdae881f 18 18 #include <iterator> 19 19 #include <algorithm> 20 #include "FixInit.h" 20 21 #include "InitTweak.h" 21 #include "FixInit.h"22 #include "FixGlobalInit.h"23 22 #include "ResolvExpr/Resolver.h" 24 23 #include "ResolvExpr/typeops.h" … … 26 25 #include "SynTree/Type.h" 27 26 #include "SynTree/Expression.h" 28 #include "SynTree/Attribute.h"29 27 #include "SynTree/Statement.h" 30 28 #include "SynTree/Initializer.h" … … 85 83 }; 86 84 87 // debug88 85 struct printSet { 89 86 typedef ObjDeclCollector::ObjectSet ObjectSet; … … 162 159 163 160 virtual DeclarationWithType * mutate( ObjectDecl *objDecl ); 164 165 std::list< Declaration * > staticDtorDecls;166 161 }; 167 162 … … 176 171 } // namespace 177 172 178 void fix( std::list< Declaration * > & translationUnit, const std::string & filename, bool inLibrary ) { 179 // fixes ConstructorInit for global variables. should happen before fixInitializers. 180 InitTweak::fixGlobalInit( translationUnit, filename, inLibrary ); 181 173 void fix( std::list< Declaration * > & translationUnit ) { 182 174 InsertImplicitCalls::insert( translationUnit ); 183 175 ResolveCopyCtors::resolveImplicitCalls( translationUnit ); … … 202 194 void FixInit::fixInitializers( std::list< Declaration * > & translationUnit ) { 203 195 FixInit fixer; 204 205 // can't use mutateAll, because need to insert declarations at top-level 206 // can't use DeclMutator, because sometimes need to insert IfStmt, etc. 207 SemanticError errors; 208 for ( std::list< Declaration * >::iterator i = translationUnit.begin(); i != translationUnit.end(); ++i ) { 209 try { 210 *i = maybeMutate( *i, fixer ); 211 translationUnit.splice( i, fixer.staticDtorDecls ); 212 } catch( SemanticError &e ) { 213 errors.append( e ); 214 } // try 215 } // for 216 if ( ! errors.isEmpty() ) { 217 throw errors; 218 } // if 196 mutateAll( translationUnit, fixer ); 219 197 } 220 198 … … 444 422 if ( Statement * ctor = ctorInit->get_ctor() ) { 445 423 if ( objDecl->get_storageClass() == DeclarationNode::Static ) { 446 // originally wanted to take advantage of gcc nested functions, but447 // we get memory errors with this approach. To remedy this, the static448 // variable is hoisted when the destructor needs to be called.449 //450 424 // generate: 451 // static T __objName_static_varN; 452 // void __objName_dtor_atexitN() { 453 // __dtor__...; 425 // static bool __objName_uninitialized = true; 426 // if (__objName_uninitialized) { 427 // __ctor(__objName); 428 // void dtor_atexit() { 429 // __dtor(__objName); 430 // } 431 // on_exit(dtorOnExit, &__objName); 432 // __objName_uninitialized = false; 454 433 // } 455 // int f(...) { 456 // ... 457 // static bool __objName_uninitialized = true; 458 // if (__objName_uninitialized) { 459 // __ctor(__objName); 460 // __objName_uninitialized = false; 461 // atexit(__objName_dtor_atexitN); 462 // } 463 // ... 464 // } 465 466 static UniqueName dtorCallerNamer( "_dtor_atexit" ); 467 468 // static bool __objName_uninitialized = true 434 435 // generate first line 469 436 BasicType * boolType = new BasicType( Type::Qualifiers(), BasicType::Bool ); 470 437 SingleInit * boolInitExpr = new SingleInit( new ConstantExpr( Constant( boolType->clone(), "1" ) ), noDesignators ); … … 472 439 isUninitializedVar->fixUniqueId(); 473 440 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); 447 UntypedExpr * callAtexit = new UntypedExpr( new NameExpr( "atexit" ) ); 448 callAtexit->get_args().push_back( new VariableExpr( dtorCaller ) ); 449 474 450 // __objName_uninitialized = false; 475 451 UntypedExpr * setTrue = new UntypedExpr( new NameExpr( "?=?" ) ); … … 481 457 std::list< Statement * > & body = initStmts->get_kids(); 482 458 body.push_back( ctor ); 459 body.push_back( new DeclStmt( noLabels, dtorCaller ) ); 460 body.push_back( new ExprStmt( noLabels, callAtexit ) ); 483 461 body.push_back( new ExprStmt( noLabels, setTrue ) ); 484 462 … … 487 465 stmtsToAddAfter.push_back( new DeclStmt( noLabels, isUninitializedVar ) ); 488 466 stmtsToAddAfter.push_back( ifStmt ); 489 490 if ( ctorInit->get_dtor() ) {491 // if the object has a non-trivial destructor, have to492 // hoist it and the object into the global space and493 // call the destructor function with atexit.494 495 Statement * dtorStmt = ctorInit->get_dtor()->clone();496 497 // void __objName_dtor_atexitN(...) {...}498 FunctionDecl * dtorCaller = new FunctionDecl( objDecl->get_mangleName() + dtorCallerNamer.newName(), DeclarationNode::Static, LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt( noLabels ), false, false );499 dtorCaller->fixUniqueId();500 dtorCaller->get_statements()->get_kids().push_back( dtorStmt );501 502 // atexit(dtor_atexit);503 UntypedExpr * callAtexit = new UntypedExpr( new NameExpr( "atexit" ) );504 callAtexit->get_args().push_back( new VariableExpr( dtorCaller ) );505 506 body.push_back( new ExprStmt( noLabels, callAtexit ) );507 508 // hoist variable and dtor caller decls to list of decls that will be added into global scope509 staticDtorDecls.push_back( objDecl );510 staticDtorDecls.push_back( dtorCaller );511 512 // need to rename object uniquely since it now appears513 // at global scope and there could be multiple function-scoped514 // static variables with the same name in different functions.515 static UniqueName staticNamer( "_static_var" );516 objDecl->set_mangleName( objDecl->get_mangleName() + staticNamer.newName() );517 518 objDecl->set_init( NULL );519 ctorInit->set_ctor( NULL );520 delete ctorInit;521 522 // xxx - temporary hack: need to return a declaration, but want to hoist the current object out of this scope523 // create a new object which is never used524 static UniqueName dummyNamer( "_dummy" );525 ObjectDecl * dummy = new ObjectDecl( dummyNamer.newName(), DeclarationNode::Static, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), new VoidType( Type::Qualifiers() ) ), 0, std::list< Attribute * >{ new Attribute("unused") } );526 return dummy;527 }528 467 } else { 529 468 stmtsToAddAfter.push_back( ctor ); … … 585 524 assert( ! ctorInit->get_ctor() || ! ctorInit->get_init() ); 586 525 Statement * dtor = ctorInit->get_dtor(); 587 if ( dtor && ! isIn trinsicSingleArgCallStmt( dtor ) ) {526 if ( dtor && ! isInstrinsicSingleArgCallStmt( dtor ) ) { 588 527 // don't need to call intrinsic dtor, because it does nothing, but 589 528 // non-intrinsic dtors must be called -
src/InitTweak/FixInit.h
r1b0020a rdae881f 27 27 /// replace constructor initializers with expression statements 28 28 /// and unwrap basic C-style initializers 29 void fix( std::list< Declaration * > & translationUnit , const std::string & name, bool inLibrary);29 void fix( std::list< Declaration * > & translationUnit ); 30 30 } // namespace 31 31 -
src/InitTweak/GenInit.cc
r1b0020a rdae881f 26 26 #include "SymTab/Autogen.h" 27 27 #include "GenPoly/PolyMutator.h" 28 #include "GenPoly/DeclMutator.h"29 28 30 29 namespace InitTweak { … … 56 55 public: 57 56 /// create constructor and destructor statements for object declarations. 58 /// the actual call statements will be added in after the resolver has run59 /// so that the initializer expression is only removed if a constructor is found60 /// and the same destructor call is inserted in all of the appropriate locations.57 /// Destructors are inserted directly into the code, whereas constructors 58 /// will be added in after the resolver has run so that the initializer expression 59 /// is only removed if a constructor is found 61 60 static void generateCtorDtor( std::list< Declaration * > &translationUnit ); 61 62 CtorDtor() : inFunction( false ) {} 62 63 63 64 virtual DeclarationWithType * mutate( ObjectDecl * ); 64 65 virtual DeclarationWithType * mutate( FunctionDecl *functionDecl ); 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; } 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 ); 75 74 76 75 protected: 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; 76 bool inFunction; 106 77 }; 107 78 108 79 void genInit( std::list< Declaration * > & translationUnit ) { 109 80 ReturnFixer::makeReturnTemp( translationUnit ); 110 HoistArrayDimension::hoistArrayDimension( translationUnit );111 81 CtorDtor::generateCtorDtor( translationUnit ); 112 82 } … … 154 124 } 155 125 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 var173 static UniqueName dimensionName( "_array_dim" );174 175 // C doesn't allow variable sized arrays at global scope or for static variables,176 // so don't hoist dimension.177 if ( ! inFunction ) return;178 if ( storageclass == DeclarationNode::Static ) return;179 180 if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) {181 if ( ! arrayType->get_dimension() ) return; // xxx - recursive call to hoist?182 183 // don't need to hoist dimension if it's a constexpr - only need to if there's potential184 // for side effects.185 if ( isConstExpr( arrayType->get_dimension() ) ) return;186 187 ObjectDecl * arrayDimension = new ObjectDecl( dimensionName.newName(), storageclass, LinkageSpec::C, 0, SymTab::SizeType->clone(), new SingleInit( arrayType->get_dimension() ) );188 arrayDimension->get_type()->set_isConst( true );189 190 arrayType->set_dimension( new VariableExpr( arrayDimension ) );191 addDeclaration( arrayDimension );192 193 hoist( arrayType->get_base() );194 return;195 }196 }197 198 DeclarationWithType * HoistArrayDimension::mutate( FunctionDecl *functionDecl ) {199 bool oldInFunc = inFunction;200 inFunction = true;201 DeclarationWithType * decl = Parent::mutate( functionDecl );202 inFunction = oldInFunc;203 return decl;204 }205 126 206 127 void CtorDtor::generateCtorDtor( std::list< Declaration * > & translationUnit ) { … … 209 130 } 210 131 132 namespace { 133 Expression * makeCtorDtorExpr( std::string name, ObjectDecl * objDecl, std::list< Expression * > args ) { 134 UntypedExpr * expr = new UntypedExpr( new NameExpr( name ) ); 135 expr->get_args().push_back( new AddressExpr( new VariableExpr( objDecl ) ) ); 136 expr->get_args().splice( expr->get_args().end(), args ); 137 return expr; 138 } 139 } 140 211 141 DeclarationWithType * CtorDtor::mutate( ObjectDecl * objDecl ) { 212 // hands off if designated , if @=, or if extern142 // hands off if designated or if @= 213 143 if ( tryConstruct( objDecl ) ) { 214 // call into genImplicitCall from Autogen.h to generate calls to ctor/dtor 215 // for each constructable object 216 std::list< Statement * > ctor; 217 std::list< Statement * > dtor; 218 219 InitExpander srcParam( objDecl->get_init() ); 220 InitExpander nullParam( (Initializer *)NULL ); 221 SymTab::genImplicitCall( srcParam, new VariableExpr( objDecl ), "?{}", back_inserter( ctor ), objDecl ); 222 SymTab::genImplicitCall( nullParam, new VariableExpr( objDecl ), "^?{}", front_inserter( dtor ), objDecl, false ); 223 224 // Currently genImplicitCall produces a single Statement - a CompoundStmt 225 // which wraps everything that needs to happen. As such, it's technically 226 // possible to use a Statement ** in the above calls, but this is inherently 227 // unsafe, so instead we take the slightly less efficient route, but will be 228 // immediately informed if somehow the above assumption is broken. In this case, 229 // we could always wrap the list of statements at this point with a CompoundStmt, 230 // but it seems reasonable at the moment for this to be done by genImplicitCall 231 // itself. It is possible that genImplicitCall produces no statements (e.g. if 232 // an array type does not have a dimension). In this case, it's fine to ignore 233 // the object for the purposes of construction. 234 assert( ctor.size() == dtor.size() && ctor.size() <= 1 ); 235 if ( ctor.size() == 1 ) { 236 // need to remember init expression, in case no ctors exist 237 // if ctor does exist, want to use ctor expression instead of init 238 // push this decision to the resolver 239 assert( dynamic_cast< ImplicitCtorDtorStmt * > ( ctor.front() ) && dynamic_cast< ImplicitCtorDtorStmt * > ( dtor.front() ) ); 240 objDecl->set_init( new ConstructorInit( ctor.front(), dtor.front(), objDecl->get_init() ) ); 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 } 241 188 } 242 189 } … … 246 193 DeclarationWithType * CtorDtor::mutate( FunctionDecl *functionDecl ) { 247 194 // parameters should not be constructed and destructed, so don't mutate FunctionType 195 bool oldInFunc = inFunction; 248 196 mutateAll( functionDecl->get_oldDecls(), *this ); 197 inFunction = true; 249 198 functionDecl->set_statements( maybeMutate( functionDecl->get_statements(), *this ) ); 199 inFunction = oldInFunc; 250 200 return functionDecl; 251 201 } 202 203 // should not traverse into any of these declarations to find objects 204 // that need to be constructed or destructed 205 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 252 213 } // namespace InitTweak 253 214 -
src/InitTweak/InitTweak.cc
r1b0020a rdae881f 1 #include <algorithm>2 1 #include "InitTweak.h" 3 2 #include "SynTree/Visitor.h" … … 5 4 #include "SynTree/Initializer.h" 6 5 #include "SynTree/Expression.h" 7 #include "SynTree/Attribute.h"8 6 #include "GenPoly/GenPoly.h" 9 7 … … 22 20 }; 23 21 24 class Init Flattener : public Visitor {22 class InitExpander : public Visitor { 25 23 public: 24 InitExpander() {} 26 25 virtual void visit( SingleInit * singleInit ); 27 26 virtual void visit( ListInit * listInit ); … … 29 28 }; 30 29 31 void Init Flattener::visit( SingleInit * singleInit ) {30 void InitExpander::visit( SingleInit * singleInit ) { 32 31 argList.push_back( singleInit->get_value()->clone() ); 33 32 } 34 33 35 void Init Flattener::visit( ListInit * listInit ) {36 // flattennested list inits37 std::list<Initializer*>::iterator it = listInit->begin ();38 for ( ; it != listInit->end (); ++it ) {34 void InitExpander::visit( ListInit * listInit ) { 35 // xxx - for now, assume no nested list inits 36 std::list<Initializer*>::iterator it = listInit->begin_initializers(); 37 for ( ; it != listInit->end_initializers(); ++it ) { 39 38 (*it)->accept( *this ); 40 39 } … … 43 42 44 43 std::list< Expression * > makeInitList( Initializer * init ) { 45 Init Flattener flattener;46 maybeAccept( init, flattener );47 return flattener.argList;44 InitExpander expander; 45 maybeAccept( init, expander ); 46 return expander.argList; 48 47 } 49 48 … … 54 53 } 55 54 56 class InitExpander::ExpanderImpl {57 public:58 virtual std::list< Expression * > next( std::list< Expression * > & indices ) = 0;59 virtual Statement * buildListInit( UntypedExpr * callExpr, std::list< Expression * > & indices ) = 0;60 };61 62 class InitImpl : public InitExpander::ExpanderImpl {63 public:64 InitImpl( Initializer * init ) : init( init ) {}65 66 virtual std::list< Expression * > next( std::list< Expression * > & indices ) {67 // this is wrong, but just a placeholder for now68 // if ( ! flattened ) flatten( indices );69 // return ! inits.empty() ? makeInitList( inits.front() ) : std::list< Expression * >();70 return makeInitList( init );71 }72 73 virtual Statement * buildListInit( UntypedExpr * callExpr, std::list< Expression * > & indices );74 private:75 Initializer * init;76 };77 78 class ExprImpl : public InitExpander::ExpanderImpl {79 public:80 ExprImpl( Expression * expr ) : arg( expr ) {}81 82 virtual std::list< Expression * > next( std::list< Expression * > & indices ) {83 std::list< Expression * > ret;84 Expression * expr = maybeClone( arg );85 if ( expr ) {86 for ( std::list< Expression * >::reverse_iterator it = indices.rbegin(); it != indices.rend(); ++it ) {87 // go through indices and layer on subscript exprs ?[?]88 ++it;89 UntypedExpr * subscriptExpr = new UntypedExpr( new NameExpr( "?[?]") );90 subscriptExpr->get_args().push_back( expr );91 subscriptExpr->get_args().push_back( (*it)->clone() );92 expr = subscriptExpr;93 }94 ret.push_back( expr );95 }96 return ret;97 }98 99 virtual Statement * buildListInit( UntypedExpr * callExpr, std::list< Expression * > & indices );100 private:101 Expression * arg;102 };103 104 InitExpander::InitExpander( Initializer * init ) : expander( new InitImpl( init ) ) {}105 106 InitExpander::InitExpander( Expression * expr ) : expander( new ExprImpl( expr ) ) {}107 108 std::list< Expression * > InitExpander::operator*() {109 return cur;110 }111 112 InitExpander & InitExpander::operator++() {113 cur = expander->next( indices );114 return *this;115 }116 117 // use array indices list to build switch statement118 void InitExpander::addArrayIndex( Expression * index, Expression * dimension ) {119 indices.push_back( index );120 indices.push_back( dimension );121 }122 123 void InitExpander::clearArrayIndices() {124 indices.clear();125 }126 127 namespace {128 /// given index i, dimension d, initializer init, and callExpr f, generates129 /// if (i < d) f(..., init)130 /// ++i;131 /// so that only elements within the range of the array are constructed132 template< typename OutIterator >133 void buildCallExpr( UntypedExpr * callExpr, Expression * index, Expression * dimension, Initializer * init, OutIterator out ) {134 UntypedExpr * cond = new UntypedExpr( new NameExpr( "?<?") );135 cond->get_args().push_back( index->clone() );136 cond->get_args().push_back( dimension->clone() );137 138 std::list< Expression * > args = makeInitList( init );139 callExpr->get_args().splice( callExpr->get_args().end(), args );140 141 *out++ = new IfStmt( noLabels, cond, new ExprStmt( noLabels, callExpr ), NULL );142 143 UntypedExpr * increment = new UntypedExpr( new NameExpr( "++?" ) );144 increment->get_args().push_back( new AddressExpr( index->clone() ) );145 *out++ = new ExprStmt( noLabels, increment );146 }147 148 template< typename OutIterator >149 void build( UntypedExpr * callExpr, InitExpander::IndexList::iterator idx, InitExpander::IndexList::iterator idxEnd, Initializer * init, OutIterator out ) {150 if ( idx == idxEnd ) return;151 Expression * index = *idx++;152 assert( idx != idxEnd );153 Expression * dimension = *idx++;154 155 // xxx - may want to eventually issue a warning here if we can detect156 // that the number of elements exceeds to dimension of the array157 if ( idx == idxEnd ) {158 if ( ListInit * listInit = dynamic_cast< ListInit * >( init ) ) {159 for ( Initializer * init : *listInit ) {160 buildCallExpr( callExpr->clone(), index, dimension, init, out );161 }162 } else {163 buildCallExpr( callExpr->clone(), index, dimension, init, out );164 }165 } else {166 std::list< Statement * > branches;167 168 unsigned long cond = 0;169 ListInit * listInit = dynamic_cast< ListInit * >( init );170 if ( ! listInit ) {171 // xxx - this shouldn't be an error, but need a way to172 // terminate without creating output, so should catch this error173 throw SemanticError( "unbalanced list initializers" );174 }175 176 static UniqueName targetLabel( "L__autogen__" );177 Label switchLabel( targetLabel.newName(), 0, std::list< Attribute * >{ new Attribute("unused") } );178 for ( Initializer * init : *listInit ) {179 Expression * condition;180 // check for designations181 // if ( init-> ) {182 condition = new ConstantExpr( Constant::from_ulong( cond ) );183 ++cond;184 // } else {185 // condition = // ... take designation186 // cond = // ... take designation+1187 // }188 std::list< Statement * > stmts;189 build( callExpr, idx, idxEnd, init, back_inserter( stmts ) );190 stmts.push_back( new BranchStmt( noLabels, switchLabel, BranchStmt::Break ) );191 CaseStmt * caseStmt = new CaseStmt( noLabels, condition, stmts );192 branches.push_back( caseStmt );193 }194 *out++ = new SwitchStmt( noLabels, index->clone(), branches );195 *out++ = new NullStmt( std::list<Label>{ switchLabel } );196 }197 }198 }199 200 // if array came with an initializer list: initialize each element201 // may have more initializers than elements in the array - need to check at each index that202 // we haven't exceeded size.203 // may have fewer initializers than elements in the array - need to default construct204 // remaining elements.205 // To accomplish this, generate switch statement, consuming all of expander's elements206 Statement * InitImpl::buildListInit( UntypedExpr * dst, std::list< Expression * > & indices ) {207 if ( ! init ) return NULL;208 CompoundStmt * block = new CompoundStmt( noLabels );209 build( dst, indices.begin(), indices.end(), init, back_inserter( block->get_kids() ) );210 if ( block->get_kids().empty() ) {211 delete block;212 return NULL;213 } else {214 init = NULL; // init was consumed in creating the list init215 return block;216 }217 }218 219 Statement * ExprImpl::buildListInit( UntypedExpr * dst, std::list< Expression * > & indices ) {220 return NULL;221 }222 223 Statement * InitExpander::buildListInit( UntypedExpr * dst ) {224 return expander->buildListInit( dst, indices );225 }226 227 55 bool tryConstruct( ObjectDecl * objDecl ) { 228 56 return ! LinkageSpec::isBuiltin( objDecl->get_linkage() ) && 229 57 (objDecl->get_init() == NULL || 230 58 ( objDecl->get_init() != NULL && objDecl->get_init()->get_maybeConstructed() )) && 231 ! isDesignated( objDecl->get_init() ) 232 && objDecl->get_storageClass() != DeclarationNode::Extern; 233 } 234 235 class CallFinder : public Visitor { 236 public: 237 typedef Visitor Parent; 238 CallFinder( const std::list< std::string > & names ) : names( names ) {} 239 240 virtual void visit( ApplicationExpr * appExpr ) { 241 handleCallExpr( appExpr ); 242 } 243 244 virtual void visit( UntypedExpr * untypedExpr ) { 245 handleCallExpr( untypedExpr ); 246 } 247 248 std::list< Expression * > * matches; 249 private: 250 const std::list< std::string > names; 251 252 template< typename CallExpr > 253 void handleCallExpr( CallExpr * expr ) { 254 Parent::visit( expr ); 255 std::string fname = getFunctionName( expr ); 256 if ( std::find( names.begin(), names.end(), fname ) != names.end() ) { 257 matches->push_back( expr ); 258 } 259 } 260 }; 261 262 void collectCtorDtorCalls( Statement * stmt, std::list< Expression * > & matches ) { 263 static CallFinder finder( std::list< std::string >{ "?{}", "^?{}" } ); 264 finder.matches = &matches; 265 maybeAccept( stmt, finder ); 59 ! isDesignated( objDecl->get_init() ); 266 60 } 267 61 268 62 Expression * getCtorDtorCall( Statement * stmt ) { 269 std::list< Expression * > matches; 270 collectCtorDtorCalls( stmt, matches ); 271 assert( matches.size() <= 1 ); 272 return matches.size() == 1 ? matches.front() : NULL; 273 } 274 275 namespace { 276 VariableExpr * getCalledFunction( ApplicationExpr * appExpr ) { 277 assert( appExpr ); 278 // xxx - it's possible this can be other things, e.g. MemberExpr, so this is insufficient 279 return dynamic_cast< VariableExpr * >( appExpr->get_function() ); 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" ); 280 84 } 281 85 } 282 86 283 ApplicationExpr * isIntrinsicCallExpr( Expression * expr ) { 284 ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr ); 285 if ( ! appExpr ) return NULL; 286 VariableExpr * function = getCalledFunction( appExpr ); 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() ); 287 93 assert( function ); 288 94 // check for Intrinsic only - don't want to remove all overridable ctor/dtors because autogenerated ctor/dtor 289 95 // will call all member dtors, and some members may have a user defined dtor. 290 return function->get_var()->get_linkage() == LinkageSpec::Intrinsic ? appExpr : NULL; 291 } 292 293 bool isIntrinsicSingleArgCallStmt( Statement * stmt ) { 294 std::list< Expression * > callExprs; 295 collectCtorDtorCalls( stmt, callExprs ); 296 // if ( callExprs.empty() ) return false; // xxx - do I still need this check? 297 return std::all_of( callExprs.begin(), callExprs.end(), []( Expression * callExpr ){ 298 if ( ApplicationExpr * appExpr = isIntrinsicCallExpr( callExpr ) ) { 299 assert( ! appExpr->get_function()->get_results().empty() ); 300 FunctionType *funcType = GenPoly::getFunctionType( appExpr->get_function()->get_results().front() ); 301 assert( funcType ); 302 return funcType->get_parameters().size() == 1; 303 } 304 return false; 305 }); 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; 306 99 } 307 100 … … 367 160 else return NULL; 368 161 } 369 370 class ConstExprChecker : public Visitor {371 public:372 ConstExprChecker() : isConstExpr( true ) {}373 374 virtual void visit( ApplicationExpr *applicationExpr ) { isConstExpr = false; }375 virtual void visit( UntypedExpr *untypedExpr ) { isConstExpr = false; }376 virtual void visit( NameExpr *nameExpr ) { isConstExpr = false; }377 virtual void visit( CastExpr *castExpr ) { isConstExpr = false; }378 virtual void visit( LabelAddressExpr *labAddressExpr ) { isConstExpr = false; }379 virtual void visit( UntypedMemberExpr *memberExpr ) { isConstExpr = false; }380 virtual void visit( MemberExpr *memberExpr ) { isConstExpr = false; }381 virtual void visit( VariableExpr *variableExpr ) { isConstExpr = false; }382 virtual void visit( ConstantExpr *constantExpr ) { /* bottom out */ }383 // these might be okay?384 // virtual void visit( SizeofExpr *sizeofExpr );385 // virtual void visit( AlignofExpr *alignofExpr );386 // virtual void visit( UntypedOffsetofExpr *offsetofExpr );387 // virtual void visit( OffsetofExpr *offsetofExpr );388 // virtual void visit( OffsetPackExpr *offsetPackExpr );389 // virtual void visit( AttrExpr *attrExpr );390 // virtual void visit( CommaExpr *commaExpr );391 // virtual void visit( LogicalExpr *logicalExpr );392 // virtual void visit( ConditionalExpr *conditionalExpr );393 virtual void visit( TupleExpr *tupleExpr ) { isConstExpr = false; }394 virtual void visit( SolvedTupleExpr *tupleExpr ) { isConstExpr = false; }395 virtual void visit( TypeExpr *typeExpr ) { isConstExpr = false; }396 virtual void visit( AsmExpr *asmExpr ) { isConstExpr = false; }397 virtual void visit( UntypedValofExpr *valofExpr ) { isConstExpr = false; }398 virtual void visit( CompoundLiteralExpr *compLitExpr ) { isConstExpr = false; }399 400 bool isConstExpr;401 };402 403 bool isConstExpr( Expression * expr ) {404 if ( expr ) {405 ConstExprChecker checker;406 expr->accept( checker );407 return checker.isConstExpr;408 }409 return true;410 }411 412 bool isConstExpr( Initializer * init ) {413 if ( init ) {414 ConstExprChecker checker;415 init->accept( checker );416 return checker.isConstExpr;417 } // if418 // for all intents and purposes, no initializer means const expr419 return true;420 }421 422 162 } -
src/InitTweak/InitTweak.h
r1b0020a rdae881f 26 26 // helper functions for initialization 27 27 namespace InitTweak { 28 /// transform Initializer into an argument list that can be passed to a call expression29 std::list< Expression * > makeInitList( Initializer * init );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 /// True if the resolver should try to construct objDecl32 bool tryConstruct( ObjectDecl * objDecl );31 /// True if the resolver should try to construct objDecl 32 bool tryConstruct( ObjectDecl * objDecl ); 33 33 34 /// True if the Initializer contains designations35 bool isDesignated( Initializer * init );34 /// True if the Initializer contains designations 35 bool isDesignated( Initializer * init ); 36 36 37 /// Non-Null if expr is a call expression whose target function is intrinsic 38 ApplicationExpr * isIntrinsicCallExpr( Expression * expr ); 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 ); 39 41 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 isIntrinsicSingleArgCallStmt( Statement * expr ); 42 /// get the Ctor/Dtor call expression from a Statement that looks like a generated ctor/dtor call 43 Expression * getCtorDtorCall( Statement * stmt ); 44 44 45 /// get all Ctor/Dtor call expressions from a Statement 46 void collectCtorDtorCalls( Statement * stmt, std::list< Expression * > & matches);45 /// returns the name of the function being called 46 std::string getFunctionName( Expression * expr ); 47 47 48 /// get the Ctor/Dtor call expression from a Statement that looks like a generated ctor/dtor call 49 Expression * getCtorDtorCall( Statement * stmt);48 /// returns the argument to a call expression in position N indexed from 0 49 Expression *& getCallArg( Expression * callExpr, unsigned int pos ); 50 50 51 /// returns the name of the function being called 52 std::string getFunctionName( Expression * expr);51 /// returns the base type of a PointerType or ArrayType, else returns NULL 52 Type * getPointerBase( Type * ); 53 53 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 }; 54 /// returns the argument if it is a PointerType or ArrayType, else returns NULL 55 Type * isPointerType( Type * ); 94 56 } // namespace 95 57 -
src/Parser/TypeData.cc
r1b0020a rdae881f 510 510 return buildVariable(); 511 511 } else { 512 return new ObjectDecl( name, sc, linkage, bitfieldWidth, build(), init, std::list< Attribute * >(),isInline, isNoreturn );512 return new ObjectDecl( name, sc, linkage, bitfieldWidth, build(), init, isInline, isNoreturn ); 513 513 } // if 514 514 return 0; -
src/ResolvExpr/Resolver.cc
r1b0020a rdae881f 24 24 #include "SynTree/Initializer.h" 25 25 #include "SymTab/Indexer.h" 26 #include "SymTab/Autogen.h"27 26 #include "Common/utility.h" 28 27 #include "InitTweak/InitTweak.h" … … 42 41 43 42 virtual void visit( ArrayType * at ); 44 virtual void visit( PointerType * at );45 43 46 44 virtual void visit( ExprStmt *exprStmt ); … … 54 52 virtual void visit( BranchStmt *branchStmt ); 55 53 virtual void visit( ReturnStmt *returnStmt ); 54 virtual void visit( ImplicitCtorDtorStmt * impCtorDtorStmt ); 56 55 57 56 virtual void visit( SingleInit *singleInit ); … … 60 59 private: 61 60 typedef std::list< Initializer * >::iterator InitIterator; 62 63 template< typename PtrType >64 void handlePtrType( PtrType * type );65 61 66 62 void resolveAggrInit( AggregateDecl *, InitIterator &, InitIterator & ); … … 196 192 } 197 193 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() );194 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() ); 202 198 Expression *newExpr = findSingleExpression( castExpr, *this ); 203 delete type->get_dimension(); 204 type->set_dimension( newExpr ); 205 } 206 } 207 208 void Resolver::visit( ArrayType * at ) { 209 handlePtrType( at ); 199 delete at->get_dimension(); 200 at->set_dimension( newExpr ); 201 } 210 202 Visitor::visit( at ); 211 }212 213 void Resolver::visit( PointerType * pt ) {214 handlePtrType( pt );215 Visitor::visit( pt );216 203 } 217 204 … … 435 422 436 423 void Resolver::visit( ListInit * listInit ) { 437 InitIterator iter = listInit->begin ();438 InitIterator end = listInit->end ();424 InitIterator iter = listInit->begin_initializers(); 425 InitIterator end = listInit->end_initializers(); 439 426 440 427 if ( ArrayType * at = dynamic_cast< ArrayType * >( initContext ) ) { … … 534 521 // implicitly generated, there's no way for it to have side effects, so get rid of it 535 522 // to clean up generated code. 536 if ( InitTweak::isIn trinsicSingleArgCallStmt( ctorInit->get_ctor() ) ) {523 if ( InitTweak::isInstrinsicSingleArgCallStmt( ctorInit->get_ctor() ) ) { 537 524 delete ctorInit->get_ctor(); 538 525 ctorInit->set_ctor( NULL ); 539 526 } 540 541 // xxx - todo 542 // if ( InitTweak::isIntrinsicCallStmt( ctorInit->get_ctor() ) ) { 543 // // can reduce the constructor down to a SingleInit using the 544 // // second argument from the ctor call 545 // } 546 547 if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->get_dtor() ) ) { 527 if ( InitTweak::isInstrinsicSingleArgCallStmt( ctorInit->get_ctor() ) ) { 548 528 delete ctorInit->get_dtor(); 549 529 ctorInit->set_dtor( NULL ); 550 530 } 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 construction 542 // 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 fixed 546 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 the 553 // 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 argument 561 // must have an lvalue qualified type, so remove all qualifiers except lvalue. If we ever 562 // remove lvalue as a qualifier, this can change to 563 // 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 output 568 type->set_isLvalue( false ); 569 constructee = new CastExpr( constructee, type ); 570 571 // finally, resolve the ctor/dtor 572 impCtorDtorStmt->get_callStmt()->accept( *this ); 551 573 } 552 574 } // namespace ResolvExpr -
src/SymTab/Autogen.cc
r1b0020a rdae881f 26 26 27 27 namespace SymTab { 28 Type * SizeType = 0;29 30 28 class AutogenerateRoutines : public Visitor { 31 29 public: … … 61 59 bool isUnnamedBitfield( ObjectDecl * obj ) { 62 60 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 accessed 67 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 members 77 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 wrapped 87 // 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; 63 93 } 64 94 … … 189 219 } 190 220 191 InitTweak::InitExpander srcParam( src );192 193 221 // assign to destination (and return value if generic) 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 ); 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() ) ); 204 238 } // if 205 239 } -
src/SymTab/Autogen.h
r1b0020a rdae881f 22 22 #include "SynTree/Declaration.h" 23 23 #include "SynTree/Initializer.h" 24 #include "InitTweak/InitTweak.h"25 24 26 25 namespace SymTab { 27 /// Generates assignment operators, constructors, and destructor for aggregate types as required28 void autogenerateRoutines( std::list< Declaration * > &translationUnit );26 /// Generates assignment operators, constructors, and destructor for aggregate types as required 27 void autogenerateRoutines( std::list< Declaration * > &translationUnit ); 29 28 30 /// returns true if obj's name is the empty string and it has a bitfield width 31 bool isUnnamedBitfield( ObjectDecl * obj ); 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 32 31 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; 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" ); 36 37 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 Statement * genCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast = false, bool forward = true ); 38 // for a flexible array member nothing is done -- user must define own assignment 39 if ( ! array->get_dimension() ) return; 40 40 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 /// optionally returns a statement which must be inserted prior to the containing loop, if there is one 43 template< typename OutputIterator > 44 Statement * genScalarCall( InitTweak::InitExpander & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast = false ) { 45 // want to be able to generate assignment, ctor, and dtor generically, 46 // so fname is either ?=?, ?{}, or ^?{} 47 UntypedExpr *fExpr = new UntypedExpr( new NameExpr( fname ) ); 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( "--?" ); 56 } 48 57 49 // do something special for unnamed members 50 dstParam = new AddressExpr( dstParam ); 51 if ( addCast ) { 52 // cast to T* with qualifiers removed, so that qualified objects can be constructed 53 // and destructed with the same functions as non-qualified objects. 54 // unfortunately, lvalue is considered a qualifier. For AddressExpr to resolve, its argument 55 // must have an lvalue qualified type, so remove all qualifiers except lvalue. If we ever 56 // remove lvalue as a qualifier, this can change to 57 // type->get_qualifiers() = Type::Qualifiers(); 58 assert( type ); 59 Type * castType = type->clone(); 60 castType->get_qualifiers() -= Type::Qualifiers(true, true, true, false, true, true); 61 castType->set_isLvalue( true ); // xxx - might not need this 62 dstParam = new CastExpr( dstParam, new PointerType( Type::Qualifiers(), castType ) ); 63 } 64 fExpr->get_args().push_back( dstParam ); 58 ObjectDecl *index = new ObjectDecl( indexName.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), NULL ); 65 59 66 Statement * listInit = srcParam.buildListInit( fExpr ); 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*>() ) ); 67 64 68 std::list< Expression * > args = *++srcParam; 69 fExpr->get_args().splice( fExpr->get_args().end(), args ); 65 UntypedExpr *cond = new UntypedExpr( cmp ); 66 cond->get_args().push_back( new VariableExpr( index ) ); 67 cond->get_args().push_back( end ); 70 68 71 *out++ = new ExprStmt( noLabels, fExpr ); 69 UntypedExpr *inc = new UntypedExpr( update ); 70 inc->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) ); 72 71 73 srcParam.clearArrayIndices(); 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 ) ); 74 75 75 return listInit; 76 } 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 ); 77 80 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" ); 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 ); 87 } 83 88 84 // for a flexible array member nothing is done -- user must define own assignment 85 if ( ! array->get_dimension() ) return ; 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 ) ) ); 86 93 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 } 103 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 // for stmt's body, eventually containing call 128 CompoundStmt * body = new CompoundStmt( noLabels ); 129 Statement * listInit = genCall( srcParam, dstParam, fname, back_inserter( body->get_kids() ), array->get_base(), addCast, forward ); 130 131 // block containing for stmt and index variable 132 std::list<Statement *> initList; 133 CompoundStmt * block = new CompoundStmt( noLabels ); 134 block->get_kids().push_back( new DeclStmt( noLabels, index ) ); 135 if ( listInit ) block->get_kids().push_back( listInit ); 136 block->get_kids().push_back( new ForStmt( noLabels, initList, cond, inc, body ) ); 137 138 *out++ = block; 139 } 140 141 template< typename OutputIterator > 142 Statement * genCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast, bool forward ) { 143 if ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) { 144 genArrayCall( srcParam, dstParam, fname, out, at, addCast, forward ); 145 return 0; 146 } else { 147 return genScalarCall( srcParam, dstParam, fname, out, type, addCast ); 148 } 149 } 150 151 /// inserts into out a generated call expression to function fname with arguments dstParam 152 /// and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls. decl is the 153 /// object being constructed. The function wraps constructor and destructor calls in an 154 /// ImplicitCtorDtorStmt node. 155 template< typename OutputIterator > 156 void genImplicitCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, DeclarationWithType * decl, bool forward = true ) { 157 ObjectDecl *obj = dynamic_cast<ObjectDecl *>( decl ); 158 assert( obj ); 159 // unnamed bit fields are not copied as they cannot be accessed 160 if ( isUnnamedBitfield( obj ) ) return; 161 162 bool addCast = (fname == "?{}" || fname == "^?{}") && ( !obj || ( obj && obj->get_bitfieldWidth() == NULL ) ); 163 std::list< Statement * > stmts; 164 genCall( srcParam, dstParam, fname, back_inserter( stmts ), obj->get_type(), addCast, forward ); 165 166 // 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 167 assert( stmts.size() <= 1 ); 168 if ( stmts.size() == 1 ) { 169 Statement * callStmt = stmts.front(); 170 if ( addCast ) { 171 // implicitly generated ctor/dtor calls should be wrapped 172 // so that later passes are aware they were generated. 173 // xxx - don't mark as an implicit ctor/dtor if obj is a bitfield, 174 // because this causes the address to be taken at codegen, which is illegal in C. 175 callStmt = new ImplicitCtorDtorStmt( callStmt ); 176 } 177 *out++ = callStmt; 178 } 179 } 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 } 180 102 } // namespace SymTab 181 103 #endif // AUTOGEN_H -
src/SymTab/FixFunction.cc
r1b0020a rdae881f 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 // 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() ); 46 PointerType *pointerType = new PointerType( arrayType->get_qualifiers(), maybeClone( arrayType->get_base()->clone() ), maybeClone( arrayType->get_dimension() ), arrayType->get_isVarLen(), arrayType->get_isStatic() ); 48 47 delete arrayType; 49 48 return pointerType; -
src/SymTab/Validate.cc
r1b0020a rdae881f 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 Pass1194 193 acceptAll( translationUnit, pass1 ); 195 194 acceptAll( translationUnit, pass2 ); 196 195 ReturnChecker::checkFunctionReturns( translationUnit ); 197 compoundliteral.mutateDeclarationList( translationUnit ); 196 mutateAll( translationUnit, compoundliteral ); 197 autogenerateRoutines( 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_t494 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 wrong497 // eventually should have a warning for this case.498 SizeType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );499 }500 492 filter( translationUnit, isTypedef, true ); 501 502 493 } 503 494 … … 527 518 Declaration *EliminateTypedef::mutate( TypedefDecl * tyDecl ) { 528 519 Declaration *ret = Mutator::mutate( tyDecl ); 529 530 520 if ( typedefNames.count( tyDecl->get_name() ) == 1 && typedefNames[ tyDecl->get_name() ].second == scopeLevel ) { 531 521 // typedef to the same name from the same scope -
src/SynTree/Declaration.cc
r1b0020a rdae881f 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // Declaration.cc -- 7 // Declaration.cc -- 8 8 // 9 9 // Author : Richard C. Bilson … … 20 20 #include "Initializer.h" 21 21 #include "Type.h" 22 #include "Attribute.h"23 22 #include "Common/utility.h" 24 23 -
src/SynTree/Declaration.h
r1b0020a rdae881f 64 64 class DeclarationWithType : public Declaration { 65 65 public: 66 DeclarationWithType( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage , const std::list< Attribute * > & attributes);66 DeclarationWithType( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage ); 67 67 DeclarationWithType( const DeclarationWithType &other ); 68 68 virtual ~DeclarationWithType(); … … 75 75 int get_scopeLevel() const { return scopeLevel; } 76 76 void set_scopeLevel( int newValue ) { scopeLevel = newValue; } 77 78 std::list< Attribute * >& get_attributes() { return attributes; }79 const std::list< Attribute * >& get_attributes() const { return attributes; }80 77 81 78 virtual DeclarationWithType *clone() const = 0; … … 90 87 // shadowed identifiers can be accessed 91 88 int scopeLevel = 0; 92 93 std::list< Attribute * > attributes;94 89 }; 95 90 … … 97 92 typedef DeclarationWithType Parent; 98 93 public: 99 ObjectDecl( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage, Expression *bitfieldWidth, Type *type, Initializer *init, const std::list< Attribute * > attributes = std::list< Attribute * >(),bool isInline = false, bool isNoreturn = false );94 ObjectDecl( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage, Expression *bitfieldWidth, Type *type, Initializer *init, bool isInline = false, bool isNoreturn = false ); 100 95 ObjectDecl( const ObjectDecl &other ); 101 96 virtual ~ObjectDecl(); … … 136 131 std::list< std::string >& get_oldIdents() { return oldIdents; } 137 132 std::list< Declaration* >& get_oldDecls() { return oldDecls; } 133 std::list< Attribute * >& get_attributes() { return attributes; } 138 134 139 135 virtual FunctionDecl *clone() const { return new FunctionDecl( *this ); } … … 147 143 std::list< std::string > oldIdents; 148 144 std::list< Declaration* > oldDecls; 145 std::list< Attribute * > attributes; 149 146 }; 150 147 -
src/SynTree/DeclarationWithType.cc
r1b0020a rdae881f 16 16 #include "Declaration.h" 17 17 #include "Type.h" 18 #include "Attribute.h"19 18 #include "Common/utility.h" 20 19 21 DeclarationWithType::DeclarationWithType( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage , const std::list< Attribute * > & attributes)22 : Declaration( name, sc, linkage ) , attributes( attributes ){20 DeclarationWithType::DeclarationWithType( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage ) 21 : Declaration( name, sc, linkage ) { 23 22 } 24 23 25 24 DeclarationWithType::DeclarationWithType( const DeclarationWithType &other ) 26 25 : Declaration( other ), mangleName( other.mangleName ), scopeLevel( other.scopeLevel ) { 27 cloneAll( other.attributes, attributes );28 26 } 29 27 30 28 DeclarationWithType::~DeclarationWithType() { 31 deleteAll( attributes );32 29 } 33 30 -
src/SynTree/Expression.cc
r1b0020a rdae881f 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...347 346 MemberExpr::MemberExpr( const MemberExpr &other ) : 348 Expression( other ), member( other.member), aggregate( maybeClone( other.aggregate ) ) {347 Expression( other ), member( maybeClone( other.member ) ), aggregate( maybeClone( other.aggregate ) ) { 349 348 } 350 349 351 350 MemberExpr::~MemberExpr() { 352 //delete member;351 delete member; 353 352 delete aggregate; 354 353 } -
src/SynTree/FunctionDecl.cc
r1b0020a rdae881f 23 23 24 24 FunctionDecl::FunctionDecl( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage, FunctionType *type, CompoundStmt *statements, bool isInline, bool isNoreturn, std::list< Attribute * > attributes ) 25 : Parent( name, sc, linkage , attributes ), type( type ), statements( statements ) {25 : Parent( name, sc, linkage ), type( type ), statements( statements ), attributes( attributes ) { 26 26 set_isInline( isInline ); 27 27 set_isNoreturn( isNoreturn ); … … 34 34 FunctionDecl::FunctionDecl( const FunctionDecl &other ) 35 35 : Parent( other ), type( maybeClone( other.type ) ), statements( maybeClone( other.statements ) ) { 36 cloneAll( other.attributes, attributes ); 36 37 } 37 38 … … 39 40 delete type; 40 41 delete statements; 42 deleteAll( attributes ); 41 43 } 42 44 … … 67 69 } // if 68 70 69 printAll( get_attributes(), os, indent );71 printAll( attributes, os, indent ); 70 72 71 73 if ( get_storageClass() != DeclarationNode::NoStorageClass ) { -
src/SynTree/Initializer.h
r1b0020a rdae881f 93 93 std::list<Initializer*> &get_initializers() { return initializers; } 94 94 95 typedef std::list<Initializer*>::iterator iterator; 96 iterator begin() { return initializers.begin(); } 97 iterator end() { return initializers.end(); } 95 std::list<Initializer*>::iterator begin_initializers() { return initializers.begin(); } 96 std::list<Initializer*>::iterator end_initializers() { return initializers.end(); } 98 97 99 98 virtual ListInit *clone() const { return new ListInit( *this ); } -
src/SynTree/Label.h
r1b0020a rdae881f 24 24 class Label { 25 25 public: 26 Label( const std::string & name = "", Statement * labelled = 0 , const std::list< Attribute * > & attributes = std::list< Attribute * >() ) : name( name ), labelled( labelled ), attributes( attributes) {}26 Label( const std::string & name = "", Statement * labelled = 0 ) : name( name ), labelled( labelled ) {} 27 27 Label( const char * name, Statement * labelled = 0 ) : name( name ), labelled( labelled ) {} 28 28 -
src/SynTree/ObjectDecl.cc
r1b0020a rdae881f 18 18 #include "Initializer.h" 19 19 #include "Expression.h" 20 #include "Attribute.h"21 20 #include "Common/utility.h" 22 21 #include "Statement.h" 23 22 24 ObjectDecl::ObjectDecl( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage, Expression *bitfieldWidth, Type *type, Initializer *init, const std::list< Attribute * > attributes,bool isInline, bool isNoreturn )25 : Parent( name, sc, linkage , attributes), type( type ), init( init ), bitfieldWidth( bitfieldWidth ) {23 ObjectDecl::ObjectDecl( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage, Expression *bitfieldWidth, Type *type, Initializer *init, bool isInline, bool isNoreturn ) 24 : Parent( name, sc, linkage ), type( type ), init( init ), bitfieldWidth( bitfieldWidth ) { 26 25 set_isInline( isInline ); 27 26 set_isNoreturn( isNoreturn ); … … 46 45 os << LinkageSpec::toString( get_linkage() ) << " "; 47 46 } // if 48 49 printAll( get_attributes(), os, indent );50 47 51 48 if ( get_storageClass() != DeclarationNode::NoStorageClass ) { … … 83 80 } // if 84 81 85 // xxx - should printShort print attributes?86 87 82 if ( get_storageClass() != DeclarationNode::NoStorageClass ) { 88 83 os << DeclarationNode::storageName[ get_storageClass() ] << ' '; -
src/main.cc
r1b0020a rdae881f 42 42 #include "InitTweak/GenInit.h" 43 43 #include "InitTweak/FixInit.h" 44 #include "InitTweak/FixGlobalInit.h" 44 45 //#include "Explain/GenProlog.h" 45 46 //#include "Try/Visit.h" … … 281 282 OPTPRINT( "fixNames" ) 282 283 CodeGen::fixNames( translationUnit ); 284 OPTPRINT( "fixGlobalInit" ); 285 InitTweak::fixGlobalInit( translationUnit, filename, libcfap || treep ); 283 286 OPTPRINT( "tweakInit" ) 284 287 InitTweak::genInit( translationUnit ); … … 301 304 } 302 305 306 OPTPRINT( "fixInit" ) 303 307 // fix ObjectDecl - replaces ConstructorInit nodes 304 OPTPRINT( "fixInit" ) 305 InitTweak::fix( translationUnit, filename, libcfap || treep ); 308 InitTweak::fix( translationUnit ); 306 309 if ( ctorinitp ) { 307 310 dump ( translationUnit ); -
src/tests/.expect/64/extension.txt
r1b0020a rdae881f 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
r1b0020a rdae881f 92 92 init_once y = x; 93 93 94 void static_variable() {95 static init_once x;96 }97 98 94 int main() { 99 95 // local variables … … 183 179 } 184 180 } 185 186 // function-scoped static variable187 for (int i = 0; i < 10; i++) {188 static_variable();189 }190 181 } 191 182
Note:
See TracChangeset
for help on using the changeset viewer.