2 // Copyright (c) 1999-2007 by Digital Mars
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.
10 // Routines to perform function inlining
20 #include "declaration.h"
21 #include "aggregate.h"
22 #include "expression.h"
23 #include "statement.h"
26 /* ========== Compute cost of inlining =============== */
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.
32 struct InlineCostState
36 int hdrscan
; // !=0 if inline scan for 'header' content
40 const int COST_MAX
= 250;
42 int Statement::inlineCost(InlineCostState
*ics
)
44 return COST_MAX
; // default is we can't inline it
47 int ExpStatement::inlineCost(InlineCostState
*ics
)
49 return exp
? exp
->inlineCost(ics
) : 0;
52 int CompoundStatement::inlineCost(InlineCostState
*ics
)
55 for (size_t i
= 0; i
< statements
->dim
; i
++)
56 { Statement
*s
= (Statement
*) statements
->data
[i
];
59 cost
+= s
->inlineCost(ics
);
67 int UnrolledLoopStatement::inlineCost(InlineCostState
*ics
)
70 for (size_t i
= 0; i
< statements
->dim
; i
++)
71 { Statement
*s
= (Statement
*) statements
->data
[i
];
74 cost
+= s
->inlineCost(ics
);
82 int IfStatement::inlineCost(InlineCostState
*ics
)
86 /* Can't declare variables inside ?: expressions, so
87 * we cannot inline if a variable is declared.
92 cost
= condition
->inlineCost(ics
);
94 /* Specifically allow:
99 * Otherwise, we can't handle return statements nested in if's.
102 if (elsebody
&& ifbody
&&
103 ifbody
->isReturnStatement() &&
104 elsebody
->isReturnStatement())
106 cost
+= ifbody
->inlineCost(ics
);
107 cost
+= elsebody
->inlineCost(ics
);
108 //printf("cost = %d\n", cost);
114 cost
+= ifbody
->inlineCost(ics
);
116 cost
+= elsebody
->inlineCost(ics
);
122 int ReturnStatement::inlineCost(InlineCostState
*ics
)
124 // Can't handle return statements nested in if's
127 return exp
? exp
->inlineCost(ics
) : 0;
130 /* -------------------------- */
132 int arrayInlineCost(InlineCostState
*ics
, Array
*arguments
)
137 for (int i
= 0; i
< arguments
->dim
; i
++)
138 { Expression
*e
= (Expression
*)arguments
->data
[i
];
141 cost
+= e
->inlineCost(ics
);
147 int Expression::inlineCost(InlineCostState
*ics
)
152 int VarExp::inlineCost(InlineCostState
*ics
)
154 //printf("VarExp::inlineCost() %s\n", toChars());
158 int ThisExp::inlineCost(InlineCostState
*ics
)
160 FuncDeclaration
*fd
= ics
->fd
;
162 if (fd
->isNested() || !ics
->hasthis
)
167 int SuperExp::inlineCost(InlineCostState
*ics
)
169 FuncDeclaration
*fd
= ics
->fd
;
171 if (fd
->isNested() || !ics
->hasthis
)
176 int TupleExp::inlineCost(InlineCostState
*ics
)
178 return 1 + arrayInlineCost(ics
, exps
);
181 int ArrayLiteralExp::inlineCost(InlineCostState
*ics
)
183 return 1 + arrayInlineCost(ics
, elements
);
186 int AssocArrayLiteralExp::inlineCost(InlineCostState
*ics
)
188 return 1 + arrayInlineCost(ics
, keys
) + arrayInlineCost(ics
, values
);
191 int StructLiteralExp::inlineCost(InlineCostState
*ics
)
193 return 1 + arrayInlineCost(ics
, elements
);
196 int FuncExp::inlineCost(InlineCostState
*ics
)
198 // Right now, this makes the function be output to the .obj file twice.
202 int DelegateExp::inlineCost(InlineCostState
*ics
)
207 int DeclarationExp::inlineCost(InlineCostState
*ics
)
211 //printf("DeclarationExp::inlineCost()\n");
212 vd
= declaration
->isVarDeclaration();
215 TupleDeclaration
*td
= vd
->toAlias()->isTupleDeclaration();
219 return COST_MAX
; // finish DeclarationExp::doInline
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
)
225 Expression
*eo
= (Expression
*)o
;
226 if (eo
->op
!= TOKdsymbol
)
229 return td
->objects
->dim
;
232 if (!ics
->hdrscan
&& vd
->isDataseg())
236 // Scan initializer (vd->init)
239 ExpInitializer
*ie
= vd
->init
->isExpInitializer();
243 cost
+= ie
->exp
->inlineCost(ics
);
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())
256 //printf("DeclarationExp::inlineCost('%s')\n", toChars());
260 int UnaExp::inlineCost(InlineCostState
*ics
)
262 return 1 + e1
->inlineCost(ics
);
265 int AssertExp::inlineCost(InlineCostState
*ics
)
267 return 1 + e1
->inlineCost(ics
) + (msg
? msg
->inlineCost(ics
) : 0);
270 int BinExp::inlineCost(InlineCostState
*ics
)
272 return 1 + e1
->inlineCost(ics
) + e2
->inlineCost(ics
);
275 int CallExp::inlineCost(InlineCostState
*ics
)
277 return 1 + e1
->inlineCost(ics
) + arrayInlineCost(ics
, arguments
);
280 int SliceExp::inlineCost(InlineCostState
*ics
)
283 cost
= 1 + e1
->inlineCost(ics
);
285 cost
+= lwr
->inlineCost(ics
);
287 cost
+= upr
->inlineCost(ics
);
291 int ArrayExp::inlineCost(InlineCostState
*ics
)
293 return 1 + e1
->inlineCost(ics
) + arrayInlineCost(ics
, arguments
);
297 int CondExp::inlineCost(InlineCostState
*ics
)
300 e1
->inlineCost(ics
) +
301 e2
->inlineCost(ics
) +
302 econd
->inlineCost(ics
);
306 /* ======================== Perform the inlining ============================== */
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
316 VarDeclaration
*vthis
;
317 Array from
; // old Dsymbols
318 Array to
; // parallel array of new Dsymbols
319 Dsymbol
*parent
; // new parent
322 Expression
*Statement::doInline(InlineDoState
*ids
)
325 return NULL
; // default is we can't inline it
328 Expression
*ExpStatement::doInline(InlineDoState
*ids
)
331 if (exp
) printf("ExpStatement::doInline() '%s'\n", exp
->toChars());
333 return exp
? exp
->doInline(ids
) : NULL
;
336 Expression
*CompoundStatement::doInline(InlineDoState
*ids
)
338 Expression
*e
= NULL
;
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
];
345 Expression
*e2
= s
->doInline(ids
);
346 e
= Expression::combine(e
, e2
);
347 if (s
->isReturnStatement())
356 IfStatement
*ifs
= s
->isIfStatement();
357 if (ifs
&& ifs
->elsebody
&& ifs
->ifbody
&&
358 ifs
->ifbody
->isReturnStatement() &&
359 ifs
->elsebody
->isReturnStatement()
368 Expression
*UnrolledLoopStatement::doInline(InlineDoState
*ids
)
370 Expression
*e
= NULL
;
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
];
377 Expression
*e2
= s
->doInline(ids
);
378 e
= Expression::combine(e
, e2
);
379 if (s
->isReturnStatement())
386 Expression
*IfStatement::doInline(InlineDoState
*ids
)
394 econd
= condition
->doInline(ids
);
397 e1
= ifbody
->doInline(ids
);
401 e2
= elsebody
->doInline(ids
);
406 e
= new CondExp(econd
->loc
, econd
, e1
, e2
);
411 e
= new AndAndExp(econd
->loc
, econd
, e1
);
412 e
->type
= Type::tvoid
;
416 e
= new OrOrExp(econd
->loc
, econd
, e2
);
417 e
->type
= Type::tvoid
;
426 Expression
*ReturnStatement::doInline(InlineDoState
*ids
)
428 //printf("ReturnStatement::doInline() '%s'\n", exp ? exp->toChars() : "");
429 return exp
? exp
->doInline(ids
) : 0;
432 /* --------------------------------------------------------------- */
434 /******************************
435 * Perform doInline() on an array of Expressions.
438 Expressions
*arrayExpressiondoInline(Expressions
*a
, InlineDoState
*ids
)
439 { Expressions
*newa
= NULL
;
443 newa
= new Expressions();
444 newa
->setDim(a
->dim
);
446 for (int i
= 0; i
< a
->dim
; i
++)
447 { Expression
*e
= (Expression
*)a
->data
[i
];
451 e
= e
->doInline(ids
);
452 newa
->data
[i
] = (void *)e
;
459 Expression
*Expression::doInline(InlineDoState
*ids
)
461 //printf("Expression::doInline(%s): %s\n", Token::toChars(op), toChars());
465 Expression
*SymOffExp::doInline(InlineDoState
*ids
)
469 //printf("SymOffExp::doInline(%s)\n", toChars());
470 for (i
= 0; i
< ids
->from
.dim
; i
++)
472 if (var
== (Declaration
*)ids
->from
.data
[i
])
474 SymOffExp
*se
= (SymOffExp
*)copy();
476 se
->var
= (Declaration
*)ids
->to
.data
[i
];
483 Expression
*VarExp::doInline(InlineDoState
*ids
)
487 //printf("VarExp::doInline(%s)\n", toChars());
488 for (i
= 0; i
< ids
->from
.dim
; i
++)
490 if (var
== (Declaration
*)ids
->from
.data
[i
])
492 VarExp
*ve
= (VarExp
*)copy();
494 ve
->var
= (Declaration
*)ids
->to
.data
[i
];
501 Expression
*ThisExp::doInline(InlineDoState
*ids
)
504 //error("no 'this' when inlining %s", ids->parent->toChars());
510 VarExp
*ve
= new VarExp(loc
, ids
->vthis
);
515 Expression
*SuperExp::doInline(InlineDoState
*ids
)
519 VarExp
*ve
= new VarExp(loc
, ids
->vthis
);
524 Expression
*DeclarationExp::doInline(InlineDoState
*ids
)
525 { DeclarationExp
*de
= (DeclarationExp
*)copy();
528 //printf("DeclarationExp::doInline(%s)\n", toChars());
529 vd
= declaration
->isVarDeclaration();
533 // Need to figure this out before inlining can work for tuples
534 TupleDeclaration
*td
= vd
->toAlias()->isTupleDeclaration();
537 for (size_t i
= 0; i
< td
->objects
->dim
; i
++)
538 { DsymbolExp
*se
= (DsymbolExp
*)td
->objects
->data
[i
];
539 assert(se
->op
== TOKdsymbol
);
542 return st
->objects
->dim
;
551 vto
= new VarDeclaration(vd
->loc
, vd
->type
, vd
->ident
, vd
->init
);
553 vto
->parent
= ids
->parent
;
562 if (vd
->init
->isVoidInitializer())
564 vto
->init
= new VoidInitializer(vd
->init
->loc
);
568 ExpInitializer
*ie
= vd
->init
->isExpInitializer();
570 vto
->init
= new ExpInitializer(ie
->loc
, ie
->exp
->doInline(ids
));
573 de
->declaration
= (Dsymbol
*) (void *)vto
;
576 /* This needs work, like DeclarationExp::toElem(), if we are
577 * to handle TemplateMixin's. For now, we just don't inline them.
582 Expression
*NewExp::doInline(InlineDoState
*ids
)
584 //printf("NewExp::doInline(): %s\n", toChars());
585 NewExp
*ne
= (NewExp
*)copy();
588 ne
->thisexp
= thisexp
->doInline(ids
);
589 ne
->newargs
= arrayExpressiondoInline(ne
->newargs
, ids
);
590 ne
->arguments
= arrayExpressiondoInline(ne
->arguments
, ids
);
594 Expression
*UnaExp::doInline(InlineDoState
*ids
)
596 UnaExp
*ue
= (UnaExp
*)copy();
598 ue
->e1
= e1
->doInline(ids
);
602 Expression
*AssertExp::doInline(InlineDoState
*ids
)
604 AssertExp
*ae
= (AssertExp
*)copy();
606 ae
->e1
= e1
->doInline(ids
);
608 ae
->msg
= msg
->doInline(ids
);
612 Expression
*BinExp::doInline(InlineDoState
*ids
)
614 BinExp
*be
= (BinExp
*)copy();
616 be
->e1
= e1
->doInline(ids
);
617 be
->e2
= e2
->doInline(ids
);
621 Expression
*CallExp::doInline(InlineDoState
*ids
)
625 ce
= (CallExp
*)copy();
626 ce
->e1
= e1
->doInline(ids
);
627 ce
->arguments
= arrayExpressiondoInline(arguments
, ids
);
632 Expression
*IndexExp::doInline(InlineDoState
*ids
)
634 IndexExp
*are
= (IndexExp
*)copy();
636 are
->e1
= e1
->doInline(ids
);
639 { //printf("lengthVar\n");
640 VarDeclaration
*vd
= lengthVar
;
642 ExpInitializer
*ieto
;
645 vto
= new VarDeclaration(vd
->loc
, vd
->type
, vd
->ident
, vd
->init
);
647 vto
->parent
= ids
->parent
;
656 ie
= vd
->init
->isExpInitializer();
658 ieto
= new ExpInitializer(ie
->loc
, ie
->exp
->doInline(ids
));
662 are
->lengthVar
= (VarDeclaration
*) (void *)vto
;
664 are
->e2
= e2
->doInline(ids
);
669 Expression
*SliceExp::doInline(InlineDoState
*ids
)
671 SliceExp
*are
= (SliceExp
*)copy();
673 are
->e1
= e1
->doInline(ids
);
676 { //printf("lengthVar\n");
677 VarDeclaration
*vd
= lengthVar
;
679 ExpInitializer
*ieto
;
682 vto
= new VarDeclaration(vd
->loc
, vd
->type
, vd
->ident
, vd
->init
);
684 vto
->parent
= ids
->parent
;
693 ie
= vd
->init
->isExpInitializer();
695 ieto
= new ExpInitializer(ie
->loc
, ie
->exp
->doInline(ids
));
699 are
->lengthVar
= (VarDeclaration
*) (void *)vto
;
702 are
->lwr
= lwr
->doInline(ids
);
704 are
->upr
= upr
->doInline(ids
);
709 Expression
*TupleExp::doInline(InlineDoState
*ids
)
713 ce
= (TupleExp
*)copy();
714 ce
->exps
= arrayExpressiondoInline(exps
, ids
);
719 Expression
*ArrayLiteralExp::doInline(InlineDoState
*ids
)
723 ce
= (ArrayLiteralExp
*)copy();
724 ce
->elements
= arrayExpressiondoInline(elements
, ids
);
729 Expression
*AssocArrayLiteralExp::doInline(InlineDoState
*ids
)
731 AssocArrayLiteralExp
*ce
;
733 ce
= (AssocArrayLiteralExp
*)copy();
734 ce
->keys
= arrayExpressiondoInline(keys
, ids
);
735 ce
->values
= arrayExpressiondoInline(values
, ids
);
740 Expression
*StructLiteralExp::doInline(InlineDoState
*ids
)
742 StructLiteralExp
*ce
;
744 ce
= (StructLiteralExp
*)copy();
745 ce
->elements
= arrayExpressiondoInline(elements
, ids
);
750 Expression
*ArrayExp::doInline(InlineDoState
*ids
)
754 ce
= (ArrayExp
*)copy();
755 ce
->e1
= e1
->doInline(ids
);
756 ce
->arguments
= arrayExpressiondoInline(arguments
, ids
);
761 Expression
*CondExp::doInline(InlineDoState
*ids
)
763 CondExp
*ce
= (CondExp
*)copy();
765 ce
->econd
= econd
->doInline(ids
);
766 ce
->e1
= e1
->doInline(ids
);
767 ce
->e2
= e2
->doInline(ids
);
772 /* ========== Walk the parse trees, and inline expand functions ============= */
774 /* Walk the trees, looking for functions to inline.
775 * Inline any that can be.
778 struct InlineScanState
780 FuncDeclaration
*fd
; // function being scanned
783 Statement
*Statement::inlineScan(InlineScanState
*iss
)
788 Statement
*ExpStatement::inlineScan(InlineScanState
*iss
)
791 printf("ExpStatement::inlineScan(%s)\n", toChars());
794 exp
= exp
->inlineScan(iss
);
798 Statement
*CompoundStatement::inlineScan(InlineScanState
*iss
)
800 for (size_t i
= 0; i
< statements
->dim
; i
++)
801 { Statement
*s
= (Statement
*) statements
->data
[i
];
803 statements
->data
[i
] = (void *)s
->inlineScan(iss
);
808 Statement
*UnrolledLoopStatement::inlineScan(InlineScanState
*iss
)
810 for (size_t i
= 0; i
< statements
->dim
; i
++)
811 { Statement
*s
= (Statement
*) statements
->data
[i
];
813 statements
->data
[i
] = (void *)s
->inlineScan(iss
);
818 Statement
*ScopeStatement::inlineScan(InlineScanState
*iss
)
821 statement
= statement
->inlineScan(iss
);
825 Statement
*WhileStatement::inlineScan(InlineScanState
*iss
)
827 condition
= condition
->inlineScan(iss
);
828 body
= body
? body
->inlineScan(iss
) : NULL
;
833 Statement
*DoStatement::inlineScan(InlineScanState
*iss
)
835 body
= body
? body
->inlineScan(iss
) : NULL
;
836 condition
= condition
->inlineScan(iss
);
841 Statement
*ForStatement::inlineScan(InlineScanState
*iss
)
844 init
= init
->inlineScan(iss
);
846 condition
= condition
->inlineScan(iss
);
848 increment
= increment
->inlineScan(iss
);
849 body
= body
->inlineScan(iss
);
854 Statement
*ForeachStatement::inlineScan(InlineScanState
*iss
)
856 aggr
= aggr
->inlineScan(iss
);
858 body
= body
->inlineScan(iss
);
864 Statement
*ForeachRangeStatement::inlineScan(InlineScanState
*iss
)
866 lwr
= lwr
->inlineScan(iss
);
867 upr
= upr
->inlineScan(iss
);
869 body
= body
->inlineScan(iss
);
875 Statement
*IfStatement::inlineScan(InlineScanState
*iss
)
877 condition
= condition
->inlineScan(iss
);
879 ifbody
= ifbody
->inlineScan(iss
);
881 elsebody
= elsebody
->inlineScan(iss
);
886 Statement
*SwitchStatement::inlineScan(InlineScanState
*iss
)
888 //printf("SwitchStatement::inlineScan()\n");
889 condition
= condition
->inlineScan(iss
);
890 body
= body
? body
->inlineScan(iss
) : NULL
;
892 sdefault
= (DefaultStatement
*)sdefault
->inlineScan(iss
);
895 for (int i
= 0; i
< cases
->dim
; i
++)
898 s
= (Statement
*) cases
->data
[i
];
899 cases
->data
[i
] = (void *)s
->inlineScan(iss
);
906 Statement
*CaseStatement::inlineScan(InlineScanState
*iss
)
908 //printf("CaseStatement::inlineScan()\n");
909 exp
= exp
->inlineScan(iss
);
911 statement
= statement
->inlineScan(iss
);
916 Statement
*DefaultStatement::inlineScan(InlineScanState
*iss
)
919 statement
= statement
->inlineScan(iss
);
924 Statement
*ReturnStatement::inlineScan(InlineScanState
*iss
)
927 exp
= exp
->inlineScan(iss
);
932 Statement
*SynchronizedStatement::inlineScan(InlineScanState
*iss
)
935 exp
= exp
->inlineScan(iss
);
937 body
= body
->inlineScan(iss
);
942 Statement
*WithStatement::inlineScan(InlineScanState
*iss
)
945 exp
= exp
->inlineScan(iss
);
947 body
= body
->inlineScan(iss
);
952 Statement
*TryCatchStatement::inlineScan(InlineScanState
*iss
)
955 body
= body
->inlineScan(iss
);
958 for (int i
= 0; i
< catches
->dim
; i
++)
959 { Catch
*c
= (Catch
*)catches
->data
[i
];
962 c
->handler
= c
->handler
->inlineScan(iss
);
969 Statement
*TryFinallyStatement::inlineScan(InlineScanState
*iss
)
972 body
= body
->inlineScan(iss
);
974 finalbody
= finalbody
->inlineScan(iss
);
979 Statement
*ThrowStatement::inlineScan(InlineScanState
*iss
)
982 exp
= exp
->inlineScan(iss
);
987 Statement
*VolatileStatement::inlineScan(InlineScanState
*iss
)
990 statement
= statement
->inlineScan(iss
);
995 Statement
*LabelStatement::inlineScan(InlineScanState
*iss
)
998 statement
= statement
->inlineScan(iss
);
1002 /* -------------------------- */
1004 void arrayInlineScan(InlineScanState
*iss
, Array
*arguments
)
1008 for (int i
= 0; i
< arguments
->dim
; i
++)
1009 { Expression
*e
= (Expression
*)arguments
->data
[i
];
1013 e
= e
->inlineScan(iss
);
1014 arguments
->data
[i
] = (void *)e
;
1020 Expression
*Expression::inlineScan(InlineScanState
*iss
)
1025 void scanVar(Dsymbol
*s
, InlineScanState
*iss
)
1027 VarDeclaration
*vd
= s
->isVarDeclaration();
1030 TupleDeclaration
*td
= vd
->toAlias()->isTupleDeclaration();
1033 for (size_t i
= 0; i
< td
->objects
->dim
; i
++)
1034 { DsymbolExp
*se
= (DsymbolExp
*)td
->objects
->data
[i
];
1035 assert(se
->op
== TOKdsymbol
);
1036 scanVar(se
->s
, iss
);
1041 // Scan initializer (vd->init)
1044 ExpInitializer
*ie
= vd
->init
->isExpInitializer();
1048 ie
->exp
= ie
->exp
->inlineScan(iss
);
1055 Expression
*DeclarationExp::inlineScan(InlineScanState
*iss
)
1057 //printf("DeclarationExp::inlineScan()\n");
1058 scanVar(declaration
, iss
);
1062 Expression
*UnaExp::inlineScan(InlineScanState
*iss
)
1064 e1
= e1
->inlineScan(iss
);
1068 Expression
*AssertExp::inlineScan(InlineScanState
*iss
)
1070 e1
= e1
->inlineScan(iss
);
1072 msg
= msg
->inlineScan(iss
);
1076 Expression
*BinExp::inlineScan(InlineScanState
*iss
)
1078 e1
= e1
->inlineScan(iss
);
1079 e2
= e2
->inlineScan(iss
);
1084 Expression
*CallExp::inlineScan(InlineScanState
*iss
)
1085 { Expression
*e
= this;
1087 //printf("CallExp::inlineScan()\n");
1088 e1
= e1
->inlineScan(iss
);
1089 arrayInlineScan(iss
, arguments
);
1091 if (e1
->op
== TOKvar
)
1093 VarExp
*ve
= (VarExp
*)e1
;
1094 FuncDeclaration
*fd
= ve
->var
->isFuncDeclaration();
1096 if (fd
&& fd
!= iss
->fd
&& fd
->canInline(0))
1098 e
= fd
->doInline(iss
, NULL
, arguments
);
1101 else if (e1
->op
== TOKdotvar
)
1103 DotVarExp
*dve
= (DotVarExp
*)e1
;
1104 FuncDeclaration
*fd
= dve
->var
->isFuncDeclaration();
1106 if (fd
&& fd
!= iss
->fd
&& fd
->canInline(1))
1108 if (dve
->e1
->op
== TOKcall
&&
1109 dve
->e1
->type
->toBasetype()->ty
== Tstruct
)
1111 /* To create ethis, we'll need to take the address
1112 * of dve->e1, but this won't work if dve->e1 is
1118 e
= fd
->doInline(iss
, dve
->e1
, arguments
);
1126 Expression
*SliceExp::inlineScan(InlineScanState
*iss
)
1128 e1
= e1
->inlineScan(iss
);
1130 lwr
= lwr
->inlineScan(iss
);
1132 upr
= upr
->inlineScan(iss
);
1137 Expression
*TupleExp::inlineScan(InlineScanState
*iss
)
1138 { Expression
*e
= this;
1140 //printf("TupleExp::inlineScan()\n");
1141 arrayInlineScan(iss
, exps
);
1147 Expression
*ArrayLiteralExp::inlineScan(InlineScanState
*iss
)
1148 { Expression
*e
= this;
1150 //printf("ArrayLiteralExp::inlineScan()\n");
1151 arrayInlineScan(iss
, elements
);
1157 Expression
*AssocArrayLiteralExp::inlineScan(InlineScanState
*iss
)
1158 { Expression
*e
= this;
1160 //printf("AssocArrayLiteralExp::inlineScan()\n");
1161 arrayInlineScan(iss
, keys
);
1162 arrayInlineScan(iss
, values
);
1168 Expression
*StructLiteralExp::inlineScan(InlineScanState
*iss
)
1169 { Expression
*e
= this;
1171 //printf("StructLiteralExp::inlineScan()\n");
1172 arrayInlineScan(iss
, elements
);
1178 Expression
*ArrayExp::inlineScan(InlineScanState
*iss
)
1179 { Expression
*e
= this;
1181 //printf("ArrayExp::inlineScan()\n");
1182 e1
= e1
->inlineScan(iss
);
1183 arrayInlineScan(iss
, arguments
);
1189 Expression
*CondExp::inlineScan(InlineScanState
*iss
)
1191 econd
= econd
->inlineScan(iss
);
1192 e1
= e1
->inlineScan(iss
);
1193 e2
= e2
->inlineScan(iss
);
1198 /* ========== =============== */
1200 void FuncDeclaration::inlineScan()
1202 InlineScanState iss
;
1205 printf("FuncDeclaration::inlineScan('%s')\n", toChars());
1207 memset(&iss
, 0, sizeof(iss
));
1212 fbody
= fbody
->inlineScan(&iss
);
1217 int FuncDeclaration::canInline(int hasthis
, int hdrscan
)
1219 InlineCostState ics
;
1222 #define CANINLINE_LOG 0
1225 printf("FuncDeclaration::canInline(hasthis = %d, '%s')\n", hasthis
, toChars());
1228 if (needThis() && !hasthis
)
1231 if (inlineNest
|| (!semanticRun
&& !hdrscan
))
1234 printf("\t1: no, inlineNest = %d, semanticRun = %d\n", inlineNest
, semanticRun
);
1239 switch (inlineStatus
)
1249 printf("\t2: no\n");
1253 case ILSuninitialized
:
1261 { assert(type
->ty
== Tfunction
);
1262 TypeFunction
*tf
= (TypeFunction
*)(type
);
1263 if (tf
->varargs
== 1) // no variadic parameter lists
1266 /* Don't inline a function that returns non-void, but has
1267 * no return expression.
1269 if (tf
->next
&& tf
->next
->ty
!= Tvoid
&&
1270 !(hasReturnExp
& 1) &&
1275 { CtorDeclaration
*ctor
= isCtorDeclaration();
1277 if (ctor
&& ctor
->varargs
== 1)
1286 isCtorDeclaration() || // cannot because need to convert:
1292 isImportedSymbol() ||
1294 closureVars
.dim
|| // no nested references to this frame
1296 nestedFrameRef
|| // no nested references to this frame
1298 (isVirtual() && !isFinal())
1304 /* If any parameters are Tsarray's (which are passed by reference)
1305 * or out parameters (also passed by reference), don't do inlining.
1309 for (int i
= 0; i
< parameters
->dim
; i
++)
1311 VarDeclaration
*v
= (VarDeclaration
*)parameters
->data
[i
];
1312 if (v
->isOut() || v
->isRef() || v
->type
->toBasetype()->ty
== Tsarray
)
1317 memset(&ics
, 0, sizeof(ics
));
1318 ics
.hasthis
= hasthis
;
1320 ics
.hdrscan
= hdrscan
;
1321 cost
= fbody
->inlineCost(&ics
);
1323 printf("cost = %d\n", cost
);
1325 if (cost
>= COST_MAX
)
1328 if (!hdrscan
) // Don't scan recursively for header content scan
1332 if (!hdrscan
) // Don't modify inlineStatus for header content scan
1333 inlineStatus
= ILSyes
;
1340 if (!hdrscan
) // Don't modify inlineStatus for header content scan
1341 inlineStatus
= ILSno
;
1348 Expression
*FuncDeclaration::doInline(InlineScanState
*iss
, Expression
*ethis
, Array
*arguments
)
1352 Expression
*e
= NULL
;
1355 printf("FuncDeclaration::doInline('%s')\n", toChars());
1358 memset(&ids
, 0, sizeof(ids
));
1359 ids
.parent
= iss
->fd
;
1364 VarDeclaration
*vthis
;
1368 if (ethis
->type
->ty
!= Tclass
&& ethis
->type
->ty
!= Tpointer
)
1370 ethis
= ethis
->addressOf(NULL
);
1373 ei
= new ExpInitializer(ethis
->loc
, ethis
);
1375 vthis
= new VarDeclaration(ethis
->loc
, ethis
->type
, Id::This
, ei
);
1376 vthis
->storage_class
= STCin
;
1377 vthis
->linkage
= LINKd
;
1378 vthis
->parent
= iss
->fd
;
1380 ve
= new VarExp(vthis
->loc
, vthis
);
1381 ve
->type
= vthis
->type
;
1383 ei
->exp
= new AssignExp(vthis
->loc
, ve
, ethis
);
1384 ei
->exp
->type
= ve
->type
;
1389 // Set up parameters
1392 e
= new DeclarationExp(0, ids
.vthis
);
1393 e
->type
= Type::tvoid
;
1396 if (arguments
&& arguments
->dim
)
1398 assert(parameters
->dim
== arguments
->dim
);
1400 for (int i
= 0; i
< arguments
->dim
; i
++)
1402 VarDeclaration
*vfrom
= (VarDeclaration
*)parameters
->data
[i
];
1403 VarDeclaration
*vto
;
1404 Expression
*arg
= (Expression
*)arguments
->data
[i
];
1408 ei
= new ExpInitializer(arg
->loc
, arg
);
1410 vto
= new VarDeclaration(vfrom
->loc
, vfrom
->type
, vfrom
->ident
, ei
);
1411 vto
->storage_class
|= vfrom
->storage_class
& (STCin
| STCout
| STClazy
| STCref
);
1412 vto
->linkage
= vfrom
->linkage
;
1413 vto
->parent
= iss
->fd
;
1414 //printf("vto = '%s', vto->storage_class = x%x\n", vto->toChars(), vto->storage_class);
1415 //printf("vto->parent = '%s'\n", iss->fd->toChars());
1417 ve
= new VarExp(vto
->loc
, vto
);
1418 //ve->type = vto->type;
1419 ve
->type
= arg
->type
;
1421 ei
->exp
= new AssignExp(vto
->loc
, ve
, arg
);
1422 ei
->exp
->type
= ve
->type
;
1423 //ve->type->print();
1424 //arg->type->print();
1427 ids
.from
.push(vfrom
);
1430 de
= new DeclarationExp(0, vto
);
1431 de
->type
= Type::tvoid
;
1433 e
= Expression::combine(e
, de
);
1438 Expression
*eb
= fbody
->doInline(&ids
);
1440 //eb->type->print();
1443 return Expression::combine(e
, eb
);