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