source: src/InitTweak/InitTweak.cc @ 39f84a4

aaron-thesisarm-ehcleanup-dtorsctordeferred_resndemanglerjacob/cs343-translationjenkins-sandboxmemorynew-astnew-ast-unique-exprnew-envno_listpersistent-indexerresolv-newwith_gc
Last change on this file since 39f84a4 was 39f84a4, checked in by Rob Schluntz <rschlunt@…>, 5 years ago

part-way through reorganizing ctor call generation so that it is more general

  • Property mode set to 100644
File size: 11.9 KB
Line 
1#include "InitTweak.h"
2#include "SynTree/Visitor.h"
3#include "SynTree/Statement.h"
4#include "SynTree/Initializer.h"
5#include "SynTree/Expression.h"
6#include "GenPoly/GenPoly.h"
7
8namespace InitTweak {
9        namespace {
10                class HasDesignations : public Visitor {
11                public:
12                        bool hasDesignations = false;
13                        template<typename Init>
14                        void handleInit( Init * init ) {
15                                if ( ! init->get_designators().empty() ) hasDesignations = true;
16                                else Visitor::visit( init );
17                        }
18                        virtual void visit( SingleInit * singleInit ) { handleInit( singleInit); }
19                        virtual void visit( ListInit * listInit ) { handleInit( listInit); }
20                };
21
22                class InitExpander_OLD : public Visitor {
23                        public:
24                        virtual void visit( SingleInit * singleInit );
25                        virtual void visit( ListInit * listInit );
26                        std::list< Expression * > argList;
27                };
28
29                void InitExpander_OLD::visit( SingleInit * singleInit ) {
30                        argList.push_back( singleInit->get_value()->clone() );
31                }
32
33                void InitExpander_OLD::visit( ListInit * listInit ) {
34                        // xxx - for now, assume no nested list inits
35                        std::list<Initializer*>::iterator it = listInit->begin_initializers();
36                        for ( ; it != listInit->end_initializers(); ++it ) {
37                                (*it)->accept( *this );
38                        }
39                }
40        }
41
42        std::list< Expression * > makeInitList( Initializer * init ) {
43                InitExpander_OLD expander;
44                maybeAccept( init, expander );
45                return expander.argList;
46        }
47
48        bool isDesignated( Initializer * init ) {
49                HasDesignations finder;
50                maybeAccept( init, finder );
51                return finder.hasDesignations;
52        }
53
54        class InitExpander::ExpanderImpl {
55        public:
56                virtual std::list< Expression * > next( std::list< Expression * > & indices ) = 0;
57        };
58
59        class InitImpl : public InitExpander::ExpanderImpl {
60        public:
61                InitImpl( Initializer * init ) {
62                        if ( init ) inits.push_back( init );
63                }
64
65                virtual std::list< Expression * > next( std::list< Expression * > & indices ) {
66                        // this is wrong, but just a placeholder for now
67                        return ! inits.empty() ? makeInitList( inits.front() ) : std::list< Expression * >();
68                }
69        private:
70                std::list< Initializer * > inits;
71        };
72
73        class ExprImpl : public InitExpander::ExpanderImpl {
74        public:
75                ExprImpl( Expression * expr ) : arg( expr ) {}
76
77                virtual std::list< Expression * > next( std::list< Expression * > & indices ) {
78                        std::list< Expression * > ret;
79                        Expression * expr = maybeClone( arg );
80                        if ( expr ) {
81                                for ( std::list< Expression * >::reverse_iterator it = indices.rbegin(); it != indices.rend(); ++it ) {
82                                        // go through indices and layer on subscript exprs ?[?]
83                                        ++it;
84                                        UntypedExpr * subscriptExpr = new UntypedExpr( new NameExpr( "?[?]") );
85                                        subscriptExpr->get_args().push_back( expr );
86                                        subscriptExpr->get_args().push_back( (*it)->clone() );
87                                        expr = subscriptExpr;
88                                }
89                                ret.push_back( expr );
90                        }
91                        return ret;
92                }
93        private:
94                Expression * arg;
95        };
96
97        InitExpander::InitExpander( Initializer * init ) : expander( new InitImpl( init ) ) {}
98
99        InitExpander::InitExpander( Expression * expr ) : expander( new ExprImpl( expr ) ) {}
100
101        std::list< Expression * > InitExpander::operator*() {
102                return cur;
103        }
104
105        InitExpander & InitExpander::operator++() {
106                cur = expander->next( indices );
107                return *this;
108        }
109
110        // use array indices list to build switch statement
111        void InitExpander::addArrayIndex( Expression * index, Expression * dimension ) {
112                indices.push_back( index );
113                indices.push_back( dimension );
114        }
115
116        template< typename OutIterator >
117        void build( UntypedExpr * callExpr, InitExpander::IndexList::iterator idx, InitExpander::IndexList::iterator end, OutIterator out ) {
118                if ( idx == end ) return;
119                Expression * index = *idx++;
120                assert( idx != end );
121                Expression * dimension = *idx++;
122
123                // if ( idx == end ) {
124                //      // loop through list of expressions belonging to the current initializer
125                //      UntypedExpr * cond = new UntypedExpr( new NameExpr( "?<?") );
126                //      cond->get_args().push_back( index->clone() );
127                //      cond->get_args().push_back( dimension->clone() );
128
129                //      UntypedExpr * call = callExpr->clone();
130                //      std::list< Expression * > args = *++expander; // xxx - need a way to indentify the end of an init list
131                //      call->get_args().splice( args );
132
133                //      *out++ = new IfStmt( noLabels, cond, new ExprStmt( call ), NULL );
134
135                //      UntypedExpr * increment = new UntypedExpr( new NameExpr( "++?" ) );
136                //      increment->get_args().push_back( index->clone() );
137                //      *out++ = new ExprStmt( increment );
138                // } else {
139                //      std::list< Statement * > branches;
140                //      for (...) { // loop over conditions?
141                //              std::list< Statement * > stmts;
142                //              build( idx, end, back_inserter( stmts ) );
143                //              CaseStmt * caseStmt = new CaseStmt( noLabels, condition, stmts );
144                //              branches.push_back( caseStmt );
145                //      }
146                //      *out++ = new SwitchStmt( noLabels, index->clone(), branches );
147                // }
148        }
149
150        // generate switch statement, consuming all of expander's elements
151        Statement * InitExpander::buildListInit( UntypedExpr * dst ) {
152                std::list< Statement * > results;
153                build( dst, indices.begin(), indices.end(), back_inserter( results ) );
154                assert( results.size() <= 1 );
155                return ! results.empty() ? results.front() : NULL;
156        }
157
158        bool tryConstruct( ObjectDecl * objDecl ) {
159                return ! LinkageSpec::isBuiltin( objDecl->get_linkage() ) &&
160                        (objDecl->get_init() == NULL ||
161                                ( objDecl->get_init() != NULL && objDecl->get_init()->get_maybeConstructed() )) &&
162                        ! isDesignated( objDecl->get_init() )
163                        && objDecl->get_storageClass() != DeclarationNode::Extern;
164        }
165
166        Expression * getCtorDtorCall( Statement * stmt ) {
167                if ( stmt == NULL ) return NULL;
168                if ( ExprStmt * exprStmt = dynamic_cast< ExprStmt * >( stmt ) ) {
169                        return exprStmt->get_expr();
170                } else if ( CompoundStmt * compoundStmt = dynamic_cast< CompoundStmt * >( stmt ) ) {
171                        // could also be a compound statement with a loop, in the case of an array
172                        if( compoundStmt->get_kids().size() == 2 ) {
173                                // loop variable and loop
174                                ForStmt * forStmt = dynamic_cast< ForStmt * >( compoundStmt->get_kids().back() );
175                                assert( forStmt && forStmt->get_body() );
176                                return getCtorDtorCall( forStmt->get_body() );
177                        } else if ( compoundStmt->get_kids().size() == 1 ) {
178                                // should be the call statement, but in any case there's only one option
179                                return getCtorDtorCall( compoundStmt->get_kids().front() );
180                        } else {
181                                assert( false && "too many statements in compoundStmt for getCtorDtorCall" );
182                        }
183                } if ( ImplicitCtorDtorStmt * impCtorDtorStmt = dynamic_cast< ImplicitCtorDtorStmt * > ( stmt ) ) {
184                        return getCtorDtorCall( impCtorDtorStmt->get_callStmt() );
185                } else {
186                        // should never get here
187                        assert( false && "encountered unknown call statement" );
188                }
189        }
190        namespace {
191                VariableExpr * getCalledFunction( ApplicationExpr * appExpr ) {
192                        assert( appExpr );
193                        return dynamic_cast< VariableExpr * >( appExpr->get_function() );
194                }
195        }
196
197        ApplicationExpr * isIntrinsicCallExpr( Expression * expr ) {
198                ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr );
199                if ( ! appExpr ) return NULL;
200                VariableExpr * function = getCalledFunction( appExpr );
201                assert( function );
202                // check for Intrinsic only - don't want to remove all overridable ctor/dtors because autogenerated ctor/dtor
203                // will call all member dtors, and some members may have a user defined dtor.
204                return function->get_var()->get_linkage() == LinkageSpec::Intrinsic ? appExpr : NULL;
205        }
206
207        bool isInstrinsicSingleArgCallStmt( Statement * stmt ) {
208                Expression * callExpr = getCtorDtorCall( stmt );
209                if ( ! callExpr ) return false;
210                if ( ApplicationExpr * appExpr = isIntrinsicCallExpr( callExpr ) ) {
211                        assert( ! appExpr->get_function()->get_results().empty() );
212                        FunctionType *funcType = GenPoly::getFunctionType( appExpr->get_function()->get_results().front() );
213                        assert( funcType );
214                        return funcType->get_parameters().size() == 1;
215                }
216                return false;
217        }
218
219        namespace {
220                template<typename CallExpr>
221                Expression *& callArg( CallExpr * callExpr, unsigned int pos ) {
222                        if ( pos >= callExpr->get_args().size() ) assert( false && "asking for argument that doesn't exist. Return NULL/throw exception?" );
223                        for ( Expression *& arg : callExpr->get_args() ) {
224                                if ( pos == 0 ) return arg;
225                                pos--;
226                        }
227                        assert( false );
228                }
229        }
230
231        Expression *& getCallArg( Expression * callExpr, unsigned int pos ) {
232                if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( callExpr ) ) {
233                        return callArg( appExpr, pos );
234                } else if ( UntypedExpr * untypedExpr = dynamic_cast< UntypedExpr * >( callExpr ) ) {
235                        return callArg( untypedExpr, pos );
236                } else {
237                        assert( false && "Unexpected expression type passed to getCallArg" );
238                }
239        }
240
241        namespace {
242                std::string funcName( Expression * func ) {
243                        if ( NameExpr * nameExpr = dynamic_cast< NameExpr * >( func ) ) {
244                                return nameExpr->get_name();
245                        } else if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( func ) ) {
246                                return varExpr->get_var()->get_name();
247                        }       else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( func ) ) {
248                                return funcName( castExpr->get_arg() );
249                        } else {
250                                assert( false && "Unexpected expression type being called as a function in call expression" );
251                        }
252                }
253        }
254
255        std::string getFunctionName( Expression * expr ) {
256                if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr ) ) {
257                        return funcName( appExpr->get_function() );
258                } else if ( UntypedExpr * untypedExpr = dynamic_cast< UntypedExpr * > ( expr ) ) {
259                        return funcName( untypedExpr->get_function() );
260                } else {
261                        std::cerr << expr << std::endl;
262                        assert( false && "Unexpected expression type passed to getFunctionName" );
263                }
264        }
265
266        Type * getPointerBase( Type * type ) {
267                if ( PointerType * ptrType = dynamic_cast< PointerType * >( type ) ) {
268                        return ptrType->get_base();
269                } else if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) {
270                        return arrayType->get_base();
271                } else {
272                        return NULL;
273                }
274        }
275
276        Type * isPointerType( Type * type ) {
277                if ( getPointerBase( type ) ) return type;
278                else return NULL;
279        }
280
281        class ConstExprChecker : public Visitor {
282        public:
283                ConstExprChecker() : isConstExpr( true ) {}
284
285                virtual void visit( ApplicationExpr *applicationExpr ) { isConstExpr = false; }
286                virtual void visit( UntypedExpr *untypedExpr ) { isConstExpr = false; }
287                virtual void visit( NameExpr *nameExpr ) { isConstExpr = false; }
288                virtual void visit( CastExpr *castExpr ) { isConstExpr = false; }
289                virtual void visit( LabelAddressExpr *labAddressExpr ) { isConstExpr = false; }
290                virtual void visit( UntypedMemberExpr *memberExpr ) { isConstExpr = false; }
291                virtual void visit( MemberExpr *memberExpr ) { isConstExpr = false; }
292                virtual void visit( VariableExpr *variableExpr ) { isConstExpr = false; }
293                virtual void visit( ConstantExpr *constantExpr ) { /* bottom out */ }
294                // these might be okay?
295                // virtual void visit( SizeofExpr *sizeofExpr );
296                // virtual void visit( AlignofExpr *alignofExpr );
297                // virtual void visit( UntypedOffsetofExpr *offsetofExpr );
298                // virtual void visit( OffsetofExpr *offsetofExpr );
299                // virtual void visit( OffsetPackExpr *offsetPackExpr );
300                // virtual void visit( AttrExpr *attrExpr );
301                // virtual void visit( CommaExpr *commaExpr );
302                // virtual void visit( LogicalExpr *logicalExpr );
303                // virtual void visit( ConditionalExpr *conditionalExpr );
304                virtual void visit( TupleExpr *tupleExpr ) { isConstExpr = false; }
305                virtual void visit( SolvedTupleExpr *tupleExpr ) { isConstExpr = false; }
306                virtual void visit( TypeExpr *typeExpr ) { isConstExpr = false; }
307                virtual void visit( AsmExpr *asmExpr ) { isConstExpr = false; }
308                virtual void visit( UntypedValofExpr *valofExpr ) { isConstExpr = false; }
309                virtual void visit( CompoundLiteralExpr *compLitExpr ) { isConstExpr = false; }
310
311                bool isConstExpr;
312        };
313
314        bool isConstExpr( Expression * expr ) {
315                if ( expr ) {
316                        ConstExprChecker checker;
317                        expr->accept( checker );
318                        return checker.isConstExpr;
319                }
320                return true;
321        }
322
323        bool isConstExpr( Initializer * init ) {
324                if ( init ) {
325                        ConstExprChecker checker;
326                        init->accept( checker );
327                        return checker.isConstExpr;
328                } // if
329                // for all intents and purposes, no initializer means const expr
330                return true;
331        }
332
333}
Note: See TracBrowser for help on using the repository browser.