Mercurial > projects > ldc
annotate dmd/inline.c @ 1421:7a693c367190
just a simple change to cmake for mingw
author | Kelly Wilson <wilsonk cpsc.ucalgary.ca> |
---|---|
date | Wed, 27 May 2009 12:41:41 -0600 |
parents | 8026319762be |
children | d9c5f5a43403 |
rev | line source |
---|---|
1 | 1 |
1367
8026319762be
Merged DMD 1.045 !!!
Tomas Lindquist Olsen <tomas.l.olsen gmail com>
parents:
1146
diff
changeset
|
2 // Copyright (c) 1999-2008 by Digital Mars |
1 | 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 { | |
1367
8026319762be
Merged DMD 1.045 !!!
Tomas Lindquist Olsen <tomas.l.olsen gmail com>
parents:
1146
diff
changeset
|
932 //printf("ReturnStatement::inlineScan()\n"); |
1 | 933 if (exp) |
1367
8026319762be
Merged DMD 1.045 !!!
Tomas Lindquist Olsen <tomas.l.olsen gmail com>
parents:
1146
diff
changeset
|
934 { |
1 | 935 exp = exp->inlineScan(iss); |
1367
8026319762be
Merged DMD 1.045 !!!
Tomas Lindquist Olsen <tomas.l.olsen gmail com>
parents:
1146
diff
changeset
|
936 } |
1 | 937 return this; |
938 } | |
939 | |
940 | |
941 Statement *SynchronizedStatement::inlineScan(InlineScanState *iss) | |
942 { | |
943 if (exp) | |
944 exp = exp->inlineScan(iss); | |
945 if (body) | |
946 body = body->inlineScan(iss); | |
947 return this; | |
948 } | |
949 | |
950 | |
951 Statement *WithStatement::inlineScan(InlineScanState *iss) | |
952 { | |
953 if (exp) | |
954 exp = exp->inlineScan(iss); | |
955 if (body) | |
956 body = body->inlineScan(iss); | |
957 return this; | |
958 } | |
959 | |
960 | |
961 Statement *TryCatchStatement::inlineScan(InlineScanState *iss) | |
962 { | |
963 if (body) | |
964 body = body->inlineScan(iss); | |
965 if (catches) | |
966 { | |
967 for (int i = 0; i < catches->dim; i++) | |
968 { Catch *c = (Catch *)catches->data[i]; | |
969 | |
970 if (c->handler) | |
971 c->handler = c->handler->inlineScan(iss); | |
972 } | |
973 } | |
974 return this; | |
975 } | |
976 | |
977 | |
978 Statement *TryFinallyStatement::inlineScan(InlineScanState *iss) | |
979 { | |
980 if (body) | |
981 body = body->inlineScan(iss); | |
982 if (finalbody) | |
983 finalbody = finalbody->inlineScan(iss); | |
984 return this; | |
985 } | |
986 | |
987 | |
988 Statement *ThrowStatement::inlineScan(InlineScanState *iss) | |
989 { | |
990 if (exp) | |
991 exp = exp->inlineScan(iss); | |
992 return this; | |
993 } | |
994 | |
995 | |
996 Statement *VolatileStatement::inlineScan(InlineScanState *iss) | |
997 { | |
998 if (statement) | |
999 statement = statement->inlineScan(iss); | |
1000 return this; | |
1001 } | |
1002 | |
1003 | |
1004 Statement *LabelStatement::inlineScan(InlineScanState *iss) | |
1005 { | |
1006 if (statement) | |
1007 statement = statement->inlineScan(iss); | |
1008 return this; | |
1009 } | |
1010 | |
1011 /* -------------------------- */ | |
1012 | |
1013 void arrayInlineScan(InlineScanState *iss, Array *arguments) | |
1014 { | |
1015 if (arguments) | |
1016 { | |
1017 for (int i = 0; i < arguments->dim; i++) | |
1018 { Expression *e = (Expression *)arguments->data[i]; | |
1019 | |
1020 if (e) | |
1021 { | |
1022 e = e->inlineScan(iss); | |
1023 arguments->data[i] = (void *)e; | |
1024 } | |
1025 } | |
1026 } | |
1027 } | |
1028 | |
1029 Expression *Expression::inlineScan(InlineScanState *iss) | |
1030 { | |
1031 return this; | |
1032 } | |
1033 | |
1034 void scanVar(Dsymbol *s, InlineScanState *iss) | |
1035 { | |
1036 VarDeclaration *vd = s->isVarDeclaration(); | |
1037 if (vd) | |
1038 { | |
1039 TupleDeclaration *td = vd->toAlias()->isTupleDeclaration(); | |
1040 if (td) | |
1041 { | |
1042 for (size_t i = 0; i < td->objects->dim; i++) | |
1043 { DsymbolExp *se = (DsymbolExp *)td->objects->data[i]; | |
1044 assert(se->op == TOKdsymbol); | |
1045 scanVar(se->s, iss); | |
1046 } | |
1047 } | |
1048 else | |
1049 { | |
1050 // Scan initializer (vd->init) | |
1051 if (vd->init) | |
1052 { | |
1053 ExpInitializer *ie = vd->init->isExpInitializer(); | |
1054 | |
1055 if (ie) | |
1056 { | |
1057 ie->exp = ie->exp->inlineScan(iss); | |
1058 } | |
1059 } | |
1060 } | |
1061 } | |
1062 } | |
1063 | |
1064 Expression *DeclarationExp::inlineScan(InlineScanState *iss) | |
1065 { | |
1066 //printf("DeclarationExp::inlineScan()\n"); | |
1067 scanVar(declaration, iss); | |
1068 return this; | |
1069 } | |
1070 | |
1071 Expression *UnaExp::inlineScan(InlineScanState *iss) | |
1072 { | |
1073 e1 = e1->inlineScan(iss); | |
1074 return this; | |
1075 } | |
1076 | |
1077 Expression *AssertExp::inlineScan(InlineScanState *iss) | |
1078 { | |
1079 e1 = e1->inlineScan(iss); | |
1080 if (msg) | |
1081 msg = msg->inlineScan(iss); | |
1082 return this; | |
1083 } | |
1084 | |
1085 Expression *BinExp::inlineScan(InlineScanState *iss) | |
1086 { | |
1087 e1 = e1->inlineScan(iss); | |
1088 e2 = e2->inlineScan(iss); | |
1089 return this; | |
1090 } | |
1091 | |
1092 | |
1093 Expression *CallExp::inlineScan(InlineScanState *iss) | |
1094 { Expression *e = this; | |
1095 | |
1096 //printf("CallExp::inlineScan()\n"); | |
1097 e1 = e1->inlineScan(iss); | |
1098 arrayInlineScan(iss, arguments); | |
1099 | |
1100 if (e1->op == TOKvar) | |
1101 { | |
1102 VarExp *ve = (VarExp *)e1; | |
1103 FuncDeclaration *fd = ve->var->isFuncDeclaration(); | |
1104 | |
1105 if (fd && fd != iss->fd && fd->canInline(0)) | |
1106 { | |
1107 e = fd->doInline(iss, NULL, arguments); | |
1108 } | |
1109 } | |
1110 else if (e1->op == TOKdotvar) | |
1111 { | |
1112 DotVarExp *dve = (DotVarExp *)e1; | |
1113 FuncDeclaration *fd = dve->var->isFuncDeclaration(); | |
1114 | |
1115 if (fd && fd != iss->fd && fd->canInline(1)) | |
1116 { | |
1117 if (dve->e1->op == TOKcall && | |
1118 dve->e1->type->toBasetype()->ty == Tstruct) | |
1119 { | |
1120 /* To create ethis, we'll need to take the address | |
1121 * of dve->e1, but this won't work if dve->e1 is | |
1122 * a function call. | |
1123 */ | |
1124 ; | |
1125 } | |
1126 else | |
1127 e = fd->doInline(iss, dve->e1, arguments); | |
1128 } | |
1129 } | |
1130 | |
1131 return e; | |
1132 } | |
1133 | |
1134 | |
1135 Expression *SliceExp::inlineScan(InlineScanState *iss) | |
1136 { | |
1137 e1 = e1->inlineScan(iss); | |
1138 if (lwr) | |
1139 lwr = lwr->inlineScan(iss); | |
1140 if (upr) | |
1141 upr = upr->inlineScan(iss); | |
1142 return this; | |
1143 } | |
1144 | |
1145 | |
1146 Expression *TupleExp::inlineScan(InlineScanState *iss) | |
1147 { Expression *e = this; | |
1148 | |
1149 //printf("TupleExp::inlineScan()\n"); | |
1150 arrayInlineScan(iss, exps); | |
1151 | |
1152 return e; | |
1153 } | |
1154 | |
1155 | |
1156 Expression *ArrayLiteralExp::inlineScan(InlineScanState *iss) | |
1157 { Expression *e = this; | |
1158 | |
1159 //printf("ArrayLiteralExp::inlineScan()\n"); | |
1160 arrayInlineScan(iss, elements); | |
1161 | |
1162 return e; | |
1163 } | |
1164 | |
1165 | |
1166 Expression *AssocArrayLiteralExp::inlineScan(InlineScanState *iss) | |
1167 { Expression *e = this; | |
1168 | |
1169 //printf("AssocArrayLiteralExp::inlineScan()\n"); | |
1170 arrayInlineScan(iss, keys); | |
1171 arrayInlineScan(iss, values); | |
1172 | |
1173 return e; | |
1174 } | |
1175 | |
1176 | |
1177 Expression *StructLiteralExp::inlineScan(InlineScanState *iss) | |
1178 { Expression *e = this; | |
1179 | |
1180 //printf("StructLiteralExp::inlineScan()\n"); | |
1181 arrayInlineScan(iss, elements); | |
1182 | |
1183 return e; | |
1184 } | |
1185 | |
1186 | |
1187 Expression *ArrayExp::inlineScan(InlineScanState *iss) | |
1188 { Expression *e = this; | |
1189 | |
1190 //printf("ArrayExp::inlineScan()\n"); | |
1191 e1 = e1->inlineScan(iss); | |
1192 arrayInlineScan(iss, arguments); | |
1193 | |
1194 return e; | |
1195 } | |
1196 | |
1197 | |
1198 Expression *CondExp::inlineScan(InlineScanState *iss) | |
1199 { | |
1200 econd = econd->inlineScan(iss); | |
1201 e1 = e1->inlineScan(iss); | |
1202 e2 = e2->inlineScan(iss); | |
1203 return this; | |
1204 } | |
1205 | |
1206 | |
1207 /* ========== =============== */ | |
1208 | |
1209 void FuncDeclaration::inlineScan() | |
1210 { | |
1211 InlineScanState iss; | |
1212 | |
1213 #if LOG | |
1214 printf("FuncDeclaration::inlineScan('%s')\n", toChars()); | |
1215 #endif | |
1216 memset(&iss, 0, sizeof(iss)); | |
1217 iss.fd = this; | |
1218 if (fbody) | |
1219 { | |
1220 inlineNest++; | |
1221 fbody = fbody->inlineScan(&iss); | |
1222 inlineNest--; | |
1223 } | |
1224 } | |
1225 | |
1226 int FuncDeclaration::canInline(int hasthis, int hdrscan) | |
1227 { | |
1228 InlineCostState ics; | |
1229 int cost; | |
1230 | |
1231 #define CANINLINE_LOG 0 | |
1232 | |
1233 #if CANINLINE_LOG | |
1234 printf("FuncDeclaration::canInline(hasthis = %d, '%s')\n", hasthis, toChars()); | |
1235 #endif | |
1236 | |
1237 if (needThis() && !hasthis) | |
1238 return 0; | |
1239 | |
1367
8026319762be
Merged DMD 1.045 !!!
Tomas Lindquist Olsen <tomas.l.olsen gmail com>
parents:
1146
diff
changeset
|
1240 if (inlineNest || (semanticRun < 3 && !hdrscan)) |
1 | 1241 { |
1242 #if CANINLINE_LOG | |
1243 printf("\t1: no, inlineNest = %d, semanticRun = %d\n", inlineNest, semanticRun); | |
1244 #endif | |
1245 return 0; | |
1246 } | |
1247 | |
1248 switch (inlineStatus) | |
1249 { | |
1250 case ILSyes: | |
1251 #if CANINLINE_LOG | |
1367
8026319762be
Merged DMD 1.045 !!!
Tomas Lindquist Olsen <tomas.l.olsen gmail com>
parents:
1146
diff
changeset
|
1252 printf("\t1: yes %s\n", toChars()); |
1 | 1253 #endif |
1254 return 1; | |
1255 | |
1256 case ILSno: | |
1257 #if CANINLINE_LOG | |
1367
8026319762be
Merged DMD 1.045 !!!
Tomas Lindquist Olsen <tomas.l.olsen gmail com>
parents:
1146
diff
changeset
|
1258 printf("\t1: no %s\n", toChars()); |
1 | 1259 #endif |
1260 return 0; | |
1261 | |
1262 case ILSuninitialized: | |
1263 break; | |
1264 | |
1265 default: | |
1266 assert(0); | |
1267 } | |
1268 | |
1269 if (type) | |
1270 { assert(type->ty == Tfunction); | |
1271 TypeFunction *tf = (TypeFunction *)(type); | |
1272 if (tf->varargs == 1) // no variadic parameter lists | |
1273 goto Lno; | |
1274 | |
1275 /* Don't inline a function that returns non-void, but has | |
1276 * no return expression. | |
1277 */ | |
1278 if (tf->next && tf->next->ty != Tvoid && | |
1279 !(hasReturnExp & 1) && | |
1280 !hdrscan) | |
1281 goto Lno; | |
1282 } | |
1283 else | |
1284 { CtorDeclaration *ctor = isCtorDeclaration(); | |
1285 | |
1286 if (ctor && ctor->varargs == 1) | |
1287 goto Lno; | |
1288 } | |
1289 | |
1290 if ( | |
1291 !fbody || | |
1292 !hdrscan && | |
1293 ( | |
1294 #if 0 | |
1295 isCtorDeclaration() || // cannot because need to convert: | |
1296 // return; | |
1297 // to: | |
1298 // return this; | |
1299 #endif | |
1300 isSynchronized() || | |
1301 isImportedSymbol() || | |
336 | 1302 #if DMDV2 |
92 | 1303 closureVars.dim || // no nested references to this frame |
1304 #else | |
1 | 1305 nestedFrameRef || // no nested references to this frame |
92 | 1306 #endif |
1 | 1307 (isVirtual() && !isFinal()) |
1308 )) | |
1309 { | |
1310 goto Lno; | |
1311 } | |
1312 | |
1313 /* If any parameters are Tsarray's (which are passed by reference) | |
1314 * or out parameters (also passed by reference), don't do inlining. | |
1315 */ | |
1316 if (parameters) | |
1317 { | |
1318 for (int i = 0; i < parameters->dim; i++) | |
1319 { | |
1320 VarDeclaration *v = (VarDeclaration *)parameters->data[i]; | |
1321 if (v->isOut() || v->isRef() || v->type->toBasetype()->ty == Tsarray) | |
1322 goto Lno; | |
1323 } | |
1324 } | |
1325 | |
1326 memset(&ics, 0, sizeof(ics)); | |
1327 ics.hasthis = hasthis; | |
1328 ics.fd = this; | |
1329 ics.hdrscan = hdrscan; | |
1330 cost = fbody->inlineCost(&ics); | |
1331 #if CANINLINE_LOG | |
1332 printf("cost = %d\n", cost); | |
1333 #endif | |
1334 if (cost >= COST_MAX) | |
1335 goto Lno; | |
1336 | |
1337 if (!hdrscan) // Don't scan recursively for header content scan | |
1338 inlineScan(); | |
1339 | |
1340 Lyes: | |
1341 if (!hdrscan) // Don't modify inlineStatus for header content scan | |
1342 inlineStatus = ILSyes; | |
1343 #if CANINLINE_LOG | |
1367
8026319762be
Merged DMD 1.045 !!!
Tomas Lindquist Olsen <tomas.l.olsen gmail com>
parents:
1146
diff
changeset
|
1344 printf("\t2: yes %s\n", toChars()); |
1 | 1345 #endif |
1346 return 1; | |
1347 | |
1348 Lno: | |
1349 if (!hdrscan) // Don't modify inlineStatus for header content scan | |
1350 inlineStatus = ILSno; | |
1351 #if CANINLINE_LOG | |
1367
8026319762be
Merged DMD 1.045 !!!
Tomas Lindquist Olsen <tomas.l.olsen gmail com>
parents:
1146
diff
changeset
|
1352 printf("\t2: no %s\n", toChars()); |
1 | 1353 #endif |
1354 return 0; | |
1355 } | |
1356 | |
1357 Expression *FuncDeclaration::doInline(InlineScanState *iss, Expression *ethis, Array *arguments) | |
1358 { | |
1359 InlineDoState ids; | |
1360 DeclarationExp *de; | |
1361 Expression *e = NULL; | |
1362 | |
1363 #if LOG | |
1364 printf("FuncDeclaration::doInline('%s')\n", toChars()); | |
1365 #endif | |
1366 | |
1367 memset(&ids, 0, sizeof(ids)); | |
1368 ids.parent = iss->fd; | |
1369 | |
1370 // Set up vthis | |
1371 if (ethis) | |
1372 { | |
1373 VarDeclaration *vthis; | |
1374 ExpInitializer *ei; | |
1375 VarExp *ve; | |
1376 | |
1377 if (ethis->type->ty != Tclass && ethis->type->ty != Tpointer) | |
1378 { | |
1379 ethis = ethis->addressOf(NULL); | |
1380 } | |
1381 | |
1382 ei = new ExpInitializer(ethis->loc, ethis); | |
1383 | |
1384 vthis = new VarDeclaration(ethis->loc, ethis->type, Id::This, ei); | |
1385 vthis->storage_class = STCin; | |
1386 vthis->linkage = LINKd; | |
1387 vthis->parent = iss->fd; | |
1388 | |
1389 ve = new VarExp(vthis->loc, vthis); | |
1390 ve->type = vthis->type; | |
1391 | |
1392 ei->exp = new AssignExp(vthis->loc, ve, ethis); | |
1393 ei->exp->type = ve->type; | |
1394 | |
1395 ids.vthis = vthis; | |
1396 } | |
1397 | |
1398 // Set up parameters | |
1399 if (ethis) | |
1400 { | |
1401 e = new DeclarationExp(0, ids.vthis); | |
1402 e->type = Type::tvoid; | |
1403 } | |
1404 | |
1405 if (arguments && arguments->dim) | |
1406 { | |
1407 assert(parameters->dim == arguments->dim); | |
1408 | |
1409 for (int i = 0; i < arguments->dim; i++) | |
1410 { | |
1411 VarDeclaration *vfrom = (VarDeclaration *)parameters->data[i]; | |
1412 VarDeclaration *vto; | |
1413 Expression *arg = (Expression *)arguments->data[i]; | |
1414 ExpInitializer *ei; | |
1415 VarExp *ve; | |
1416 | |
1417 ei = new ExpInitializer(arg->loc, arg); | |
1418 | |
1419 vto = new VarDeclaration(vfrom->loc, vfrom->type, vfrom->ident, ei); | |
1420 vto->storage_class |= vfrom->storage_class & (STCin | STCout | STClazy | STCref); | |
1421 vto->linkage = vfrom->linkage; | |
1422 vto->parent = iss->fd; | |
1423 //printf("vto = '%s', vto->storage_class = x%x\n", vto->toChars(), vto->storage_class); | |
1424 //printf("vto->parent = '%s'\n", iss->fd->toChars()); | |
1425 | |
1426 ve = new VarExp(vto->loc, vto); | |
1427 //ve->type = vto->type; | |
1428 ve->type = arg->type; | |
1429 | |
1430 ei->exp = new AssignExp(vto->loc, ve, arg); | |
1431 ei->exp->type = ve->type; | |
1432 //ve->type->print(); | |
1433 //arg->type->print(); | |
1434 //ei->exp->print(); | |
1435 | |
1436 ids.from.push(vfrom); | |
1437 ids.to.push(vto); | |
1438 | |
1439 de = new DeclarationExp(0, vto); | |
1440 de->type = Type::tvoid; | |
1441 | |
1442 e = Expression::combine(e, de); | |
1443 } | |
1444 } | |
1445 | |
1446 inlineNest++; | |
1447 Expression *eb = fbody->doInline(&ids); | |
1448 inlineNest--; | |
1449 //eb->type->print(); | |
1450 //eb->print(); | |
1451 //eb->dump(0); | |
1452 return Expression::combine(e, eb); | |
1453 } | |
1454 | |
1455 | |
1456 |