Mercurial > projects > ldc
annotate dmd/inline.c @ 1351:8d501abecd24
Initial (but disabled) fix for ticket #294 , the actual part that fixes the bug is in a #if 0 block as I'm afraid it will cause regressions. I'm most likely not going to be around tonight, and maybe not tomorrow as well, so I'm pushing it in case someone wants to run some serious testing/investigate the problem noted in llvmhelpers.cpp : realignOffset .
author | Tomas Lindquist Olsen <tomas.l.olsen gmail com> |
---|---|
date | Thu, 14 May 2009 17:20:17 +0200 |
parents | 1860414bf3b7 |
children | 8026319762be |
rev | line source |
---|---|
1 | 1 |
2 // Copyright (c) 1999-2007 by Digital Mars | |
3 // All Rights Reserved | |
4 // written by Walter Bright | |
5 // http://www.digitalmars.com | |
6 // License for redistribution is by either the Artistic License | |
7 // in artistic.txt, or the GNU General Public License in gnu.txt. | |
8 // See the included readme.txt for details. | |
9 | |
10 // Routines to perform function inlining | |
11 | |
12 #define LOG 0 | |
13 | |
14 #include <stdio.h> | |
15 #include <stdlib.h> | |
16 #include <assert.h> | |
17 | |
18 #include "id.h" | |
19 #include "init.h" | |
20 #include "declaration.h" | |
21 #include "aggregate.h" | |
22 #include "expression.h" | |
23 #include "statement.h" | |
24 #include "mtype.h" | |
25 | |
26 /* ========== Compute cost of inlining =============== */ | |
27 | |
28 /* Walk trees to determine if inlining can be done, and if so, | |
29 * if it is too complex to be worth inlining or not. | |
30 */ | |
31 | |
32 struct InlineCostState | |
33 { | |
34 int nested; | |
35 int hasthis; | |
36 int hdrscan; // !=0 if inline scan for 'header' content | |
37 FuncDeclaration *fd; | |
38 }; | |
39 | |
40 const int COST_MAX = 250; | |
41 | |
42 int Statement::inlineCost(InlineCostState *ics) | |
43 { | |
44 return COST_MAX; // default is we can't inline it | |
45 } | |
46 | |
47 int ExpStatement::inlineCost(InlineCostState *ics) | |
48 { | |
49 return exp ? exp->inlineCost(ics) : 0; | |
50 } | |
51 | |
52 int CompoundStatement::inlineCost(InlineCostState *ics) | |
53 { int cost = 0; | |
54 | |
55 for (size_t i = 0; i < statements->dim; i++) | |
56 { Statement *s = (Statement *) statements->data[i]; | |
57 if (s) | |
58 { | |
59 cost += s->inlineCost(ics); | |
60 if (cost >= COST_MAX) | |
61 break; | |
62 } | |
63 } | |
64 return cost; | |
65 } | |
66 | |
67 int UnrolledLoopStatement::inlineCost(InlineCostState *ics) | |
68 { int cost = 0; | |
69 | |
70 for (size_t i = 0; i < statements->dim; i++) | |
71 { Statement *s = (Statement *) statements->data[i]; | |
72 if (s) | |
73 { | |
74 cost += s->inlineCost(ics); | |
75 if (cost >= COST_MAX) | |
76 break; | |
77 } | |
78 } | |
79 return cost; | |
80 } | |
81 | |
82 int IfStatement::inlineCost(InlineCostState *ics) | |
83 { | |
84 int cost; | |
85 | |
86 /* Can't declare variables inside ?: expressions, so | |
87 * we cannot inline if a variable is declared. | |
88 */ | |
89 if (arg) | |
90 return COST_MAX; | |
91 | |
92 cost = condition->inlineCost(ics); | |
93 | |
94 /* Specifically allow: | |
95 * if (condition) | |
96 * return exp1; | |
97 * else | |
98 * return exp2; | |
99 * Otherwise, we can't handle return statements nested in if's. | |
100 */ | |
101 | |
102 if (elsebody && ifbody && | |
103 ifbody->isReturnStatement() && | |
104 elsebody->isReturnStatement()) | |
105 { | |
106 cost += ifbody->inlineCost(ics); | |
107 cost += elsebody->inlineCost(ics); | |
108 //printf("cost = %d\n", cost); | |
109 } | |
110 else | |
111 { | |
112 ics->nested += 1; | |
113 if (ifbody) | |
114 cost += ifbody->inlineCost(ics); | |
115 if (elsebody) | |
116 cost += elsebody->inlineCost(ics); | |
117 ics->nested -= 1; | |
118 } | |
119 return cost; | |
120 } | |
121 | |
122 int ReturnStatement::inlineCost(InlineCostState *ics) | |
123 { | |
124 // Can't handle return statements nested in if's | |
125 if (ics->nested) | |
126 return COST_MAX; | |
127 return exp ? exp->inlineCost(ics) : 0; | |
128 } | |
129 | |
130 /* -------------------------- */ | |
131 | |
132 int arrayInlineCost(InlineCostState *ics, Array *arguments) | |
133 { int cost = 0; | |
134 | |
135 if (arguments) | |
136 { | |
137 for (int i = 0; i < arguments->dim; i++) | |
138 { Expression *e = (Expression *)arguments->data[i]; | |
139 | |
140 if (e) | |
141 cost += e->inlineCost(ics); | |
142 } | |
143 } | |
144 return cost; | |
145 } | |
146 | |
147 int Expression::inlineCost(InlineCostState *ics) | |
148 { | |
149 return 1; | |
150 } | |
151 | |
152 int VarExp::inlineCost(InlineCostState *ics) | |
153 { | |
154 //printf("VarExp::inlineCost() %s\n", toChars()); | |
155 return 1; | |
156 } | |
157 | |
158 int ThisExp::inlineCost(InlineCostState *ics) | |
159 { | |
160 FuncDeclaration *fd = ics->fd; | |
161 if (!ics->hdrscan) | |
162 if (fd->isNested() || !ics->hasthis) | |
163 return COST_MAX; | |
164 return 1; | |
165 } | |
166 | |
167 int SuperExp::inlineCost(InlineCostState *ics) | |
168 { | |
169 FuncDeclaration *fd = ics->fd; | |
170 if (!ics->hdrscan) | |
171 if (fd->isNested() || !ics->hasthis) | |
172 return COST_MAX; | |
173 return 1; | |
174 } | |
175 | |
176 int TupleExp::inlineCost(InlineCostState *ics) | |
177 { | |
178 return 1 + arrayInlineCost(ics, exps); | |
179 } | |
180 | |
181 int ArrayLiteralExp::inlineCost(InlineCostState *ics) | |
182 { | |
183 return 1 + arrayInlineCost(ics, elements); | |
184 } | |
185 | |
186 int AssocArrayLiteralExp::inlineCost(InlineCostState *ics) | |
187 { | |
188 return 1 + arrayInlineCost(ics, keys) + arrayInlineCost(ics, values); | |
189 } | |
190 | |
191 int StructLiteralExp::inlineCost(InlineCostState *ics) | |
192 { | |
193 return 1 + arrayInlineCost(ics, elements); | |
194 } | |
195 | |
196 int FuncExp::inlineCost(InlineCostState *ics) | |
197 { | |
198 // Right now, this makes the function be output to the .obj file twice. | |
199 return COST_MAX; | |
200 } | |
201 | |
202 int DelegateExp::inlineCost(InlineCostState *ics) | |
203 { | |
204 return COST_MAX; | |
205 } | |
206 | |
207 int DeclarationExp::inlineCost(InlineCostState *ics) | |
208 { int cost = 0; | |
209 VarDeclaration *vd; | |
210 | |
211 //printf("DeclarationExp::inlineCost()\n"); | |
212 vd = declaration->isVarDeclaration(); | |
213 if (vd) | |
214 { | |
215 TupleDeclaration *td = vd->toAlias()->isTupleDeclaration(); | |
216 if (td) | |
217 { | |
218 #if 1 | |
219 return COST_MAX; // finish DeclarationExp::doInline | |
220 #else | |
221 for (size_t i = 0; i < td->objects->dim; i++) | |
222 { Object *o = (Object *)td->objects->data[i]; | |
223 if (o->dyncast() != DYNCAST_EXPRESSION) | |
224 return COST_MAX; | |
225 Expression *eo = (Expression *)o; | |
226 if (eo->op != TOKdsymbol) | |
227 return COST_MAX; | |
228 } | |
229 return td->objects->dim; | |
230 #endif | |
231 } | |
232 if (!ics->hdrscan && vd->isDataseg()) | |
233 return COST_MAX; | |
234 cost += 1; | |
235 | |
236 // Scan initializer (vd->init) | |
237 if (vd->init) | |
238 { | |
239 ExpInitializer *ie = vd->init->isExpInitializer(); | |
240 | |
241 if (ie) | |
242 { | |
243 cost += ie->exp->inlineCost(ics); | |
244 } | |
245 } | |
246 } | |
247 | |
248 // These can contain functions, which when copied, get output twice. | |
249 if (declaration->isStructDeclaration() || | |
250 declaration->isClassDeclaration() || | |
251 declaration->isFuncDeclaration() || | |
252 declaration->isTypedefDeclaration() || | |
253 declaration->isTemplateMixin()) | |
254 return COST_MAX; | |
255 | |
256 //printf("DeclarationExp::inlineCost('%s')\n", toChars()); | |
257 return cost; | |
258 } | |
259 | |
260 int UnaExp::inlineCost(InlineCostState *ics) | |
261 { | |
262 return 1 + e1->inlineCost(ics); | |
263 } | |
264 | |
265 int AssertExp::inlineCost(InlineCostState *ics) | |
266 { | |
267 return 1 + e1->inlineCost(ics) + (msg ? msg->inlineCost(ics) : 0); | |
268 } | |
269 | |
270 int BinExp::inlineCost(InlineCostState *ics) | |
271 { | |
272 return 1 + e1->inlineCost(ics) + e2->inlineCost(ics); | |
273 } | |
274 | |
275 int CallExp::inlineCost(InlineCostState *ics) | |
276 { | |
277 return 1 + e1->inlineCost(ics) + arrayInlineCost(ics, arguments); | |
278 } | |
279 | |
280 int SliceExp::inlineCost(InlineCostState *ics) | |
281 { int cost; | |
282 | |
283 cost = 1 + e1->inlineCost(ics); | |
284 if (lwr) | |
285 cost += lwr->inlineCost(ics); | |
286 if (upr) | |
287 cost += upr->inlineCost(ics); | |
288 return cost; | |
289 } | |
290 | |
291 int ArrayExp::inlineCost(InlineCostState *ics) | |
292 { | |
293 return 1 + e1->inlineCost(ics) + arrayInlineCost(ics, arguments); | |
294 } | |
295 | |
296 | |
297 int CondExp::inlineCost(InlineCostState *ics) | |
298 { | |
299 return 1 + | |
300 e1->inlineCost(ics) + | |
301 e2->inlineCost(ics) + | |
302 econd->inlineCost(ics); | |
303 } | |
304 | |
305 | |
306 /* ======================== Perform the inlining ============================== */ | |
307 | |
308 /* Inlining is done by: | |
309 * o Converting to an Expression | |
310 * o Copying the trees of the function to be inlined | |
311 * o Renaming the variables | |
312 */ | |
313 | |
314 struct InlineDoState | |
315 { | |
316 VarDeclaration *vthis; | |
317 Array from; // old Dsymbols | |
318 Array to; // parallel array of new Dsymbols | |
319 Dsymbol *parent; // new parent | |
320 }; | |
321 | |
322 Expression *Statement::doInline(InlineDoState *ids) | |
323 { | |
324 assert(0); | |
325 return NULL; // default is we can't inline it | |
326 } | |
327 | |
328 Expression *ExpStatement::doInline(InlineDoState *ids) | |
329 { | |
330 #if LOG | |
331 if (exp) printf("ExpStatement::doInline() '%s'\n", exp->toChars()); | |
332 #endif | |
333 return exp ? exp->doInline(ids) : NULL; | |
334 } | |
335 | |
336 Expression *CompoundStatement::doInline(InlineDoState *ids) | |
337 { | |
338 Expression *e = NULL; | |
339 | |
340 //printf("CompoundStatement::doInline() %d\n", statements->dim); | |
341 for (size_t i = 0; i < statements->dim; i++) | |
342 { Statement *s = (Statement *) statements->data[i]; | |
343 if (s) | |
344 { | |
345 Expression *e2 = s->doInline(ids); | |
346 e = Expression::combine(e, e2); | |
347 if (s->isReturnStatement()) | |
348 break; | |
349 | |
350 /* Check for: | |
351 * if (condition) | |
352 * return exp1; | |
353 * else | |
354 * return exp2; | |
355 */ | |
356 IfStatement *ifs = s->isIfStatement(); | |
357 if (ifs && ifs->elsebody && ifs->ifbody && | |
358 ifs->ifbody->isReturnStatement() && | |
359 ifs->elsebody->isReturnStatement() | |
360 ) | |
361 break; | |
362 | |
363 } | |
364 } | |
365 return e; | |
366 } | |
367 | |
368 Expression *UnrolledLoopStatement::doInline(InlineDoState *ids) | |
369 { | |
370 Expression *e = NULL; | |
371 | |
372 //printf("UnrolledLoopStatement::doInline() %d\n", statements->dim); | |
373 for (size_t i = 0; i < statements->dim; i++) | |
374 { Statement *s = (Statement *) statements->data[i]; | |
375 if (s) | |
376 { | |
377 Expression *e2 = s->doInline(ids); | |
378 e = Expression::combine(e, e2); | |
379 if (s->isReturnStatement()) | |
380 break; | |
381 } | |
382 } | |
383 return e; | |
384 } | |
385 | |
386 Expression *IfStatement::doInline(InlineDoState *ids) | |
387 { | |
388 Expression *econd; | |
389 Expression *e1; | |
390 Expression *e2; | |
391 Expression *e; | |
392 | |
393 assert(!arg); | |
394 econd = condition->doInline(ids); | |
395 assert(econd); | |
396 if (ifbody) | |
397 e1 = ifbody->doInline(ids); | |
398 else | |
399 e1 = NULL; | |
400 if (elsebody) | |
401 e2 = elsebody->doInline(ids); | |
402 else | |
403 e2 = NULL; | |
404 if (e1 && e2) | |
405 { | |
406 e = new CondExp(econd->loc, econd, e1, e2); | |
407 e->type = e1->type; | |
408 } | |
409 else if (e1) | |
410 { | |
411 e = new AndAndExp(econd->loc, econd, e1); | |
412 e->type = Type::tvoid; | |
413 } | |
414 else if (e2) | |
415 { | |
416 e = new OrOrExp(econd->loc, econd, e2); | |
417 e->type = Type::tvoid; | |
418 } | |
419 else | |
420 { | |
421 e = econd; | |
422 } | |
423 return e; | |
424 } | |
425 | |
426 Expression *ReturnStatement::doInline(InlineDoState *ids) | |
427 { | |
428 //printf("ReturnStatement::doInline() '%s'\n", exp ? exp->toChars() : ""); | |
429 return exp ? exp->doInline(ids) : 0; | |
430 } | |
431 | |
432 /* --------------------------------------------------------------- */ | |
433 | |
434 /****************************** | |
435 * Perform doInline() on an array of Expressions. | |
436 */ | |
437 | |
438 Expressions *arrayExpressiondoInline(Expressions *a, InlineDoState *ids) | |
439 { Expressions *newa = NULL; | |
440 | |
441 if (a) | |
442 { | |
443 newa = new Expressions(); | |
444 newa->setDim(a->dim); | |
445 | |
446 for (int i = 0; i < a->dim; i++) | |
447 { Expression *e = (Expression *)a->data[i]; | |
448 | |
449 if (e) | |
450 { | |
451 e = e->doInline(ids); | |
452 newa->data[i] = (void *)e; | |
453 } | |
454 } | |
455 } | |
456 return newa; | |
457 } | |
458 | |
459 Expression *Expression::doInline(InlineDoState *ids) | |
460 { | |
461 //printf("Expression::doInline(%s): %s\n", Token::toChars(op), toChars()); | |
462 return copy(); | |
463 } | |
464 | |
465 Expression *SymOffExp::doInline(InlineDoState *ids) | |
466 { | |
467 int i; | |
468 | |
469 //printf("SymOffExp::doInline(%s)\n", toChars()); | |
470 for (i = 0; i < ids->from.dim; i++) | |
471 { | |
472 if (var == (Declaration *)ids->from.data[i]) | |
473 { | |
474 SymOffExp *se = (SymOffExp *)copy(); | |
475 | |
476 se->var = (Declaration *)ids->to.data[i]; | |
477 return se; | |
478 } | |
479 } | |
480 return this; | |
481 } | |
482 | |
483 Expression *VarExp::doInline(InlineDoState *ids) | |
484 { | |
485 int i; | |
486 | |
487 //printf("VarExp::doInline(%s)\n", toChars()); | |
488 for (i = 0; i < ids->from.dim; i++) | |
489 { | |
490 if (var == (Declaration *)ids->from.data[i]) | |
491 { | |
492 VarExp *ve = (VarExp *)copy(); | |
493 | |
494 ve->var = (Declaration *)ids->to.data[i]; | |
495 return ve; | |
496 } | |
497 } | |
498 return this; | |
499 } | |
500 | |
501 Expression *ThisExp::doInline(InlineDoState *ids) | |
502 { | |
503 //if (!ids->vthis) | |
504 //error("no 'this' when inlining %s", ids->parent->toChars()); | |
505 if (!ids->vthis) | |
506 { | |
507 return this; | |
508 } | |
509 | |
510 VarExp *ve = new VarExp(loc, ids->vthis); | |
511 ve->type = type; | |
512 return ve; | |
513 } | |
514 | |
515 Expression *SuperExp::doInline(InlineDoState *ids) | |
516 { | |
517 assert(ids->vthis); | |
518 | |
519 VarExp *ve = new VarExp(loc, ids->vthis); | |
520 ve->type = type; | |
521 return ve; | |
522 } | |
523 | |
524 Expression *DeclarationExp::doInline(InlineDoState *ids) | |
525 { DeclarationExp *de = (DeclarationExp *)copy(); | |
526 VarDeclaration *vd; | |
527 | |
528 //printf("DeclarationExp::doInline(%s)\n", toChars()); | |
529 vd = declaration->isVarDeclaration(); | |
530 if (vd) | |
531 { | |
532 #if 0 | |
533 // Need to figure this out before inlining can work for tuples | |
534 TupleDeclaration *td = vd->toAlias()->isTupleDeclaration(); | |
535 if (td) | |
536 { | |
537 for (size_t i = 0; i < td->objects->dim; i++) | |
538 { DsymbolExp *se = (DsymbolExp *)td->objects->data[i]; | |
539 assert(se->op == TOKdsymbol); | |
540 se->s; | |
541 } | |
542 return st->objects->dim; | |
543 } | |
544 #endif | |
545 if (vd->isStatic() || vd->isConst()) | |
546 ; | |
547 else | |
548 { | |
549 VarDeclaration *vto; | |
550 | |
551 vto = new VarDeclaration(vd->loc, vd->type, vd->ident, vd->init); | |
552 *vto = *vd; | |
553 vto->parent = ids->parent; | |
1146
1860414bf3b7
* Moved ir/irsymbol.cpp/h into ir/irdsymbol.cpp/h.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
336
diff
changeset
|
554 #if IN_DMD |
1 | 555 vto->csym = NULL; |
556 vto->isym = NULL; | |
1146
1860414bf3b7
* Moved ir/irsymbol.cpp/h into ir/irdsymbol.cpp/h.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
336
diff
changeset
|
557 #endif |
1 | 558 |
559 ids->from.push(vd); | |
560 ids->to.push(vto); | |
561 | |
92 | 562 if (vd->init) |
1 | 563 { |
92 | 564 if (vd->init->isVoidInitializer()) |
565 { | |
566 vto->init = new VoidInitializer(vd->init->loc); | |
567 } | |
568 else | |
569 { | |
570 ExpInitializer *ie = vd->init->isExpInitializer(); | |
571 assert(ie); | |
572 vto->init = new ExpInitializer(ie->loc, ie->exp->doInline(ids)); | |
573 } | |
1 | 574 } |
575 de->declaration = (Dsymbol *) (void *)vto; | |
576 } | |
577 } | |
578 /* This needs work, like DeclarationExp::toElem(), if we are | |
579 * to handle TemplateMixin's. For now, we just don't inline them. | |
580 */ | |
581 return de; | |
582 } | |
583 | |
584 Expression *NewExp::doInline(InlineDoState *ids) | |
585 { | |
586 //printf("NewExp::doInline(): %s\n", toChars()); | |
587 NewExp *ne = (NewExp *)copy(); | |
588 | |
589 if (thisexp) | |
590 ne->thisexp = thisexp->doInline(ids); | |
591 ne->newargs = arrayExpressiondoInline(ne->newargs, ids); | |
592 ne->arguments = arrayExpressiondoInline(ne->arguments, ids); | |
593 return ne; | |
594 } | |
595 | |
596 Expression *UnaExp::doInline(InlineDoState *ids) | |
597 { | |
598 UnaExp *ue = (UnaExp *)copy(); | |
599 | |
600 ue->e1 = e1->doInline(ids); | |
601 return ue; | |
602 } | |
603 | |
604 Expression *AssertExp::doInline(InlineDoState *ids) | |
605 { | |
606 AssertExp *ae = (AssertExp *)copy(); | |
607 | |
608 ae->e1 = e1->doInline(ids); | |
609 if (msg) | |
610 ae->msg = msg->doInline(ids); | |
611 return ae; | |
612 } | |
613 | |
614 Expression *BinExp::doInline(InlineDoState *ids) | |
615 { | |
616 BinExp *be = (BinExp *)copy(); | |
617 | |
618 be->e1 = e1->doInline(ids); | |
619 be->e2 = e2->doInline(ids); | |
620 return be; | |
621 } | |
622 | |
623 Expression *CallExp::doInline(InlineDoState *ids) | |
624 { | |
625 CallExp *ce; | |
626 | |
627 ce = (CallExp *)copy(); | |
628 ce->e1 = e1->doInline(ids); | |
629 ce->arguments = arrayExpressiondoInline(arguments, ids); | |
630 return ce; | |
631 } | |
632 | |
633 | |
634 Expression *IndexExp::doInline(InlineDoState *ids) | |
635 { | |
636 IndexExp *are = (IndexExp *)copy(); | |
637 | |
638 are->e1 = e1->doInline(ids); | |
639 | |
640 if (lengthVar) | |
641 { //printf("lengthVar\n"); | |
642 VarDeclaration *vd = lengthVar; | |
643 ExpInitializer *ie; | |
644 ExpInitializer *ieto; | |
645 VarDeclaration *vto; | |
646 | |
647 vto = new VarDeclaration(vd->loc, vd->type, vd->ident, vd->init); | |
648 *vto = *vd; | |
649 vto->parent = ids->parent; | |
1146
1860414bf3b7
* Moved ir/irsymbol.cpp/h into ir/irdsymbol.cpp/h.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
336
diff
changeset
|
650 #if IN_DMD |
1 | 651 vto->csym = NULL; |
652 vto->isym = NULL; | |
1146
1860414bf3b7
* Moved ir/irsymbol.cpp/h into ir/irdsymbol.cpp/h.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
336
diff
changeset
|
653 #endif |
1 | 654 |
655 ids->from.push(vd); | |
656 ids->to.push(vto); | |
657 | |
658 if (vd->init) | |
659 { | |
660 ie = vd->init->isExpInitializer(); | |
661 assert(ie); | |
662 ieto = new ExpInitializer(ie->loc, ie->exp->doInline(ids)); | |
663 vto->init = ieto; | |
664 } | |
665 | |
666 are->lengthVar = (VarDeclaration *) (void *)vto; | |
667 } | |
668 are->e2 = e2->doInline(ids); | |
669 return are; | |
670 } | |
671 | |
672 | |
673 Expression *SliceExp::doInline(InlineDoState *ids) | |
674 { | |
675 SliceExp *are = (SliceExp *)copy(); | |
676 | |
677 are->e1 = e1->doInline(ids); | |
678 | |
679 if (lengthVar) | |
680 { //printf("lengthVar\n"); | |
681 VarDeclaration *vd = lengthVar; | |
682 ExpInitializer *ie; | |
683 ExpInitializer *ieto; | |
684 VarDeclaration *vto; | |
685 | |
686 vto = new VarDeclaration(vd->loc, vd->type, vd->ident, vd->init); | |
687 *vto = *vd; | |
688 vto->parent = ids->parent; | |
1146
1860414bf3b7
* Moved ir/irsymbol.cpp/h into ir/irdsymbol.cpp/h.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
336
diff
changeset
|
689 #if IN_DMD |
1 | 690 vto->csym = NULL; |
691 vto->isym = NULL; | |
1146
1860414bf3b7
* Moved ir/irsymbol.cpp/h into ir/irdsymbol.cpp/h.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
336
diff
changeset
|
692 #endif |
1 | 693 |
694 ids->from.push(vd); | |
695 ids->to.push(vto); | |
696 | |
697 if (vd->init) | |
698 { | |
699 ie = vd->init->isExpInitializer(); | |
700 assert(ie); | |
701 ieto = new ExpInitializer(ie->loc, ie->exp->doInline(ids)); | |
702 vto->init = ieto; | |
703 } | |
704 | |
705 are->lengthVar = (VarDeclaration *) (void *)vto; | |
706 } | |
707 if (lwr) | |
708 are->lwr = lwr->doInline(ids); | |
709 if (upr) | |
710 are->upr = upr->doInline(ids); | |
711 return are; | |
712 } | |
713 | |
714 | |
715 Expression *TupleExp::doInline(InlineDoState *ids) | |
716 { | |
717 TupleExp *ce; | |
718 | |
719 ce = (TupleExp *)copy(); | |
720 ce->exps = arrayExpressiondoInline(exps, ids); | |
721 return ce; | |
722 } | |
723 | |
724 | |
725 Expression *ArrayLiteralExp::doInline(InlineDoState *ids) | |
726 { | |
727 ArrayLiteralExp *ce; | |
728 | |
729 ce = (ArrayLiteralExp *)copy(); | |
730 ce->elements = arrayExpressiondoInline(elements, ids); | |
731 return ce; | |
732 } | |
733 | |
734 | |
735 Expression *AssocArrayLiteralExp::doInline(InlineDoState *ids) | |
736 { | |
737 AssocArrayLiteralExp *ce; | |
738 | |
739 ce = (AssocArrayLiteralExp *)copy(); | |
740 ce->keys = arrayExpressiondoInline(keys, ids); | |
741 ce->values = arrayExpressiondoInline(values, ids); | |
742 return ce; | |
743 } | |
744 | |
745 | |
746 Expression *StructLiteralExp::doInline(InlineDoState *ids) | |
747 { | |
748 StructLiteralExp *ce; | |
749 | |
750 ce = (StructLiteralExp *)copy(); | |
751 ce->elements = arrayExpressiondoInline(elements, ids); | |
752 return ce; | |
753 } | |
754 | |
755 | |
756 Expression *ArrayExp::doInline(InlineDoState *ids) | |
757 { | |
758 ArrayExp *ce; | |
759 | |
760 ce = (ArrayExp *)copy(); | |
761 ce->e1 = e1->doInline(ids); | |
762 ce->arguments = arrayExpressiondoInline(arguments, ids); | |
763 return ce; | |
764 } | |
765 | |
766 | |
767 Expression *CondExp::doInline(InlineDoState *ids) | |
768 { | |
769 CondExp *ce = (CondExp *)copy(); | |
770 | |
771 ce->econd = econd->doInline(ids); | |
772 ce->e1 = e1->doInline(ids); | |
773 ce->e2 = e2->doInline(ids); | |
774 return ce; | |
775 } | |
776 | |
777 | |
778 /* ========== Walk the parse trees, and inline expand functions ============= */ | |
779 | |
780 /* Walk the trees, looking for functions to inline. | |
781 * Inline any that can be. | |
782 */ | |
783 | |
784 struct InlineScanState | |
785 { | |
786 FuncDeclaration *fd; // function being scanned | |
787 }; | |
788 | |
789 Statement *Statement::inlineScan(InlineScanState *iss) | |
790 { | |
791 return this; | |
792 } | |
793 | |
794 Statement *ExpStatement::inlineScan(InlineScanState *iss) | |
795 { | |
796 #if LOG | |
797 printf("ExpStatement::inlineScan(%s)\n", toChars()); | |
798 #endif | |
799 if (exp) | |
800 exp = exp->inlineScan(iss); | |
801 return this; | |
802 } | |
803 | |
804 Statement *CompoundStatement::inlineScan(InlineScanState *iss) | |
805 { | |
806 for (size_t i = 0; i < statements->dim; i++) | |
807 { Statement *s = (Statement *) statements->data[i]; | |
808 if (s) | |
809 statements->data[i] = (void *)s->inlineScan(iss); | |
810 } | |
811 return this; | |
812 } | |
813 | |
814 Statement *UnrolledLoopStatement::inlineScan(InlineScanState *iss) | |
815 { | |
816 for (size_t i = 0; i < statements->dim; i++) | |
817 { Statement *s = (Statement *) statements->data[i]; | |
818 if (s) | |
819 statements->data[i] = (void *)s->inlineScan(iss); | |
820 } | |
821 return this; | |
822 } | |
823 | |
824 Statement *ScopeStatement::inlineScan(InlineScanState *iss) | |
825 { | |
826 if (statement) | |
827 statement = statement->inlineScan(iss); | |
828 return this; | |
829 } | |
830 | |
831 Statement *WhileStatement::inlineScan(InlineScanState *iss) | |
832 { | |
833 condition = condition->inlineScan(iss); | |
834 body = body ? body->inlineScan(iss) : NULL; | |
835 return this; | |
836 } | |
837 | |
838 | |
839 Statement *DoStatement::inlineScan(InlineScanState *iss) | |
840 { | |
841 body = body ? body->inlineScan(iss) : NULL; | |
842 condition = condition->inlineScan(iss); | |
843 return this; | |
844 } | |
845 | |
846 | |
847 Statement *ForStatement::inlineScan(InlineScanState *iss) | |
848 { | |
849 if (init) | |
850 init = init->inlineScan(iss); | |
851 if (condition) | |
852 condition = condition->inlineScan(iss); | |
853 if (increment) | |
854 increment = increment->inlineScan(iss); | |
855 body = body->inlineScan(iss); | |
856 return this; | |
857 } | |
858 | |
859 | |
860 Statement *ForeachStatement::inlineScan(InlineScanState *iss) | |
861 { | |
862 aggr = aggr->inlineScan(iss); | |
92 | 863 if (body) |
864 body = body->inlineScan(iss); | |
1 | 865 return this; |
866 } | |
867 | |
868 | |
336 | 869 #if DMDV2 |
1 | 870 Statement *ForeachRangeStatement::inlineScan(InlineScanState *iss) |
871 { | |
872 lwr = lwr->inlineScan(iss); | |
873 upr = upr->inlineScan(iss); | |
92 | 874 if (body) |
875 body = body->inlineScan(iss); | |
1 | 876 return this; |
877 } | |
878 #endif | |
879 | |
880 | |
881 Statement *IfStatement::inlineScan(InlineScanState *iss) | |
882 { | |
883 condition = condition->inlineScan(iss); | |
884 if (ifbody) | |
885 ifbody = ifbody->inlineScan(iss); | |
886 if (elsebody) | |
887 elsebody = elsebody->inlineScan(iss); | |
888 return this; | |
889 } | |
890 | |
891 | |
892 Statement *SwitchStatement::inlineScan(InlineScanState *iss) | |
893 { | |
894 //printf("SwitchStatement::inlineScan()\n"); | |
895 condition = condition->inlineScan(iss); | |
896 body = body ? body->inlineScan(iss) : NULL; | |
897 if (sdefault) | |
898 sdefault = (DefaultStatement *)sdefault->inlineScan(iss); | |
899 if (cases) | |
900 { | |
901 for (int i = 0; i < cases->dim; i++) | |
902 { Statement *s; | |
903 | |
904 s = (Statement *) cases->data[i]; | |
905 cases->data[i] = (void *)s->inlineScan(iss); | |
906 } | |
907 } | |
908 return this; | |
909 } | |
910 | |
911 | |
912 Statement *CaseStatement::inlineScan(InlineScanState *iss) | |
913 { | |
914 //printf("CaseStatement::inlineScan()\n"); | |
915 exp = exp->inlineScan(iss); | |
916 if (statement) | |
917 statement = statement->inlineScan(iss); | |
918 return this; | |
919 } | |
920 | |
921 | |
922 Statement *DefaultStatement::inlineScan(InlineScanState *iss) | |
923 { | |
924 if (statement) | |
925 statement = statement->inlineScan(iss); | |
926 return this; | |
927 } | |
928 | |
929 | |
930 Statement *ReturnStatement::inlineScan(InlineScanState *iss) | |
931 { | |
932 if (exp) | |
933 exp = exp->inlineScan(iss); | |
934 return this; | |
935 } | |
936 | |
937 | |
938 Statement *SynchronizedStatement::inlineScan(InlineScanState *iss) | |
939 { | |
940 if (exp) | |
941 exp = exp->inlineScan(iss); | |
942 if (body) | |
943 body = body->inlineScan(iss); | |
944 return this; | |
945 } | |
946 | |
947 | |
948 Statement *WithStatement::inlineScan(InlineScanState *iss) | |
949 { | |
950 if (exp) | |
951 exp = exp->inlineScan(iss); | |
952 if (body) | |
953 body = body->inlineScan(iss); | |
954 return this; | |
955 } | |
956 | |
957 | |
958 Statement *TryCatchStatement::inlineScan(InlineScanState *iss) | |
959 { | |
960 if (body) | |
961 body = body->inlineScan(iss); | |
962 if (catches) | |
963 { | |
964 for (int i = 0; i < catches->dim; i++) | |
965 { Catch *c = (Catch *)catches->data[i]; | |
966 | |
967 if (c->handler) | |
968 c->handler = c->handler->inlineScan(iss); | |
969 } | |
970 } | |
971 return this; | |
972 } | |
973 | |
974 | |
975 Statement *TryFinallyStatement::inlineScan(InlineScanState *iss) | |
976 { | |
977 if (body) | |
978 body = body->inlineScan(iss); | |
979 if (finalbody) | |
980 finalbody = finalbody->inlineScan(iss); | |
981 return this; | |
982 } | |
983 | |
984 | |
985 Statement *ThrowStatement::inlineScan(InlineScanState *iss) | |
986 { | |
987 if (exp) | |
988 exp = exp->inlineScan(iss); | |
989 return this; | |
990 } | |
991 | |
992 | |
993 Statement *VolatileStatement::inlineScan(InlineScanState *iss) | |
994 { | |
995 if (statement) | |
996 statement = statement->inlineScan(iss); | |
997 return this; | |
998 } | |
999 | |
1000 | |
1001 Statement *LabelStatement::inlineScan(InlineScanState *iss) | |
1002 { | |
1003 if (statement) | |
1004 statement = statement->inlineScan(iss); | |
1005 return this; | |
1006 } | |
1007 | |
1008 /* -------------------------- */ | |
1009 | |
1010 void arrayInlineScan(InlineScanState *iss, Array *arguments) | |
1011 { | |
1012 if (arguments) | |
1013 { | |
1014 for (int i = 0; i < arguments->dim; i++) | |
1015 { Expression *e = (Expression *)arguments->data[i]; | |
1016 | |
1017 if (e) | |
1018 { | |
1019 e = e->inlineScan(iss); | |
1020 arguments->data[i] = (void *)e; | |
1021 } | |
1022 } | |
1023 } | |
1024 } | |
1025 | |
1026 Expression *Expression::inlineScan(InlineScanState *iss) | |
1027 { | |
1028 return this; | |
1029 } | |
1030 | |
1031 void scanVar(Dsymbol *s, InlineScanState *iss) | |
1032 { | |
1033 VarDeclaration *vd = s->isVarDeclaration(); | |
1034 if (vd) | |
1035 { | |
1036 TupleDeclaration *td = vd->toAlias()->isTupleDeclaration(); | |
1037 if (td) | |
1038 { | |
1039 for (size_t i = 0; i < td->objects->dim; i++) | |
1040 { DsymbolExp *se = (DsymbolExp *)td->objects->data[i]; | |
1041 assert(se->op == TOKdsymbol); | |
1042 scanVar(se->s, iss); | |
1043 } | |
1044 } | |
1045 else | |
1046 { | |
1047 // Scan initializer (vd->init) | |
1048 if (vd->init) | |
1049 { | |
1050 ExpInitializer *ie = vd->init->isExpInitializer(); | |
1051 | |
1052 if (ie) | |
1053 { | |
1054 ie->exp = ie->exp->inlineScan(iss); | |
1055 } | |
1056 } | |
1057 } | |
1058 } | |
1059 } | |
1060 | |
1061 Expression *DeclarationExp::inlineScan(InlineScanState *iss) | |
1062 { | |
1063 //printf("DeclarationExp::inlineScan()\n"); | |
1064 scanVar(declaration, iss); | |
1065 return this; | |
1066 } | |
1067 | |
1068 Expression *UnaExp::inlineScan(InlineScanState *iss) | |
1069 { | |
1070 e1 = e1->inlineScan(iss); | |
1071 return this; | |
1072 } | |
1073 | |
1074 Expression *AssertExp::inlineScan(InlineScanState *iss) | |
1075 { | |
1076 e1 = e1->inlineScan(iss); | |
1077 if (msg) | |
1078 msg = msg->inlineScan(iss); | |
1079 return this; | |
1080 } | |
1081 | |
1082 Expression *BinExp::inlineScan(InlineScanState *iss) | |
1083 { | |
1084 e1 = e1->inlineScan(iss); | |
1085 e2 = e2->inlineScan(iss); | |
1086 return this; | |
1087 } | |
1088 | |
1089 | |
1090 Expression *CallExp::inlineScan(InlineScanState *iss) | |
1091 { Expression *e = this; | |
1092 | |
1093 //printf("CallExp::inlineScan()\n"); | |
1094 e1 = e1->inlineScan(iss); | |
1095 arrayInlineScan(iss, arguments); | |
1096 | |
1097 if (e1->op == TOKvar) | |
1098 { | |
1099 VarExp *ve = (VarExp *)e1; | |
1100 FuncDeclaration *fd = ve->var->isFuncDeclaration(); | |
1101 | |
1102 if (fd && fd != iss->fd && fd->canInline(0)) | |
1103 { | |
1104 e = fd->doInline(iss, NULL, arguments); | |
1105 } | |
1106 } | |
1107 else if (e1->op == TOKdotvar) | |
1108 { | |
1109 DotVarExp *dve = (DotVarExp *)e1; | |
1110 FuncDeclaration *fd = dve->var->isFuncDeclaration(); | |
1111 | |
1112 if (fd && fd != iss->fd && fd->canInline(1)) | |
1113 { | |
1114 if (dve->e1->op == TOKcall && | |
1115 dve->e1->type->toBasetype()->ty == Tstruct) | |
1116 { | |
1117 /* To create ethis, we'll need to take the address | |
1118 * of dve->e1, but this won't work if dve->e1 is | |
1119 * a function call. | |
1120 */ | |
1121 ; | |
1122 } | |
1123 else | |
1124 e = fd->doInline(iss, dve->e1, arguments); | |
1125 } | |
1126 } | |
1127 | |
1128 return e; | |
1129 } | |
1130 | |
1131 | |
1132 Expression *SliceExp::inlineScan(InlineScanState *iss) | |
1133 { | |
1134 e1 = e1->inlineScan(iss); | |
1135 if (lwr) | |
1136 lwr = lwr->inlineScan(iss); | |
1137 if (upr) | |
1138 upr = upr->inlineScan(iss); | |
1139 return this; | |
1140 } | |
1141 | |
1142 | |
1143 Expression *TupleExp::inlineScan(InlineScanState *iss) | |
1144 { Expression *e = this; | |
1145 | |
1146 //printf("TupleExp::inlineScan()\n"); | |
1147 arrayInlineScan(iss, exps); | |
1148 | |
1149 return e; | |
1150 } | |
1151 | |
1152 | |
1153 Expression *ArrayLiteralExp::inlineScan(InlineScanState *iss) | |
1154 { Expression *e = this; | |
1155 | |
1156 //printf("ArrayLiteralExp::inlineScan()\n"); | |
1157 arrayInlineScan(iss, elements); | |
1158 | |
1159 return e; | |
1160 } | |
1161 | |
1162 | |
1163 Expression *AssocArrayLiteralExp::inlineScan(InlineScanState *iss) | |
1164 { Expression *e = this; | |
1165 | |
1166 //printf("AssocArrayLiteralExp::inlineScan()\n"); | |
1167 arrayInlineScan(iss, keys); | |
1168 arrayInlineScan(iss, values); | |
1169 | |
1170 return e; | |
1171 } | |
1172 | |
1173 | |
1174 Expression *StructLiteralExp::inlineScan(InlineScanState *iss) | |
1175 { Expression *e = this; | |
1176 | |
1177 //printf("StructLiteralExp::inlineScan()\n"); | |
1178 arrayInlineScan(iss, elements); | |
1179 | |
1180 return e; | |
1181 } | |
1182 | |
1183 | |
1184 Expression *ArrayExp::inlineScan(InlineScanState *iss) | |
1185 { Expression *e = this; | |
1186 | |
1187 //printf("ArrayExp::inlineScan()\n"); | |
1188 e1 = e1->inlineScan(iss); | |
1189 arrayInlineScan(iss, arguments); | |
1190 | |
1191 return e; | |
1192 } | |
1193 | |
1194 | |
1195 Expression *CondExp::inlineScan(InlineScanState *iss) | |
1196 { | |
1197 econd = econd->inlineScan(iss); | |
1198 e1 = e1->inlineScan(iss); | |
1199 e2 = e2->inlineScan(iss); | |
1200 return this; | |
1201 } | |
1202 | |
1203 | |
1204 /* ========== =============== */ | |
1205 | |
1206 void FuncDeclaration::inlineScan() | |
1207 { | |
1208 InlineScanState iss; | |
1209 | |
1210 #if LOG | |
1211 printf("FuncDeclaration::inlineScan('%s')\n", toChars()); | |
1212 #endif | |
1213 memset(&iss, 0, sizeof(iss)); | |
1214 iss.fd = this; | |
1215 if (fbody) | |
1216 { | |
1217 inlineNest++; | |
1218 fbody = fbody->inlineScan(&iss); | |
1219 inlineNest--; | |
1220 } | |
1221 } | |
1222 | |
1223 int FuncDeclaration::canInline(int hasthis, int hdrscan) | |
1224 { | |
1225 InlineCostState ics; | |
1226 int cost; | |
1227 | |
1228 #define CANINLINE_LOG 0 | |
1229 | |
1230 #if CANINLINE_LOG | |
1231 printf("FuncDeclaration::canInline(hasthis = %d, '%s')\n", hasthis, toChars()); | |
1232 #endif | |
1233 | |
1234 if (needThis() && !hasthis) | |
1235 return 0; | |
1236 | |
1237 if (inlineNest || (!semanticRun && !hdrscan)) | |
1238 { | |
1239 #if CANINLINE_LOG | |
1240 printf("\t1: no, inlineNest = %d, semanticRun = %d\n", inlineNest, semanticRun); | |
1241 #endif | |
1242 return 0; | |
1243 } | |
1244 | |
1245 switch (inlineStatus) | |
1246 { | |
1247 case ILSyes: | |
1248 #if CANINLINE_LOG | |
1249 printf("\tyes\n"); | |
1250 #endif | |
1251 return 1; | |
1252 | |
1253 case ILSno: | |
1254 #if CANINLINE_LOG | |
1255 printf("\t2: no\n"); | |
1256 #endif | |
1257 return 0; | |
1258 | |
1259 case ILSuninitialized: | |
1260 break; | |
1261 | |
1262 default: | |
1263 assert(0); | |
1264 } | |
1265 | |
1266 if (type) | |
1267 { assert(type->ty == Tfunction); | |
1268 TypeFunction *tf = (TypeFunction *)(type); | |
1269 if (tf->varargs == 1) // no variadic parameter lists | |
1270 goto Lno; | |
1271 | |
1272 /* Don't inline a function that returns non-void, but has | |
1273 * no return expression. | |
1274 */ | |
1275 if (tf->next && tf->next->ty != Tvoid && | |
1276 !(hasReturnExp & 1) && | |
1277 !hdrscan) | |
1278 goto Lno; | |
1279 } | |
1280 else | |
1281 { CtorDeclaration *ctor = isCtorDeclaration(); | |
1282 | |
1283 if (ctor && ctor->varargs == 1) | |
1284 goto Lno; | |
1285 } | |
1286 | |
1287 if ( | |
1288 !fbody || | |
1289 !hdrscan && | |
1290 ( | |
1291 #if 0 | |
1292 isCtorDeclaration() || // cannot because need to convert: | |
1293 // return; | |
1294 // to: | |
1295 // return this; | |
1296 #endif | |
1297 isSynchronized() || | |
1298 isImportedSymbol() || | |
336 | 1299 #if DMDV2 |
92 | 1300 closureVars.dim || // no nested references to this frame |
1301 #else | |
1 | 1302 nestedFrameRef || // no nested references to this frame |
92 | 1303 #endif |
1 | 1304 (isVirtual() && !isFinal()) |
1305 )) | |
1306 { | |
1307 goto Lno; | |
1308 } | |
1309 | |
1310 /* If any parameters are Tsarray's (which are passed by reference) | |
1311 * or out parameters (also passed by reference), don't do inlining. | |
1312 */ | |
1313 if (parameters) | |
1314 { | |
1315 for (int i = 0; i < parameters->dim; i++) | |
1316 { | |
1317 VarDeclaration *v = (VarDeclaration *)parameters->data[i]; | |
1318 if (v->isOut() || v->isRef() || v->type->toBasetype()->ty == Tsarray) | |
1319 goto Lno; | |
1320 } | |
1321 } | |
1322 | |
1323 memset(&ics, 0, sizeof(ics)); | |
1324 ics.hasthis = hasthis; | |
1325 ics.fd = this; | |
1326 ics.hdrscan = hdrscan; | |
1327 cost = fbody->inlineCost(&ics); | |
1328 #if CANINLINE_LOG | |
1329 printf("cost = %d\n", cost); | |
1330 #endif | |
1331 if (cost >= COST_MAX) | |
1332 goto Lno; | |
1333 | |
1334 if (!hdrscan) // Don't scan recursively for header content scan | |
1335 inlineScan(); | |
1336 | |
1337 Lyes: | |
1338 if (!hdrscan) // Don't modify inlineStatus for header content scan | |
1339 inlineStatus = ILSyes; | |
1340 #if CANINLINE_LOG | |
1341 printf("\tyes\n"); | |
1342 #endif | |
1343 return 1; | |
1344 | |
1345 Lno: | |
1346 if (!hdrscan) // Don't modify inlineStatus for header content scan | |
1347 inlineStatus = ILSno; | |
1348 #if CANINLINE_LOG | |
1349 printf("\tno\n"); | |
1350 #endif | |
1351 return 0; | |
1352 } | |
1353 | |
1354 Expression *FuncDeclaration::doInline(InlineScanState *iss, Expression *ethis, Array *arguments) | |
1355 { | |
1356 InlineDoState ids; | |
1357 DeclarationExp *de; | |
1358 Expression *e = NULL; | |
1359 | |
1360 #if LOG | |
1361 printf("FuncDeclaration::doInline('%s')\n", toChars()); | |
1362 #endif | |
1363 | |
1364 memset(&ids, 0, sizeof(ids)); | |
1365 ids.parent = iss->fd; | |
1366 | |
1367 // Set up vthis | |
1368 if (ethis) | |
1369 { | |
1370 VarDeclaration *vthis; | |
1371 ExpInitializer *ei; | |
1372 VarExp *ve; | |
1373 | |
1374 if (ethis->type->ty != Tclass && ethis->type->ty != Tpointer) | |
1375 { | |
1376 ethis = ethis->addressOf(NULL); | |
1377 } | |
1378 | |
1379 ei = new ExpInitializer(ethis->loc, ethis); | |
1380 | |
1381 vthis = new VarDeclaration(ethis->loc, ethis->type, Id::This, ei); | |
1382 vthis->storage_class = STCin; | |
1383 vthis->linkage = LINKd; | |
1384 vthis->parent = iss->fd; | |
1385 | |
1386 ve = new VarExp(vthis->loc, vthis); | |
1387 ve->type = vthis->type; | |
1388 | |
1389 ei->exp = new AssignExp(vthis->loc, ve, ethis); | |
1390 ei->exp->type = ve->type; | |
1391 | |
1392 ids.vthis = vthis; | |
1393 } | |
1394 | |
1395 // Set up parameters | |
1396 if (ethis) | |
1397 { | |
1398 e = new DeclarationExp(0, ids.vthis); | |
1399 e->type = Type::tvoid; | |
1400 } | |
1401 | |
1402 if (arguments && arguments->dim) | |
1403 { | |
1404 assert(parameters->dim == arguments->dim); | |
1405 | |
1406 for (int i = 0; i < arguments->dim; i++) | |
1407 { | |
1408 VarDeclaration *vfrom = (VarDeclaration *)parameters->data[i]; | |
1409 VarDeclaration *vto; | |
1410 Expression *arg = (Expression *)arguments->data[i]; | |
1411 ExpInitializer *ei; | |
1412 VarExp *ve; | |
1413 | |
1414 ei = new ExpInitializer(arg->loc, arg); | |
1415 | |
1416 vto = new VarDeclaration(vfrom->loc, vfrom->type, vfrom->ident, ei); | |
1417 vto->storage_class |= vfrom->storage_class & (STCin | STCout | STClazy | STCref); | |
1418 vto->linkage = vfrom->linkage; | |
1419 vto->parent = iss->fd; | |
1420 //printf("vto = '%s', vto->storage_class = x%x\n", vto->toChars(), vto->storage_class); | |
1421 //printf("vto->parent = '%s'\n", iss->fd->toChars()); | |
1422 | |
1423 ve = new VarExp(vto->loc, vto); | |
1424 //ve->type = vto->type; | |
1425 ve->type = arg->type; | |
1426 | |
1427 ei->exp = new AssignExp(vto->loc, ve, arg); | |
1428 ei->exp->type = ve->type; | |
1429 //ve->type->print(); | |
1430 //arg->type->print(); | |
1431 //ei->exp->print(); | |
1432 | |
1433 ids.from.push(vfrom); | |
1434 ids.to.push(vto); | |
1435 | |
1436 de = new DeclarationExp(0, vto); | |
1437 de->type = Type::tvoid; | |
1438 | |
1439 e = Expression::combine(e, de); | |
1440 } | |
1441 } | |
1442 | |
1443 inlineNest++; | |
1444 Expression *eb = fbody->doInline(&ids); | |
1445 inlineNest--; | |
1446 //eb->type->print(); | |
1447 //eb->print(); | |
1448 //eb->dump(0); | |
1449 return Expression::combine(e, eb); | |
1450 } | |
1451 | |
1452 | |
1453 |