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

ADT aaron-thesis arm-eh ast-experimental cleanup-dtors ctor deferred_resn demangler enum forall-pointer-decay jacob/cs343-translation jenkins-sandbox memory new-ast new-ast-unique-expr new-env no_list persistent-indexer pthread-emulation qualifiedEnum resolv-new stuck-waitfor-destruct with_gc
Last change on this file since 39f84a4 was 39f84a4, checked in by Rob Schluntz <rschlunt@…>, 10 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.