Mercurial > projects > ldc
annotate dmd/inline.c @ 1404:11b122f92136
Now that templates instantiations are no longer emitted for all modules that
even blink at them they seem to break due to being linkonce (if compiled with
any optimization level > 0), so let's give them weak linkage instead.
The difference is that unreferenced linkonce symbols can be deleted, while
weak symbols need to be preserved.
author | Frits van Bommel <fvbommel wxs.nl> |
---|---|
date | Thu, 21 May 2009 15:23:28 +0200 |
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 |