Mercurial > projects > ldc
annotate dmd/inline.c @ 1526:54b3c1394d62
Merged dmdfe 2.031.
author | Robert Clipsham <robert@octarineparrot.com> |
---|---|
date | Tue, 07 Jul 2009 02:26:11 +0100 |
parents | d9c5f5a43403 |
children | def7a1d494fd |
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 | |
1482
d9c5f5a43403
Run `semantic3` on imported modules, and emit new symbols with
Frits van Bommel <fvbommel wxs.nl>
parents:
1367
diff
changeset
|
86 #if !IN_LLVM |
1 | 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; | |
1482
d9c5f5a43403
Run `semantic3` on imported modules, and emit new symbols with
Frits van Bommel <fvbommel wxs.nl>
parents:
1367
diff
changeset
|
92 #endif |
1 | 93 |
94 cost = condition->inlineCost(ics); | |
95 | |
1482
d9c5f5a43403
Run `semantic3` on imported modules, and emit new symbols with
Frits van Bommel <fvbommel wxs.nl>
parents:
1367
diff
changeset
|
96 #if !IN_LLVM |
1 | 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 | |
1482
d9c5f5a43403
Run `semantic3` on imported modules, and emit new symbols with
Frits van Bommel <fvbommel wxs.nl>
parents:
1367
diff
changeset
|
114 #endif |
1 | 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 { | |
1482
d9c5f5a43403
Run `semantic3` on imported modules, and emit new symbols with
Frits van Bommel <fvbommel wxs.nl>
parents:
1367
diff
changeset
|
128 #if !IN_LLVM |
1 | 129 // Can't handle return statements nested in if's |
130 if (ics->nested) | |
131 return COST_MAX; | |
1482
d9c5f5a43403
Run `semantic3` on imported modules, and emit new symbols with
Frits van Bommel <fvbommel wxs.nl>
parents:
1367
diff
changeset
|
132 #endif |
1 | 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 { | |
1482
d9c5f5a43403
Run `semantic3` on imported modules, and emit new symbols with
Frits van Bommel <fvbommel wxs.nl>
parents:
1367
diff
changeset
|
166 #if !IN_LLVM |
1 | 167 FuncDeclaration *fd = ics->fd; |
168 if (!ics->hdrscan) | |
169 if (fd->isNested() || !ics->hasthis) | |
170 return COST_MAX; | |
1482
d9c5f5a43403
Run `semantic3` on imported modules, and emit new symbols with
Frits van Bommel <fvbommel wxs.nl>
parents:
1367
diff
changeset
|
171 #endif |
1 | 172 return 1; |
173 } | |
174 | |
175 int SuperExp::inlineCost(InlineCostState *ics) | |
176 { | |
1482
d9c5f5a43403
Run `semantic3` on imported modules, and emit new symbols with
Frits van Bommel <fvbommel wxs.nl>
parents:
1367
diff
changeset
|
177 #if !IN_LLVM |
1 | 178 FuncDeclaration *fd = ics->fd; |
179 if (!ics->hdrscan) | |
180 if (fd->isNested() || !ics->hasthis) | |
181 return COST_MAX; | |
1482
d9c5f5a43403
Run `semantic3` on imported modules, and emit new symbols with
Frits van Bommel <fvbommel wxs.nl>
parents:
1367
diff
changeset
|
182 #endif |
1 | 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 { | |
1482
d9c5f5a43403
Run `semantic3` on imported modules, and emit new symbols with
Frits van Bommel <fvbommel wxs.nl>
parents:
1367
diff
changeset
|
208 // This breaks on LDC too, since nested functions have internal linkage |
d9c5f5a43403
Run `semantic3` on imported modules, and emit new symbols with
Frits van Bommel <fvbommel wxs.nl>
parents:
1367
diff
changeset
|
209 // and thus can't be referenced from other objects. |
1 | 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 { | |
1482
d9c5f5a43403
Run `semantic3` on imported modules, and emit new symbols with
Frits van Bommel <fvbommel wxs.nl>
parents:
1367
diff
changeset
|
216 // This breaks on LDC too, since nested functions have internal linkage |
d9c5f5a43403
Run `semantic3` on imported modules, and emit new symbols with
Frits van Bommel <fvbommel wxs.nl>
parents:
1367
diff
changeset
|
217 // and thus can't be referenced from other objects. |
1 | 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 } | |
1482
d9c5f5a43403
Run `semantic3` on imported modules, and emit new symbols with
Frits van Bommel <fvbommel wxs.nl>
parents:
1367
diff
changeset
|
246 // This breaks on LDC too, since nested static variables have internal |
d9c5f5a43403
Run `semantic3` on imported modules, and emit new symbols with
Frits van Bommel <fvbommel wxs.nl>
parents:
1367
diff
changeset
|
247 // linkage and thus can't be referenced from other objects. |
1 | 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. | |
1482
d9c5f5a43403
Run `semantic3` on imported modules, and emit new symbols with
Frits van Bommel <fvbommel wxs.nl>
parents:
1367
diff
changeset
|
265 // These break on LDC too, since nested static variables and functions have |
d9c5f5a43403
Run `semantic3` on imported modules, and emit new symbols with
Frits van Bommel <fvbommel wxs.nl>
parents:
1367
diff
changeset
|
266 // internal linkage and thus can't be referenced from other objects. |
1 | 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 { | |
295 return 1 + e1->inlineCost(ics) + arrayInlineCost(ics, arguments); | |
296 } | |
297 | |
298 int SliceExp::inlineCost(InlineCostState *ics) | |
299 { int cost; | |
300 | |
301 cost = 1 + e1->inlineCost(ics); | |
302 if (lwr) | |
303 cost += lwr->inlineCost(ics); | |
304 if (upr) | |
305 cost += upr->inlineCost(ics); | |
306 return cost; | |
307 } | |
308 | |
309 int ArrayExp::inlineCost(InlineCostState *ics) | |
310 { | |
311 return 1 + e1->inlineCost(ics) + arrayInlineCost(ics, arguments); | |
312 } | |
313 | |
314 | |
315 int CondExp::inlineCost(InlineCostState *ics) | |
316 { | |
317 return 1 + | |
318 e1->inlineCost(ics) + | |
319 e2->inlineCost(ics) + | |
320 econd->inlineCost(ics); | |
321 } | |
322 | |
323 | |
324 /* ======================== Perform the inlining ============================== */ | |
325 | |
326 /* Inlining is done by: | |
327 * o Converting to an Expression | |
328 * o Copying the trees of the function to be inlined | |
329 * o Renaming the variables | |
330 */ | |
331 | |
332 struct InlineDoState | |
333 { | |
334 VarDeclaration *vthis; | |
335 Array from; // old Dsymbols | |
336 Array to; // parallel array of new Dsymbols | |
337 Dsymbol *parent; // new parent | |
338 }; | |
339 | |
340 Expression *Statement::doInline(InlineDoState *ids) | |
341 { | |
342 assert(0); | |
343 return NULL; // default is we can't inline it | |
344 } | |
345 | |
346 Expression *ExpStatement::doInline(InlineDoState *ids) | |
347 { | |
348 #if LOG | |
349 if (exp) printf("ExpStatement::doInline() '%s'\n", exp->toChars()); | |
350 #endif | |
351 return exp ? exp->doInline(ids) : NULL; | |
352 } | |
353 | |
354 Expression *CompoundStatement::doInline(InlineDoState *ids) | |
355 { | |
356 Expression *e = NULL; | |
357 | |
358 //printf("CompoundStatement::doInline() %d\n", statements->dim); | |
359 for (size_t i = 0; i < statements->dim; i++) | |
360 { Statement *s = (Statement *) statements->data[i]; | |
361 if (s) | |
362 { | |
363 Expression *e2 = s->doInline(ids); | |
364 e = Expression::combine(e, e2); | |
365 if (s->isReturnStatement()) | |
366 break; | |
367 | |
368 /* Check for: | |
369 * if (condition) | |
370 * return exp1; | |
371 * else | |
372 * return exp2; | |
373 */ | |
374 IfStatement *ifs = s->isIfStatement(); | |
375 if (ifs && ifs->elsebody && ifs->ifbody && | |
376 ifs->ifbody->isReturnStatement() && | |
377 ifs->elsebody->isReturnStatement() | |
378 ) | |
379 break; | |
380 | |
381 } | |
382 } | |
383 return e; | |
384 } | |
385 | |
386 Expression *UnrolledLoopStatement::doInline(InlineDoState *ids) | |
387 { | |
388 Expression *e = NULL; | |
389 | |
390 //printf("UnrolledLoopStatement::doInline() %d\n", statements->dim); | |
391 for (size_t i = 0; i < statements->dim; i++) | |
392 { Statement *s = (Statement *) statements->data[i]; | |
393 if (s) | |
394 { | |
395 Expression *e2 = s->doInline(ids); | |
396 e = Expression::combine(e, e2); | |
397 if (s->isReturnStatement()) | |
398 break; | |
399 } | |
400 } | |
401 return e; | |
402 } | |
403 | |
404 Expression *IfStatement::doInline(InlineDoState *ids) | |
405 { | |
406 Expression *econd; | |
407 Expression *e1; | |
408 Expression *e2; | |
409 Expression *e; | |
410 | |
411 assert(!arg); | |
412 econd = condition->doInline(ids); | |
413 assert(econd); | |
414 if (ifbody) | |
415 e1 = ifbody->doInline(ids); | |
416 else | |
417 e1 = NULL; | |
418 if (elsebody) | |
419 e2 = elsebody->doInline(ids); | |
420 else | |
421 e2 = NULL; | |
422 if (e1 && e2) | |
423 { | |
424 e = new CondExp(econd->loc, econd, e1, e2); | |
425 e->type = e1->type; | |
426 } | |
427 else if (e1) | |
428 { | |
429 e = new AndAndExp(econd->loc, econd, e1); | |
430 e->type = Type::tvoid; | |
431 } | |
432 else if (e2) | |
433 { | |
434 e = new OrOrExp(econd->loc, econd, e2); | |
435 e->type = Type::tvoid; | |
436 } | |
437 else | |
438 { | |
439 e = econd; | |
440 } | |
441 return e; | |
442 } | |
443 | |
444 Expression *ReturnStatement::doInline(InlineDoState *ids) | |
445 { | |
446 //printf("ReturnStatement::doInline() '%s'\n", exp ? exp->toChars() : ""); | |
447 return exp ? exp->doInline(ids) : 0; | |
448 } | |
449 | |
450 /* --------------------------------------------------------------- */ | |
451 | |
452 /****************************** | |
453 * Perform doInline() on an array of Expressions. | |
454 */ | |
455 | |
456 Expressions *arrayExpressiondoInline(Expressions *a, InlineDoState *ids) | |
457 { Expressions *newa = NULL; | |
458 | |
459 if (a) | |
460 { | |
461 newa = new Expressions(); | |
462 newa->setDim(a->dim); | |
463 | |
464 for (int i = 0; i < a->dim; i++) | |
465 { Expression *e = (Expression *)a->data[i]; | |
466 | |
467 if (e) | |
468 { | |
469 e = e->doInline(ids); | |
470 newa->data[i] = (void *)e; | |
471 } | |
472 } | |
473 } | |
474 return newa; | |
475 } | |
476 | |
477 Expression *Expression::doInline(InlineDoState *ids) | |
478 { | |
479 //printf("Expression::doInline(%s): %s\n", Token::toChars(op), toChars()); | |
480 return copy(); | |
481 } | |
482 | |
483 Expression *SymOffExp::doInline(InlineDoState *ids) | |
484 { | |
485 int i; | |
486 | |
487 //printf("SymOffExp::doInline(%s)\n", toChars()); | |
488 for (i = 0; i < ids->from.dim; i++) | |
489 { | |
490 if (var == (Declaration *)ids->from.data[i]) | |
491 { | |
492 SymOffExp *se = (SymOffExp *)copy(); | |
493 | |
494 se->var = (Declaration *)ids->to.data[i]; | |
495 return se; | |
496 } | |
497 } | |
498 return this; | |
499 } | |
500 | |
501 Expression *VarExp::doInline(InlineDoState *ids) | |
502 { | |
503 int i; | |
504 | |
505 //printf("VarExp::doInline(%s)\n", toChars()); | |
506 for (i = 0; i < ids->from.dim; i++) | |
507 { | |
508 if (var == (Declaration *)ids->from.data[i]) | |
509 { | |
510 VarExp *ve = (VarExp *)copy(); | |
511 | |
512 ve->var = (Declaration *)ids->to.data[i]; | |
513 return ve; | |
514 } | |
515 } | |
516 return this; | |
517 } | |
518 | |
519 Expression *ThisExp::doInline(InlineDoState *ids) | |
520 { | |
521 //if (!ids->vthis) | |
522 //error("no 'this' when inlining %s", ids->parent->toChars()); | |
523 if (!ids->vthis) | |
524 { | |
525 return this; | |
526 } | |
527 | |
528 VarExp *ve = new VarExp(loc, ids->vthis); | |
529 ve->type = type; | |
530 return ve; | |
531 } | |
532 | |
533 Expression *SuperExp::doInline(InlineDoState *ids) | |
534 { | |
535 assert(ids->vthis); | |
536 | |
537 VarExp *ve = new VarExp(loc, ids->vthis); | |
538 ve->type = type; | |
539 return ve; | |
540 } | |
541 | |
542 Expression *DeclarationExp::doInline(InlineDoState *ids) | |
543 { DeclarationExp *de = (DeclarationExp *)copy(); | |
544 VarDeclaration *vd; | |
545 | |
546 //printf("DeclarationExp::doInline(%s)\n", toChars()); | |
547 vd = declaration->isVarDeclaration(); | |
548 if (vd) | |
549 { | |
550 #if 0 | |
551 // Need to figure this out before inlining can work for tuples | |
552 TupleDeclaration *td = vd->toAlias()->isTupleDeclaration(); | |
553 if (td) | |
554 { | |
555 for (size_t i = 0; i < td->objects->dim; i++) | |
556 { DsymbolExp *se = (DsymbolExp *)td->objects->data[i]; | |
557 assert(se->op == TOKdsymbol); | |
558 se->s; | |
559 } | |
560 return st->objects->dim; | |
561 } | |
562 #endif | |
563 if (vd->isStatic() || vd->isConst()) | |
564 ; | |
565 else | |
566 { | |
567 VarDeclaration *vto; | |
568 | |
569 vto = new VarDeclaration(vd->loc, vd->type, vd->ident, vd->init); | |
570 *vto = *vd; | |
571 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
|
572 #if IN_DMD |
1 | 573 vto->csym = NULL; |
574 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
|
575 #endif |
1 | 576 |
577 ids->from.push(vd); | |
578 ids->to.push(vto); | |
579 | |
92 | 580 if (vd->init) |
1 | 581 { |
92 | 582 if (vd->init->isVoidInitializer()) |
583 { | |
584 vto->init = new VoidInitializer(vd->init->loc); | |
585 } | |
586 else | |
587 { | |
588 ExpInitializer *ie = vd->init->isExpInitializer(); | |
589 assert(ie); | |
590 vto->init = new ExpInitializer(ie->loc, ie->exp->doInline(ids)); | |
591 } | |
1 | 592 } |
593 de->declaration = (Dsymbol *) (void *)vto; | |
594 } | |
595 } | |
596 /* This needs work, like DeclarationExp::toElem(), if we are | |
597 * to handle TemplateMixin's. For now, we just don't inline them. | |
598 */ | |
599 return de; | |
600 } | |
601 | |
602 Expression *NewExp::doInline(InlineDoState *ids) | |
603 { | |
604 //printf("NewExp::doInline(): %s\n", toChars()); | |
605 NewExp *ne = (NewExp *)copy(); | |
606 | |
607 if (thisexp) | |
608 ne->thisexp = thisexp->doInline(ids); | |
609 ne->newargs = arrayExpressiondoInline(ne->newargs, ids); | |
610 ne->arguments = arrayExpressiondoInline(ne->arguments, ids); | |
611 return ne; | |
612 } | |
613 | |
614 Expression *UnaExp::doInline(InlineDoState *ids) | |
615 { | |
616 UnaExp *ue = (UnaExp *)copy(); | |
617 | |
618 ue->e1 = e1->doInline(ids); | |
619 return ue; | |
620 } | |
621 | |
622 Expression *AssertExp::doInline(InlineDoState *ids) | |
623 { | |
624 AssertExp *ae = (AssertExp *)copy(); | |
625 | |
626 ae->e1 = e1->doInline(ids); | |
627 if (msg) | |
628 ae->msg = msg->doInline(ids); | |
629 return ae; | |
630 } | |
631 | |
632 Expression *BinExp::doInline(InlineDoState *ids) | |
633 { | |
634 BinExp *be = (BinExp *)copy(); | |
635 | |
636 be->e1 = e1->doInline(ids); | |
637 be->e2 = e2->doInline(ids); | |
638 return be; | |
639 } | |
640 | |
641 Expression *CallExp::doInline(InlineDoState *ids) | |
642 { | |
643 CallExp *ce; | |
644 | |
645 ce = (CallExp *)copy(); | |
646 ce->e1 = e1->doInline(ids); | |
647 ce->arguments = arrayExpressiondoInline(arguments, ids); | |
648 return ce; | |
649 } | |
650 | |
651 | |
652 Expression *IndexExp::doInline(InlineDoState *ids) | |
653 { | |
654 IndexExp *are = (IndexExp *)copy(); | |
655 | |
656 are->e1 = e1->doInline(ids); | |
657 | |
658 if (lengthVar) | |
659 { //printf("lengthVar\n"); | |
660 VarDeclaration *vd = lengthVar; | |
661 ExpInitializer *ie; | |
662 ExpInitializer *ieto; | |
663 VarDeclaration *vto; | |
664 | |
665 vto = new VarDeclaration(vd->loc, vd->type, vd->ident, vd->init); | |
666 *vto = *vd; | |
667 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
|
668 #if IN_DMD |
1 | 669 vto->csym = NULL; |
670 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
|
671 #endif |
1 | 672 |
673 ids->from.push(vd); | |
674 ids->to.push(vto); | |
675 | |
676 if (vd->init) | |
677 { | |
678 ie = vd->init->isExpInitializer(); | |
679 assert(ie); | |
680 ieto = new ExpInitializer(ie->loc, ie->exp->doInline(ids)); | |
681 vto->init = ieto; | |
682 } | |
683 | |
684 are->lengthVar = (VarDeclaration *) (void *)vto; | |
685 } | |
686 are->e2 = e2->doInline(ids); | |
687 return are; | |
688 } | |
689 | |
690 | |
691 Expression *SliceExp::doInline(InlineDoState *ids) | |
692 { | |
693 SliceExp *are = (SliceExp *)copy(); | |
694 | |
695 are->e1 = e1->doInline(ids); | |
696 | |
697 if (lengthVar) | |
698 { //printf("lengthVar\n"); | |
699 VarDeclaration *vd = lengthVar; | |
700 ExpInitializer *ie; | |
701 ExpInitializer *ieto; | |
702 VarDeclaration *vto; | |
703 | |
704 vto = new VarDeclaration(vd->loc, vd->type, vd->ident, vd->init); | |
705 *vto = *vd; | |
706 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
|
707 #if IN_DMD |
1 | 708 vto->csym = NULL; |
709 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
|
710 #endif |
1 | 711 |
712 ids->from.push(vd); | |
713 ids->to.push(vto); | |
714 | |
715 if (vd->init) | |
716 { | |
717 ie = vd->init->isExpInitializer(); | |
718 assert(ie); | |
719 ieto = new ExpInitializer(ie->loc, ie->exp->doInline(ids)); | |
720 vto->init = ieto; | |
721 } | |
722 | |
723 are->lengthVar = (VarDeclaration *) (void *)vto; | |
724 } | |
725 if (lwr) | |
726 are->lwr = lwr->doInline(ids); | |
727 if (upr) | |
728 are->upr = upr->doInline(ids); | |
729 return are; | |
730 } | |
731 | |
732 | |
733 Expression *TupleExp::doInline(InlineDoState *ids) | |
734 { | |
735 TupleExp *ce; | |
736 | |
737 ce = (TupleExp *)copy(); | |
738 ce->exps = arrayExpressiondoInline(exps, ids); | |
739 return ce; | |
740 } | |
741 | |
742 | |
743 Expression *ArrayLiteralExp::doInline(InlineDoState *ids) | |
744 { | |
745 ArrayLiteralExp *ce; | |
746 | |
747 ce = (ArrayLiteralExp *)copy(); | |
748 ce->elements = arrayExpressiondoInline(elements, ids); | |
749 return ce; | |
750 } | |
751 | |
752 | |
753 Expression *AssocArrayLiteralExp::doInline(InlineDoState *ids) | |
754 { | |
755 AssocArrayLiteralExp *ce; | |
756 | |
757 ce = (AssocArrayLiteralExp *)copy(); | |
758 ce->keys = arrayExpressiondoInline(keys, ids); | |
759 ce->values = arrayExpressiondoInline(values, ids); | |
760 return ce; | |
761 } | |
762 | |
763 | |
764 Expression *StructLiteralExp::doInline(InlineDoState *ids) | |
765 { | |
766 StructLiteralExp *ce; | |
767 | |
768 ce = (StructLiteralExp *)copy(); | |
769 ce->elements = arrayExpressiondoInline(elements, ids); | |
770 return ce; | |
771 } | |
772 | |
773 | |
774 Expression *ArrayExp::doInline(InlineDoState *ids) | |
775 { | |
776 ArrayExp *ce; | |
777 | |
778 ce = (ArrayExp *)copy(); | |
779 ce->e1 = e1->doInline(ids); | |
780 ce->arguments = arrayExpressiondoInline(arguments, ids); | |
781 return ce; | |
782 } | |
783 | |
784 | |
785 Expression *CondExp::doInline(InlineDoState *ids) | |
786 { | |
787 CondExp *ce = (CondExp *)copy(); | |
788 | |
789 ce->econd = econd->doInline(ids); | |
790 ce->e1 = e1->doInline(ids); | |
791 ce->e2 = e2->doInline(ids); | |
792 return ce; | |
793 } | |
794 | |
795 | |
796 /* ========== Walk the parse trees, and inline expand functions ============= */ | |
797 | |
798 /* Walk the trees, looking for functions to inline. | |
799 * Inline any that can be. | |
800 */ | |
801 | |
802 struct InlineScanState | |
803 { | |
804 FuncDeclaration *fd; // function being scanned | |
805 }; | |
806 | |
807 Statement *Statement::inlineScan(InlineScanState *iss) | |
808 { | |
809 return this; | |
810 } | |
811 | |
812 Statement *ExpStatement::inlineScan(InlineScanState *iss) | |
813 { | |
814 #if LOG | |
815 printf("ExpStatement::inlineScan(%s)\n", toChars()); | |
816 #endif | |
817 if (exp) | |
818 exp = exp->inlineScan(iss); | |
819 return this; | |
820 } | |
821 | |
822 Statement *CompoundStatement::inlineScan(InlineScanState *iss) | |
823 { | |
824 for (size_t i = 0; i < statements->dim; i++) | |
825 { Statement *s = (Statement *) statements->data[i]; | |
826 if (s) | |
827 statements->data[i] = (void *)s->inlineScan(iss); | |
828 } | |
829 return this; | |
830 } | |
831 | |
832 Statement *UnrolledLoopStatement::inlineScan(InlineScanState *iss) | |
833 { | |
834 for (size_t i = 0; i < statements->dim; i++) | |
835 { Statement *s = (Statement *) statements->data[i]; | |
836 if (s) | |
837 statements->data[i] = (void *)s->inlineScan(iss); | |
838 } | |
839 return this; | |
840 } | |
841 | |
842 Statement *ScopeStatement::inlineScan(InlineScanState *iss) | |
843 { | |
844 if (statement) | |
845 statement = statement->inlineScan(iss); | |
846 return this; | |
847 } | |
848 | |
849 Statement *WhileStatement::inlineScan(InlineScanState *iss) | |
850 { | |
851 condition = condition->inlineScan(iss); | |
852 body = body ? body->inlineScan(iss) : NULL; | |
853 return this; | |
854 } | |
855 | |
856 | |
857 Statement *DoStatement::inlineScan(InlineScanState *iss) | |
858 { | |
859 body = body ? body->inlineScan(iss) : NULL; | |
860 condition = condition->inlineScan(iss); | |
861 return this; | |
862 } | |
863 | |
864 | |
865 Statement *ForStatement::inlineScan(InlineScanState *iss) | |
866 { | |
867 if (init) | |
868 init = init->inlineScan(iss); | |
869 if (condition) | |
870 condition = condition->inlineScan(iss); | |
871 if (increment) | |
872 increment = increment->inlineScan(iss); | |
873 body = body->inlineScan(iss); | |
874 return this; | |
875 } | |
876 | |
877 | |
878 Statement *ForeachStatement::inlineScan(InlineScanState *iss) | |
879 { | |
880 aggr = aggr->inlineScan(iss); | |
92 | 881 if (body) |
882 body = body->inlineScan(iss); | |
1 | 883 return this; |
884 } | |
885 | |
886 | |
336 | 887 #if DMDV2 |
1 | 888 Statement *ForeachRangeStatement::inlineScan(InlineScanState *iss) |
889 { | |
890 lwr = lwr->inlineScan(iss); | |
891 upr = upr->inlineScan(iss); | |
92 | 892 if (body) |
893 body = body->inlineScan(iss); | |
1 | 894 return this; |
895 } | |
896 #endif | |
897 | |
898 | |
899 Statement *IfStatement::inlineScan(InlineScanState *iss) | |
900 { | |
901 condition = condition->inlineScan(iss); | |
902 if (ifbody) | |
903 ifbody = ifbody->inlineScan(iss); | |
904 if (elsebody) | |
905 elsebody = elsebody->inlineScan(iss); | |
906 return this; | |
907 } | |
908 | |
909 | |
910 Statement *SwitchStatement::inlineScan(InlineScanState *iss) | |
911 { | |
912 //printf("SwitchStatement::inlineScan()\n"); | |
913 condition = condition->inlineScan(iss); | |
914 body = body ? body->inlineScan(iss) : NULL; | |
915 if (sdefault) | |
916 sdefault = (DefaultStatement *)sdefault->inlineScan(iss); | |
917 if (cases) | |
918 { | |
919 for (int i = 0; i < cases->dim; i++) | |
920 { Statement *s; | |
921 | |
922 s = (Statement *) cases->data[i]; | |
923 cases->data[i] = (void *)s->inlineScan(iss); | |
924 } | |
925 } | |
926 return this; | |
927 } | |
928 | |
929 | |
930 Statement *CaseStatement::inlineScan(InlineScanState *iss) | |
931 { | |
932 //printf("CaseStatement::inlineScan()\n"); | |
933 exp = exp->inlineScan(iss); | |
934 if (statement) | |
935 statement = statement->inlineScan(iss); | |
936 return this; | |
937 } | |
938 | |
939 | |
940 Statement *DefaultStatement::inlineScan(InlineScanState *iss) | |
941 { | |
942 if (statement) | |
943 statement = statement->inlineScan(iss); | |
944 return this; | |
945 } | |
946 | |
947 | |
948 Statement *ReturnStatement::inlineScan(InlineScanState *iss) | |
949 { | |
1367
8026319762be
Merged DMD 1.045 !!!
Tomas Lindquist Olsen <tomas.l.olsen gmail com>
parents:
1146
diff
changeset
|
950 //printf("ReturnStatement::inlineScan()\n"); |
1 | 951 if (exp) |
1367
8026319762be
Merged DMD 1.045 !!!
Tomas Lindquist Olsen <tomas.l.olsen gmail com>
parents:
1146
diff
changeset
|
952 { |
1 | 953 exp = exp->inlineScan(iss); |
1367
8026319762be
Merged DMD 1.045 !!!
Tomas Lindquist Olsen <tomas.l.olsen gmail com>
parents:
1146
diff
changeset
|
954 } |
1 | 955 return this; |
956 } | |
957 | |
958 | |
959 Statement *SynchronizedStatement::inlineScan(InlineScanState *iss) | |
960 { | |
961 if (exp) | |
962 exp = exp->inlineScan(iss); | |
963 if (body) | |
964 body = body->inlineScan(iss); | |
965 return this; | |
966 } | |
967 | |
968 | |
969 Statement *WithStatement::inlineScan(InlineScanState *iss) | |
970 { | |
971 if (exp) | |
972 exp = exp->inlineScan(iss); | |
973 if (body) | |
974 body = body->inlineScan(iss); | |
975 return this; | |
976 } | |
977 | |
978 | |
979 Statement *TryCatchStatement::inlineScan(InlineScanState *iss) | |
980 { | |
981 if (body) | |
982 body = body->inlineScan(iss); | |
983 if (catches) | |
984 { | |
985 for (int i = 0; i < catches->dim; i++) | |
986 { Catch *c = (Catch *)catches->data[i]; | |
987 | |
988 if (c->handler) | |
989 c->handler = c->handler->inlineScan(iss); | |
990 } | |
991 } | |
992 return this; | |
993 } | |
994 | |
995 | |
996 Statement *TryFinallyStatement::inlineScan(InlineScanState *iss) | |
997 { | |
998 if (body) | |
999 body = body->inlineScan(iss); | |
1000 if (finalbody) | |
1001 finalbody = finalbody->inlineScan(iss); | |
1002 return this; | |
1003 } | |
1004 | |
1005 | |
1006 Statement *ThrowStatement::inlineScan(InlineScanState *iss) | |
1007 { | |
1008 if (exp) | |
1009 exp = exp->inlineScan(iss); | |
1010 return this; | |
1011 } | |
1012 | |
1013 | |
1014 Statement *VolatileStatement::inlineScan(InlineScanState *iss) | |
1015 { | |
1016 if (statement) | |
1017 statement = statement->inlineScan(iss); | |
1018 return this; | |
1019 } | |
1020 | |
1021 | |
1022 Statement *LabelStatement::inlineScan(InlineScanState *iss) | |
1023 { | |
1024 if (statement) | |
1025 statement = statement->inlineScan(iss); | |
1026 return this; | |
1027 } | |
1028 | |
1029 /* -------------------------- */ | |
1030 | |
1031 void arrayInlineScan(InlineScanState *iss, Array *arguments) | |
1032 { | |
1033 if (arguments) | |
1034 { | |
1035 for (int i = 0; i < arguments->dim; i++) | |
1036 { Expression *e = (Expression *)arguments->data[i]; | |
1037 | |
1038 if (e) | |
1039 { | |
1040 e = e->inlineScan(iss); | |
1041 arguments->data[i] = (void *)e; | |
1042 } | |
1043 } | |
1044 } | |
1045 } | |
1046 | |
1047 Expression *Expression::inlineScan(InlineScanState *iss) | |
1048 { | |
1049 return this; | |
1050 } | |
1051 | |
1052 void scanVar(Dsymbol *s, InlineScanState *iss) | |
1053 { | |
1054 VarDeclaration *vd = s->isVarDeclaration(); | |
1055 if (vd) | |
1056 { | |
1057 TupleDeclaration *td = vd->toAlias()->isTupleDeclaration(); | |
1058 if (td) | |
1059 { | |
1060 for (size_t i = 0; i < td->objects->dim; i++) | |
1061 { DsymbolExp *se = (DsymbolExp *)td->objects->data[i]; | |
1062 assert(se->op == TOKdsymbol); | |
1063 scanVar(se->s, iss); | |
1064 } | |
1065 } | |
1066 else | |
1067 { | |
1068 // Scan initializer (vd->init) | |
1069 if (vd->init) | |
1070 { | |
1071 ExpInitializer *ie = vd->init->isExpInitializer(); | |
1072 | |
1073 if (ie) | |
1074 { | |
1075 ie->exp = ie->exp->inlineScan(iss); | |
1076 } | |
1077 } | |
1078 } | |
1079 } | |
1080 } | |
1081 | |
1082 Expression *DeclarationExp::inlineScan(InlineScanState *iss) | |
1083 { | |
1084 //printf("DeclarationExp::inlineScan()\n"); | |
1085 scanVar(declaration, iss); | |
1086 return this; | |
1087 } | |
1088 | |
1089 Expression *UnaExp::inlineScan(InlineScanState *iss) | |
1090 { | |
1091 e1 = e1->inlineScan(iss); | |
1092 return this; | |
1093 } | |
1094 | |
1095 Expression *AssertExp::inlineScan(InlineScanState *iss) | |
1096 { | |
1097 e1 = e1->inlineScan(iss); | |
1098 if (msg) | |
1099 msg = msg->inlineScan(iss); | |
1100 return this; | |
1101 } | |
1102 | |
1103 Expression *BinExp::inlineScan(InlineScanState *iss) | |
1104 { | |
1105 e1 = e1->inlineScan(iss); | |
1106 e2 = e2->inlineScan(iss); | |
1107 return this; | |
1108 } | |
1109 | |
1110 | |
1111 Expression *CallExp::inlineScan(InlineScanState *iss) | |
1112 { Expression *e = this; | |
1113 | |
1114 //printf("CallExp::inlineScan()\n"); | |
1115 e1 = e1->inlineScan(iss); | |
1116 arrayInlineScan(iss, arguments); | |
1117 | |
1118 if (e1->op == TOKvar) | |
1119 { | |
1120 VarExp *ve = (VarExp *)e1; | |
1121 FuncDeclaration *fd = ve->var->isFuncDeclaration(); | |
1122 | |
1123 if (fd && fd != iss->fd && fd->canInline(0)) | |
1124 { | |
1125 e = fd->doInline(iss, NULL, arguments); | |
1126 } | |
1127 } | |
1128 else if (e1->op == TOKdotvar) | |
1129 { | |
1130 DotVarExp *dve = (DotVarExp *)e1; | |
1131 FuncDeclaration *fd = dve->var->isFuncDeclaration(); | |
1132 | |
1133 if (fd && fd != iss->fd && fd->canInline(1)) | |
1134 { | |
1135 if (dve->e1->op == TOKcall && | |
1136 dve->e1->type->toBasetype()->ty == Tstruct) | |
1137 { | |
1138 /* To create ethis, we'll need to take the address | |
1139 * of dve->e1, but this won't work if dve->e1 is | |
1140 * a function call. | |
1141 */ | |
1142 ; | |
1143 } | |
1144 else | |
1145 e = fd->doInline(iss, dve->e1, arguments); | |
1146 } | |
1147 } | |
1148 | |
1149 return e; | |
1150 } | |
1151 | |
1152 | |
1153 Expression *SliceExp::inlineScan(InlineScanState *iss) | |
1154 { | |
1155 e1 = e1->inlineScan(iss); | |
1156 if (lwr) | |
1157 lwr = lwr->inlineScan(iss); | |
1158 if (upr) | |
1159 upr = upr->inlineScan(iss); | |
1160 return this; | |
1161 } | |
1162 | |
1163 | |
1164 Expression *TupleExp::inlineScan(InlineScanState *iss) | |
1165 { Expression *e = this; | |
1166 | |
1167 //printf("TupleExp::inlineScan()\n"); | |
1168 arrayInlineScan(iss, exps); | |
1169 | |
1170 return e; | |
1171 } | |
1172 | |
1173 | |
1174 Expression *ArrayLiteralExp::inlineScan(InlineScanState *iss) | |
1175 { Expression *e = this; | |
1176 | |
1177 //printf("ArrayLiteralExp::inlineScan()\n"); | |
1178 arrayInlineScan(iss, elements); | |
1179 | |
1180 return e; | |
1181 } | |
1182 | |
1183 | |
1184 Expression *AssocArrayLiteralExp::inlineScan(InlineScanState *iss) | |
1185 { Expression *e = this; | |
1186 | |
1187 //printf("AssocArrayLiteralExp::inlineScan()\n"); | |
1188 arrayInlineScan(iss, keys); | |
1189 arrayInlineScan(iss, values); | |
1190 | |
1191 return e; | |
1192 } | |
1193 | |
1194 | |
1195 Expression *StructLiteralExp::inlineScan(InlineScanState *iss) | |
1196 { Expression *e = this; | |
1197 | |
1198 //printf("StructLiteralExp::inlineScan()\n"); | |
1199 arrayInlineScan(iss, elements); | |
1200 | |
1201 return e; | |
1202 } | |
1203 | |
1204 | |
1205 Expression *ArrayExp::inlineScan(InlineScanState *iss) | |
1206 { Expression *e = this; | |
1207 | |
1208 //printf("ArrayExp::inlineScan()\n"); | |
1209 e1 = e1->inlineScan(iss); | |
1210 arrayInlineScan(iss, arguments); | |
1211 | |
1212 return e; | |
1213 } | |
1214 | |
1215 | |
1216 Expression *CondExp::inlineScan(InlineScanState *iss) | |
1217 { | |
1218 econd = econd->inlineScan(iss); | |
1219 e1 = e1->inlineScan(iss); | |
1220 e2 = e2->inlineScan(iss); | |
1221 return this; | |
1222 } | |
1223 | |
1224 | |
1225 /* ========== =============== */ | |
1226 | |
1227 void FuncDeclaration::inlineScan() | |
1228 { | |
1229 InlineScanState iss; | |
1230 | |
1231 #if LOG | |
1232 printf("FuncDeclaration::inlineScan('%s')\n", toChars()); | |
1233 #endif | |
1234 memset(&iss, 0, sizeof(iss)); | |
1235 iss.fd = this; | |
1236 if (fbody) | |
1237 { | |
1238 inlineNest++; | |
1239 fbody = fbody->inlineScan(&iss); | |
1240 inlineNest--; | |
1241 } | |
1242 } | |
1243 | |
1244 int FuncDeclaration::canInline(int hasthis, int hdrscan) | |
1245 { | |
1246 InlineCostState ics; | |
1247 int cost; | |
1248 | |
1249 #define CANINLINE_LOG 0 | |
1250 | |
1251 #if CANINLINE_LOG | |
1252 printf("FuncDeclaration::canInline(hasthis = %d, '%s')\n", hasthis, toChars()); | |
1253 #endif | |
1254 | |
1255 if (needThis() && !hasthis) | |
1256 return 0; | |
1257 | |
1367
8026319762be
Merged DMD 1.045 !!!
Tomas Lindquist Olsen <tomas.l.olsen gmail com>
parents:
1146
diff
changeset
|
1258 if (inlineNest || (semanticRun < 3 && !hdrscan)) |
1 | 1259 { |
1260 #if CANINLINE_LOG | |
1261 printf("\t1: no, inlineNest = %d, semanticRun = %d\n", inlineNest, semanticRun); | |
1262 #endif | |
1263 return 0; | |
1264 } | |
1265 | |
1266 switch (inlineStatus) | |
1267 { | |
1268 case ILSyes: | |
1269 #if CANINLINE_LOG | |
1367
8026319762be
Merged DMD 1.045 !!!
Tomas Lindquist Olsen <tomas.l.olsen gmail com>
parents:
1146
diff
changeset
|
1270 printf("\t1: yes %s\n", toChars()); |
1 | 1271 #endif |
1272 return 1; | |
1273 | |
1274 case ILSno: | |
1275 #if CANINLINE_LOG | |
1367
8026319762be
Merged DMD 1.045 !!!
Tomas Lindquist Olsen <tomas.l.olsen gmail com>
parents:
1146
diff
changeset
|
1276 printf("\t1: no %s\n", toChars()); |
1 | 1277 #endif |
1278 return 0; | |
1279 | |
1280 case ILSuninitialized: | |
1281 break; | |
1282 | |
1283 default: | |
1284 assert(0); | |
1285 } | |
1286 | |
1287 if (type) | |
1288 { assert(type->ty == Tfunction); | |
1289 TypeFunction *tf = (TypeFunction *)(type); | |
1482
d9c5f5a43403
Run `semantic3` on imported modules, and emit new symbols with
Frits van Bommel <fvbommel wxs.nl>
parents:
1367
diff
changeset
|
1290 #if IN_LLVM |
d9c5f5a43403
Run `semantic3` on imported modules, and emit new symbols with
Frits van Bommel <fvbommel wxs.nl>
parents:
1367
diff
changeset
|
1291 // LDC: Only extern(C) varargs count. |
d9c5f5a43403
Run `semantic3` on imported modules, and emit new symbols with
Frits van Bommel <fvbommel wxs.nl>
parents:
1367
diff
changeset
|
1292 if (tf->linkage != LINKd) |
d9c5f5a43403
Run `semantic3` on imported modules, and emit new symbols with
Frits van Bommel <fvbommel wxs.nl>
parents:
1367
diff
changeset
|
1293 #endif |
1 | 1294 if (tf->varargs == 1) // no variadic parameter lists |
1295 goto Lno; | |
1296 | |
1297 /* Don't inline a function that returns non-void, but has | |
1298 * no return expression. | |
1299 */ | |
1300 if (tf->next && tf->next->ty != Tvoid && | |
1301 !(hasReturnExp & 1) && | |
1302 !hdrscan) | |
1303 goto Lno; | |
1304 } | |
1482
d9c5f5a43403
Run `semantic3` on imported modules, and emit new symbols with
Frits van Bommel <fvbommel wxs.nl>
parents:
1367
diff
changeset
|
1305 #if !IN_LLVM |
d9c5f5a43403
Run `semantic3` on imported modules, and emit new symbols with
Frits van Bommel <fvbommel wxs.nl>
parents:
1367
diff
changeset
|
1306 // LDC: Only extern(C) varargs count, and ctors use extern(D). |
1 | 1307 else |
1308 { CtorDeclaration *ctor = isCtorDeclaration(); | |
1309 | |
1310 if (ctor && ctor->varargs == 1) | |
1311 goto Lno; | |
1312 } | |
1482
d9c5f5a43403
Run `semantic3` on imported modules, and emit new symbols with
Frits van Bommel <fvbommel wxs.nl>
parents:
1367
diff
changeset
|
1313 #endif |
1 | 1314 |
1315 if ( | |
1316 !fbody || | |
1317 !hdrscan && | |
1318 ( | |
1319 #if 0 | |
1320 isCtorDeclaration() || // cannot because need to convert: | |
1321 // return; | |
1322 // to: | |
1323 // return this; | |
1324 #endif | |
1325 isSynchronized() || | |
1326 isImportedSymbol() || | |
1482
d9c5f5a43403
Run `semantic3` on imported modules, and emit new symbols with
Frits van Bommel <fvbommel wxs.nl>
parents:
1367
diff
changeset
|
1327 #if !IN_LLVM |
336 | 1328 #if DMDV2 |
92 | 1329 closureVars.dim || // no nested references to this frame |
1330 #else | |
1 | 1331 nestedFrameRef || // no nested references to this frame |
92 | 1332 #endif |
1482
d9c5f5a43403
Run `semantic3` on imported modules, and emit new symbols with
Frits van Bommel <fvbommel wxs.nl>
parents:
1367
diff
changeset
|
1333 #endif // !IN_LLVM |
1 | 1334 (isVirtual() && !isFinal()) |
1335 )) | |
1336 { | |
1337 goto Lno; | |
1338 } | |
1339 | |
1482
d9c5f5a43403
Run `semantic3` on imported modules, and emit new symbols with
Frits van Bommel <fvbommel wxs.nl>
parents:
1367
diff
changeset
|
1340 #if !IN_LLVM |
1 | 1341 /* If any parameters are Tsarray's (which are passed by reference) |
1342 * or out parameters (also passed by reference), don't do inlining. | |
1343 */ | |
1344 if (parameters) | |
1345 { | |
1346 for (int i = 0; i < parameters->dim; i++) | |
1347 { | |
1348 VarDeclaration *v = (VarDeclaration *)parameters->data[i]; | |
1349 if (v->isOut() || v->isRef() || v->type->toBasetype()->ty == Tsarray) | |
1350 goto Lno; | |
1351 } | |
1352 } | |
1482
d9c5f5a43403
Run `semantic3` on imported modules, and emit new symbols with
Frits van Bommel <fvbommel wxs.nl>
parents:
1367
diff
changeset
|
1353 #endif |
1 | 1354 |
1355 memset(&ics, 0, sizeof(ics)); | |
1356 ics.hasthis = hasthis; | |
1357 ics.fd = this; | |
1358 ics.hdrscan = hdrscan; | |
1359 cost = fbody->inlineCost(&ics); | |
1360 #if CANINLINE_LOG | |
1361 printf("cost = %d\n", cost); | |
1362 #endif | |
1363 if (cost >= COST_MAX) | |
1364 goto Lno; | |
1365 | |
1482
d9c5f5a43403
Run `semantic3` on imported modules, and emit new symbols with
Frits van Bommel <fvbommel wxs.nl>
parents:
1367
diff
changeset
|
1366 #if !IN_LLVM |
1 | 1367 if (!hdrscan) // Don't scan recursively for header content scan |
1368 inlineScan(); | |
1482
d9c5f5a43403
Run `semantic3` on imported modules, and emit new symbols with
Frits van Bommel <fvbommel wxs.nl>
parents:
1367
diff
changeset
|
1369 #endif |
1 | 1370 |
1371 Lyes: | |
1372 if (!hdrscan) // Don't modify inlineStatus for header content scan | |
1373 inlineStatus = ILSyes; | |
1374 #if CANINLINE_LOG | |
1367
8026319762be
Merged DMD 1.045 !!!
Tomas Lindquist Olsen <tomas.l.olsen gmail com>
parents:
1146
diff
changeset
|
1375 printf("\t2: yes %s\n", toChars()); |
1 | 1376 #endif |
1377 return 1; | |
1378 | |
1379 Lno: | |
1380 if (!hdrscan) // Don't modify inlineStatus for header content scan | |
1381 inlineStatus = ILSno; | |
1382 #if CANINLINE_LOG | |
1367
8026319762be
Merged DMD 1.045 !!!
Tomas Lindquist Olsen <tomas.l.olsen gmail com>
parents:
1146
diff
changeset
|
1383 printf("\t2: no %s\n", toChars()); |
1 | 1384 #endif |
1385 return 0; | |
1386 } | |
1387 | |
1388 Expression *FuncDeclaration::doInline(InlineScanState *iss, Expression *ethis, Array *arguments) | |
1389 { | |
1390 InlineDoState ids; | |
1391 DeclarationExp *de; | |
1392 Expression *e = NULL; | |
1393 | |
1394 #if LOG | |
1395 printf("FuncDeclaration::doInline('%s')\n", toChars()); | |
1396 #endif | |
1397 | |
1398 memset(&ids, 0, sizeof(ids)); | |
1399 ids.parent = iss->fd; | |
1400 | |
1401 // Set up vthis | |
1402 if (ethis) | |
1403 { | |
1404 VarDeclaration *vthis; | |
1405 ExpInitializer *ei; | |
1406 VarExp *ve; | |
1407 | |
1408 if (ethis->type->ty != Tclass && ethis->type->ty != Tpointer) | |
1409 { | |
1410 ethis = ethis->addressOf(NULL); | |
1411 } | |
1412 | |
1413 ei = new ExpInitializer(ethis->loc, ethis); | |
1414 | |
1415 vthis = new VarDeclaration(ethis->loc, ethis->type, Id::This, ei); | |
1416 vthis->storage_class = STCin; | |
1417 vthis->linkage = LINKd; | |
1418 vthis->parent = iss->fd; | |
1419 | |
1420 ve = new VarExp(vthis->loc, vthis); | |
1421 ve->type = vthis->type; | |
1422 | |
1423 ei->exp = new AssignExp(vthis->loc, ve, ethis); | |
1424 ei->exp->type = ve->type; | |
1425 | |
1426 ids.vthis = vthis; | |
1427 } | |
1428 | |
1429 // Set up parameters | |
1430 if (ethis) | |
1431 { | |
1432 e = new DeclarationExp(0, ids.vthis); | |
1433 e->type = Type::tvoid; | |
1434 } | |
1435 | |
1436 if (arguments && arguments->dim) | |
1437 { | |
1438 assert(parameters->dim == arguments->dim); | |
1439 | |
1440 for (int i = 0; i < arguments->dim; i++) | |
1441 { | |
1442 VarDeclaration *vfrom = (VarDeclaration *)parameters->data[i]; | |
1443 VarDeclaration *vto; | |
1444 Expression *arg = (Expression *)arguments->data[i]; | |
1445 ExpInitializer *ei; | |
1446 VarExp *ve; | |
1447 | |
1448 ei = new ExpInitializer(arg->loc, arg); | |
1449 | |
1450 vto = new VarDeclaration(vfrom->loc, vfrom->type, vfrom->ident, ei); | |
1451 vto->storage_class |= vfrom->storage_class & (STCin | STCout | STClazy | STCref); | |
1452 vto->linkage = vfrom->linkage; | |
1453 vto->parent = iss->fd; | |
1454 //printf("vto = '%s', vto->storage_class = x%x\n", vto->toChars(), vto->storage_class); | |
1455 //printf("vto->parent = '%s'\n", iss->fd->toChars()); | |
1456 | |
1457 ve = new VarExp(vto->loc, vto); | |
1458 //ve->type = vto->type; | |
1459 ve->type = arg->type; | |
1460 | |
1461 ei->exp = new AssignExp(vto->loc, ve, arg); | |
1462 ei->exp->type = ve->type; | |
1463 //ve->type->print(); | |
1464 //arg->type->print(); | |
1465 //ei->exp->print(); | |
1466 | |
1467 ids.from.push(vfrom); | |
1468 ids.to.push(vto); | |
1469 | |
1470 de = new DeclarationExp(0, vto); | |
1471 de->type = Type::tvoid; | |
1472 | |
1473 e = Expression::combine(e, de); | |
1474 } | |
1475 } | |
1476 | |
1477 inlineNest++; | |
1478 Expression *eb = fbody->doInline(&ids); | |
1479 inlineNest--; | |
1480 //eb->type->print(); | |
1481 //eb->print(); | |
1482 //eb->dump(0); | |
1483 return Expression::combine(e, eb); | |
1484 } | |
1485 | |
1486 | |
1487 |