Changes in / [31e46b8:ccb447e]
- Location:
- src
- Files:
-
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
src/GenPoly/DeclMutator.h
r31e46b8 rccb447e 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/InitTweak/FixGlobalInit.cc
r31e46b8 rccb447e 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
r31e46b8 rccb447e 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; … … 171 173 } // namespace 172 174 173 void fix( std::list< Declaration * > & translationUnit ) { 175 void fix( std::list< Declaration * > & translationUnit, const std::string & filename, bool inLibrary ) { 176 // fixes ConstructorInit for global variables. should happen before fixInitializers. 177 InitTweak::fixGlobalInit( translationUnit, filename, inLibrary ); 178 174 179 InsertImplicitCalls::insert( translationUnit ); 175 180 ResolveCopyCtors::resolveImplicitCalls( translationUnit ); -
src/InitTweak/FixInit.h
r31e46b8 rccb447e 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
r31e46b8 rccb447e 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 void HoistArrayDimension::hoistArrayDimension( std::list< Declaration * > & translationUnit ) { 157 HoistArrayDimension hoister; 158 hoister.mutateDeclarationList( translationUnit ); 159 } 160 161 DeclarationWithType * HoistArrayDimension::mutate( ObjectDecl * objectDecl ) { 162 storageclass = objectDecl->get_storageClass(); 163 DeclarationWithType * temp = Parent::mutate( objectDecl ); 164 hoist( objectDecl->get_type() ); 165 storageclass = DeclarationNode::NoStorageClass; 166 return temp; 167 } 168 169 void HoistArrayDimension::hoist( Type * type ) { 170 // if in function, generate const size_t var 171 static UniqueName dimensionName( "_array_dim" ); 172 if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) { 173 if ( ! inFunction ) return; 174 175 if ( ! arrayType->get_dimension() ) return; // xxx - recursive call to hoist? 176 177 // don't need to hoist dimension if it's a constexpr - only need to if there's potential 178 // for side effects. 179 if ( isConstExpr( arrayType->get_dimension() ) ) return; 180 181 ObjectDecl * arrayDimension = new ObjectDecl( dimensionName.newName(), storageclass, LinkageSpec::C, 0, SymTab::SizeType->clone(), new SingleInit( arrayType->get_dimension() ) ); 182 arrayDimension->get_type()->set_isConst( true ); 183 184 arrayType->set_dimension( new VariableExpr( arrayDimension ) ); 185 addDeclaration( arrayDimension ); 186 187 hoist( arrayType->get_base() ); 188 return; 189 } 190 } 191 192 DeclarationWithType * HoistArrayDimension::mutate( FunctionDecl *functionDecl ) { 193 bool oldInFunc = inFunction; 194 inFunction = true; 195 DeclarationWithType * decl = Parent::mutate( functionDecl ); 196 inFunction = oldInFunc; 197 return decl; 198 } 126 199 127 200 void CtorDtor::generateCtorDtor( std::list< Declaration * > & translationUnit ) { … … 140 213 141 214 DeclarationWithType * CtorDtor::mutate( ObjectDecl * objDecl ) { 142 // hands off if designated or if @=215 // hands off if designated, if @=, or if extern 143 216 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() ) ); 217 if ( ArrayType * at = dynamic_cast< ArrayType * >( objDecl->get_type() ) ) { 218 // call into makeArrayFunction from validate.cc to generate calls to ctor/dtor for each element of array 219 // TODO: walk initializers and generate appropriate ctor if element has initializer. 220 // Initializer could be nested (depends on the depth of the array type on the object) 221 222 std::list< Expression * > args = makeInitList( objDecl->get_init() ); 223 if ( args.empty() ) { 224 std::list< Statement * > ctor; 225 std::list< Statement * > dtor; 226 227 SymTab::genImplicitCall( NULL, new VariableExpr( objDecl ), "?{}", back_inserter( ctor ), objDecl ); 228 SymTab::genImplicitCall( NULL, new VariableExpr( objDecl ), "^?{}", front_inserter( dtor ), objDecl, false ); 229 230 // Currently genImplicitCall produces a single Statement - a CompoundStmt 231 // which wraps everything that needs to happen. As such, it's technically 232 // possible to use a Statement ** in the above calls, but this is inherently 233 // unsafe, so instead we take the slightly less efficient route, but will be 234 // immediately informed if somehow the above assumption is broken. In this case, 235 // we could always wrap the list of statements at this point with a CompoundStmt, 236 // but it seems reasonable at the moment for this to be done by genImplicitCall 237 // itself. It is possible that genImplicitCall produces no statements (e.g. if 238 // an array type does not have a dimension). In this case, it's fine to ignore 239 // the object for the purposes of construction. 240 assert( ctor.size() == dtor.size() && ctor.size() <= 1 ); 241 if ( ctor.size() == 1 ) { 242 assert( dynamic_cast< ImplicitCtorDtorStmt * > ( ctor.front() ) && dynamic_cast< ImplicitCtorDtorStmt * > ( dtor.front() ) ); 166 243 objDecl->set_init( new ConstructorInit( ctor.front(), dtor.front(), objDecl->get_init() ) ); 167 } else {168 // array came with an initializer list: initialize each element169 // may have more initializers than elements in the array - need to check at each index that170 // we haven't exceeded size. This requires precomputing the size because it might be a side-effecting171 // computation.172 // may have fewer initializers than eleemnts in the array - need to default construct173 // remaining elements.174 // might be able to merge this with the case above.175 244 } 176 245 } 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() ) ); 246 // array came with an initializer list: initialize each element 247 // may have more initializers than elements in the array - need to check at each index that 248 // we haven't exceeded size. This requires precomputing the size because it might be a side-effecting 249 // computation. 250 // may have fewer initializers than elements in the array - need to default construct 251 // remaining elements. 252 // might be able to merge this with the case above. 253 187 254 } 255 } else { 256 // it's sufficient to attempt to call the ctor/dtor for the given object and its initializer 257 Expression * ctor = makeCtorDtorExpr( "?{}", objDecl, makeInitList( objDecl->get_init() ) ); 258 Expression * dtor = makeCtorDtorExpr( "^?{}", objDecl, std::list< Expression * >() ); 259 260 // need to remember init expression, in case no ctors exist 261 // if ctor does exist, want to use ctor expression instead of init 262 // push this decision to the resolver 263 ExprStmt * ctorStmt = new ExprStmt( noLabels, ctor ); 264 ExprStmt * dtorStmt = new ExprStmt( noLabels, dtor ); 265 objDecl->set_init( new ConstructorInit( new ImplicitCtorDtorStmt( ctorStmt ), new ImplicitCtorDtorStmt( dtorStmt ), objDecl->get_init() ) ); 188 266 } 189 267 } … … 193 271 DeclarationWithType * CtorDtor::mutate( FunctionDecl *functionDecl ) { 194 272 // parameters should not be constructed and destructed, so don't mutate FunctionType 195 bool oldInFunc = inFunction;196 273 mutateAll( functionDecl->get_oldDecls(), *this ); 197 inFunction = true;198 274 functionDecl->set_statements( maybeMutate( functionDecl->get_statements(), *this ) ); 199 inFunction = oldInFunc;200 275 return functionDecl; 201 276 } 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 277 } // namespace InitTweak 214 278 -
src/InitTweak/InitTweak.cc
r31e46b8 rccb447e 57 57 (objDecl->get_init() == NULL || 58 58 ( objDecl->get_init() != NULL && objDecl->get_init()->get_maybeConstructed() )) && 59 ! isDesignated( objDecl->get_init() ); 59 ! isDesignated( objDecl->get_init() ) 60 && objDecl->get_storageClass() != DeclarationNode::Extern; 60 61 } 61 62 … … 160 161 else return NULL; 161 162 } 163 164 class ConstExprChecker : public Visitor { 165 public: 166 ConstExprChecker() : isConstExpr( true ) {} 167 168 virtual void visit( ApplicationExpr *applicationExpr ) { isConstExpr = false; } 169 virtual void visit( UntypedExpr *untypedExpr ) { isConstExpr = false; } 170 virtual void visit( NameExpr *nameExpr ) { isConstExpr = false; } 171 virtual void visit( CastExpr *castExpr ) { isConstExpr = false; } 172 virtual void visit( LabelAddressExpr *labAddressExpr ) { isConstExpr = false; } 173 virtual void visit( UntypedMemberExpr *memberExpr ) { isConstExpr = false; } 174 virtual void visit( MemberExpr *memberExpr ) { isConstExpr = false; } 175 virtual void visit( VariableExpr *variableExpr ) { isConstExpr = false; } 176 virtual void visit( ConstantExpr *constantExpr ) { /* bottom out */ } 177 // these might be okay? 178 // virtual void visit( SizeofExpr *sizeofExpr ); 179 // virtual void visit( AlignofExpr *alignofExpr ); 180 // virtual void visit( UntypedOffsetofExpr *offsetofExpr ); 181 // virtual void visit( OffsetofExpr *offsetofExpr ); 182 // virtual void visit( OffsetPackExpr *offsetPackExpr ); 183 // virtual void visit( AttrExpr *attrExpr ); 184 // virtual void visit( CommaExpr *commaExpr ); 185 // virtual void visit( LogicalExpr *logicalExpr ); 186 // virtual void visit( ConditionalExpr *conditionalExpr ); 187 virtual void visit( TupleExpr *tupleExpr ) { isConstExpr = false; } 188 virtual void visit( SolvedTupleExpr *tupleExpr ) { isConstExpr = false; } 189 virtual void visit( TypeExpr *typeExpr ) { isConstExpr = false; } 190 virtual void visit( AsmExpr *asmExpr ) { isConstExpr = false; } 191 virtual void visit( UntypedValofExpr *valofExpr ) { isConstExpr = false; } 192 virtual void visit( CompoundLiteralExpr *compLitExpr ) { isConstExpr = false; } 193 194 bool isConstExpr; 195 }; 196 197 bool isConstExpr( Expression * expr ) { 198 if ( expr ) { 199 ConstExprChecker checker; 200 expr->accept( checker ); 201 return checker.isConstExpr; 202 } 203 return true; 204 } 205 206 bool isConstExpr( Initializer * init ) { 207 if ( init ) { 208 ConstExprChecker checker; 209 init->accept( checker ); 210 return checker.isConstExpr; 211 } // if 212 // for all intents and purposes, no initializer means const expr 213 return true; 214 } 215 162 216 } -
src/InitTweak/InitTweak.h
r31e46b8 rccb447e 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 38 39 40 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 ); 41 41 42 43 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 46 45 /// returns the name of the function being called 46 std::string getFunctionName( Expression * expr ); 47 47 48 49 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 52 51 /// returns the base type of a PointerType or ArrayType, else returns NULL 52 Type * getPointerBase( Type * ); 53 53 54 /// returns the argument if it is a PointerType or ArrayType, else returns NULL 55 Type * isPointerType( Type * ); 54 /// returns the argument if it is a PointerType or ArrayType, else returns NULL 55 Type * isPointerType( Type * ); 56 57 /// returns true if expr is trivially a compile-time constant 58 bool isConstExpr( Expression * expr ); 59 bool isConstExpr( Initializer * init ); 56 60 } // namespace 57 61 -
src/ResolvExpr/Resolver.cc
r31e46b8 rccb447e 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 ); … … 59 61 private: 60 62 typedef std::list< Initializer * >::iterator InitIterator; 63 64 template< typename PtrType > 65 void handlePtrType( PtrType * type ); 61 66 62 67 void resolveAggrInit( AggregateDecl *, InitIterator &, InitIterator & ); … … 192 197 } 193 198 199 template< typename PtrType > 200 void Resolver::handlePtrType( PtrType * type ) { 201 if ( type->get_dimension() ) { 202 CastExpr *castExpr = new CastExpr( type->get_dimension(), SymTab::SizeType->clone() ); 203 Expression *newExpr = findSingleExpression( castExpr, *this ); 204 delete type->get_dimension(); 205 type->set_dimension( newExpr ); 206 } 207 } 208 194 209 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 } 210 handlePtrType( at ); 202 211 Visitor::visit( at ); 212 } 213 214 void Resolver::visit( PointerType * pt ) { 215 handlePtrType( pt ); 216 Visitor::visit( pt ); 203 217 } 204 218 … … 537 551 assert( callExpr ); 538 552 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 } 553 554 // the first argument will always be &<expr> 555 AddressExpr * addrExpr = dynamic_cast< AddressExpr * > ( constructee ); 556 assert( addrExpr ); 557 558 // need to find the type of the first argument. In the case of an array, 559 // need to remove one ArrayType layer from the type for each subscript expression. 560 Expression * addressee = addrExpr->get_arg(); 561 int numLayers = 0; 562 while ( UntypedExpr * untypedExpr = dynamic_cast< UntypedExpr * >( addressee ) ) { 563 assert( InitTweak::getFunctionName( untypedExpr ) == "?[?]" ); 564 addressee = InitTweak::getCallArg( untypedExpr, 0 ); 565 numLayers++; 566 } 567 assert( addressee->get_results().size() == 1 ); 568 Type * type = addressee->get_results().front(); 569 for ( int i = 0; i < numLayers; i++ ) { 570 type = InitTweak::getPointerBase( type ); 571 assert( type && "Expected pointer or array type. May have generated too many ?[?] calls." ); 572 } 573 559 574 // cast to T* with qualifiers removed. 560 575 // unfortunately, lvalue is considered a qualifier. For AddressExpr to resolve, its argument … … 562 577 // remove lvalue as a qualifier, this can change to 563 578 // 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 ); 579 assert( type ); 580 type = type->clone(); 581 type->get_qualifiers() -= Type::Qualifiers(true, true, true, false, true, true); 582 type = new PointerType( Type::Qualifiers(), type ); 569 583 constructee = new CastExpr( constructee, type ); 570 584 -
src/SymTab/Autogen.cc
r31e46b8 rccb447e 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 … … 220 190 221 191 // 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() ) ); 192 UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) ); 193 derefExpr->get_args().push_back( new VariableExpr( dstParam ) ); 194 Expression *dstselect = new MemberExpr( field, derefExpr ); 195 genImplicitCall( src, dstselect, func->get_name(), back_inserter( func->get_statements()->get_kids() ), field, forward ); 196 197 if ( isGeneric && returnVal ) { 198 UntypedExpr *derefRet = new UntypedExpr( new NameExpr( "*?" ) ); 199 derefRet->get_args().push_back( new VariableExpr( returnVal ) ); 200 Expression *retselect = new MemberExpr( field, derefRet ); 201 genImplicitCall( src, retselect, func->get_name(), back_inserter( func->get_statements()->get_kids() ), field, forward ); 238 202 } // if 239 203 } -
src/SymTab/Autogen.h
r31e46b8 rccb447e 24 24 25 25 namespace SymTab { 26 27 26 /// Generates assignment operators, constructors, and destructor for aggregate types as required 27 void autogenerateRoutines( std::list< Declaration * > &translationUnit ); 28 28 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 29 /// returns true if obj's name is the empty string and it has a bitfield width 30 bool isUnnamedBitfield( ObjectDecl * obj ); 31 31 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" ); 32 /// size_t type - set when size_t typedef is seen. Useful in a few places, 33 /// such as in determining array dimension type 34 extern Type * SizeType; 37 35 38 // for a flexible array member nothing is done -- user must define own assignment 39 if ( ! array->get_dimension() ) return; 36 /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls. 37 template< typename OutputIterator > 38 void genCall( Expression * srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, bool forward = true ); 40 39 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( "--?" ); 40 /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Should only be called with non-array types. 41 template< typename OutputIterator > 42 void genScalarCall( Expression *srcParam, Expression *dstParam, const std::string & fname, OutputIterator out ) { 43 // want to be able to generate assignment, ctor, and dtor generically, 44 // so fname is either ?=?, ?{}, or ^?{} 45 UntypedExpr *fExpr = new UntypedExpr( new NameExpr( fname ) ); 46 47 // do something special for unnamed members 48 fExpr->get_args().push_back( new AddressExpr( dstParam ) ); 49 50 if ( srcParam ) { 51 fExpr->get_args().push_back( srcParam ); 52 } 53 54 *out++ = new ExprStmt( noLabels, fExpr ); 55 } 56 57 /// Store in out a loop which calls fname on each element of the array with srcParam and dstParam as arguments. 58 /// If forward is true, loop goes from 0 to N-1, else N-1 to 0 59 template< typename OutputIterator > 60 void genArrayCall( Expression *srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, ArrayType *array, bool forward = true ) { 61 static UniqueName indexName( "_index" ); 62 63 // for a flexible array member nothing is done -- user must define own assignment 64 if ( ! array->get_dimension() ) return ; 65 66 Expression * begin, * end, * update, * cmp; 67 if ( forward ) { 68 // generate: for ( int i = 0; i < 0; ++i ) 69 begin = new NameExpr( "0" ); 70 end = array->get_dimension()->clone(); 71 cmp = new NameExpr( "?<?" ); 72 update = new NameExpr( "++?" ); 73 } else { 74 // generate: for ( int i = N-1; i >= 0; --i ) 75 begin = new UntypedExpr( new NameExpr( "?-?" ) ); 76 ((UntypedExpr*)begin)->get_args().push_back( array->get_dimension()->clone() ); 77 ((UntypedExpr*)begin)->get_args().push_back( new NameExpr( "1" ) ); 78 end = new NameExpr( "0" ); 79 cmp = new NameExpr( "?>=?" ); 80 update = new NameExpr( "--?" ); 81 } 82 83 ObjectDecl *index = new ObjectDecl( indexName.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), NULL ); 84 85 UntypedExpr *init = new UntypedExpr( new NameExpr( "?=?" ) ); 86 init->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) ); 87 init->get_args().push_back( begin ); 88 index->set_init( new SingleInit( init, std::list<Expression*>() ) ); 89 90 UntypedExpr *cond = new UntypedExpr( cmp ); 91 cond->get_args().push_back( new VariableExpr( index ) ); 92 cond->get_args().push_back( end ); 93 94 UntypedExpr *inc = new UntypedExpr( update ); 95 inc->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) ); 96 97 UntypedExpr *dstIndex = new UntypedExpr( new NameExpr( "?[?]" ) ); 98 dstIndex->get_args().push_back( dstParam ); 99 dstIndex->get_args().push_back( new VariableExpr( index ) ); 100 dstParam = dstIndex; 101 102 // srcParam is NULL for default ctor/dtor 103 if ( srcParam ) { 104 UntypedExpr *srcIndex = new UntypedExpr( new NameExpr( "?[?]" ) ); 105 srcIndex->get_args().push_back( srcParam ); 106 srcIndex->get_args().push_back( new VariableExpr( index ) ); 107 srcParam = srcIndex; 108 } 109 110 // for stmt's body, eventually containing call 111 CompoundStmt * body = new CompoundStmt( noLabels ); 112 genCall( srcParam, dstParam, fname, back_inserter( body->get_kids() ), array->get_base(), forward ); 113 114 // block containing for stmt and index variable 115 std::list<Statement *> initList; 116 CompoundStmt * block = new CompoundStmt( noLabels ); 117 block->get_kids().push_back( new DeclStmt( noLabels, index ) ); 118 block->get_kids().push_back( new ForStmt( noLabels, initList, cond, inc, body ) ); 119 120 *out++ = block; 121 } 122 123 template< typename OutputIterator > 124 void genCall( Expression * srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, bool forward ) { 125 if ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) { 126 genArrayCall( srcParam, dstParam, fname, out, at, forward ); 127 } else { 128 genScalarCall( srcParam, dstParam, fname, out ); 129 } 130 } 131 132 /// inserts into out a generated call expression to function fname with arguments dstParam 133 /// and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls. decl is the 134 /// object being constructed. The function wraps constructor and destructor calls in an 135 /// ImplicitCtorDtorStmt node. 136 template< typename OutputIterator > 137 void genImplicitCall( Expression * srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, DeclarationWithType * decl, bool forward = true ) { 138 ObjectDecl *obj = dynamic_cast<ObjectDecl *>( decl ); 139 assert( obj ); 140 // unnamed bit fields are not copied as they cannot be accessed 141 if ( isUnnamedBitfield( obj ) ) return; 142 143 std::list< Statement * > stmts; 144 genCall( srcParam, dstParam, fname, back_inserter( stmts ), obj->get_type(), forward ); 145 146 // 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 147 assert( stmts.size() <= 1 ); 148 if ( stmts.size() == 1 ) { 149 Statement * callStmt = stmts.front(); 150 if ( (fname == "?{}" || fname == "^?{}") && ( !obj || ( obj && obj->get_bitfieldWidth() == NULL ) ) ) { 151 // implicitly generated ctor/dtor calls should be wrapped 152 // so that later passes are aware they were generated. 153 // xxx - don't mark as an implicit ctor/dtor if obj is a bitfield, 154 // because this causes the address to be taken at codegen, which is illegal in C. 155 callStmt = new ImplicitCtorDtorStmt( callStmt ); 156 } 157 *out++ = callStmt; 56 158 } 57 58 ObjectDecl *index = new ObjectDecl( indexName.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), NULL ); 59 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*>() ) ); 64 65 UntypedExpr *cond = new UntypedExpr( cmp ); 66 cond->get_args().push_back( new VariableExpr( index ) ); 67 cond->get_args().push_back( end ); 68 69 UntypedExpr *inc = new UntypedExpr( update ); 70 inc->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) ); 71 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 ) ); 75 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 ); 80 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 } 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 } 159 } 102 160 } // namespace SymTab 103 161 #endif // AUTOGEN_H -
src/SymTab/FixFunction.cc
r31e46b8 rccb447e 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
r31e46b8 rccb447e 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/main.cc
r31e46b8 rccb447e 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
r31e46b8 rccb447e 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 }
Note: See TracChangeset
for help on using the changeset viewer.