* src/vm/method.h (vm/jit/code.h): Added.
[cacao.git] / src / vm / jit / stack.h
1 /* vm/jit/stack.h - stack analysis header
2
3    Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    Contact: cacao@cacaojvm.org
26
27    Authors: Christian Thalinger
28
29    Changes: Christian Ullrich
30
31    $Id: stack.h 4699 2006-03-28 14:52:32Z twisti $
32
33 */
34
35
36 #ifndef _STACK_H
37 #define _STACK_H
38
39 #include "config.h"
40
41 #include "vm/types.h"
42
43 #include "vm/exceptions.h"
44 #include "vm/global.h"
45 #include "vm/jit/jit.h"
46 #include "vm/jit/reg.h"
47
48
49 /* macros used internally by analyse_stack ************************************/
50
51 #if defined(ENABLE_LSRA)
52 # define INC_LIFETIMES(a) { m->maxlifetimes += (a); }
53 #else
54 # define INC_LIFETIMES(a)
55 #endif
56
57 /* convenient abbreviations */
58 #define CURKIND    curstack->varkind
59 #define CURTYPE    curstack->type
60
61
62 /*--------------------------------------------------*/
63 /* STACK DEPTH CHECKING                             */
64 /*--------------------------------------------------*/
65
66 #if defined(ENABLE_VERIFIER)
67 #define CHECK_STACK_DEPTH(depthA,depthB) \
68         do { \
69                 if ((depthA) != (depthB)) \
70                         goto throw_stack_depth_error; \
71         } while (0)
72 #else /* !ENABLE_VERIFIER */
73 #define CHECK_STACK_DEPTH(depthA,depthB)
74 #endif /* ENABLE_VERIFIER */
75
76
77 /*--------------------------------------------------*/
78 /* BASIC TYPE CHECKING                              */
79 /*--------------------------------------------------*/
80
81 /* XXX would be nice if we did not have to pass the expected type */
82
83 #if defined(ENABLE_VERIFIER)
84 #define CHECK_BASIC_TYPE(expected,actual) \
85         do { \
86                 if ((actual) != (expected)) { \
87                         expectedtype = (expected); \
88                         goto throw_stack_type_error; \
89                 } \
90         } while (0)
91 #else /* !ENABLE_VERIFIER */
92 #define CHECK_BASIC_TYPE(expected,actual)
93 #endif /* ENABLE_VERIFIER */
94
95 /*--------------------------------------------------*/
96 /* STACK UNDERFLOW/OVERFLOW CHECKS                  */
97 /*--------------------------------------------------*/
98
99 /* underflow checks */
100
101 #if defined(ENABLE_VERIFIER)
102 #define REQUIRE(num) \
103     do { \
104         if (stackdepth < (num)) \
105                         goto throw_stack_underflow; \
106         } while (0)
107 #else /* !ENABLE_VERIFIER */
108 #define REQUIRE(num)
109 #endif /* ENABLE_VERIFIER */
110
111 #define REQUIRE_1     REQUIRE(1)
112 #define REQUIRE_2     REQUIRE(2)
113 #define REQUIRE_3     REQUIRE(3)
114 #define REQUIRE_4     REQUIRE(4)
115
116
117 /* overflow check */
118 /* We allow ACONST instructions inserted as arguments to builtin
119  * functions to exceed the maximum stack depth.  Maybe we should check
120  * against maximum stack depth only at block boundaries?
121  */
122
123 /* XXX we should find a way to remove the opc/op1 check */
124 #if defined(ENABLE_VERIFIER)
125 #define CHECKOVERFLOW \
126         do { \
127                 if (stackdepth > m->maxstack) \
128                         if ((iptr[0].opc != ICMD_ACONST) || (iptr[0].op1 == 0)) \
129                                 goto throw_stack_overflow; \
130         } while(0)
131 #else /* !ENABLE_VERIFIER */
132 #define CHECKOVERFLOW
133 #endif /* ENABLE_VERIFIER */
134
135 /*--------------------------------------------------*/
136 /* ALLOCATING STACK SLOTS                           */
137 /*--------------------------------------------------*/
138
139 #define NEWSTACK_(s,v,n) \
140     do { \
141         new->prev = curstack; \
142         new->type = (s); \
143         new->flags = 0; \
144         new->varkind = (v); \
145         new->varnum = (n); \
146         curstack = new; \
147         new++; \
148     } while (0)
149
150
151 /* Initialize regoff, so -sia can show regnames even before reg.inc */
152 /* regs[rd->intregargnum has to be set for this */
153 /* new->regoff = (IS_FLT_DBL_TYPE(s))?-1:rd->intreg_argnum; }*/
154
155 #define NEWSTACK(s,v,n) { NEWSTACK_(s,v,n); INC_LIFETIMES(1); }
156
157 #define NEWSTACKn(s,n)  NEWSTACK(s,UNDEFVAR,n)
158 #define NEWSTACK0(s)    NEWSTACK(s,UNDEFVAR,0)
159
160 /* allocate the input stack for an exception handler */
161 #define NEWXSTACK   {NEWSTACK(TYPE_ADR,STACKVAR,0);curstack=0;}
162
163
164 /*--------------------------------------------------*/
165 /* STACK MANIPULATION                               */
166 /*--------------------------------------------------*/
167
168 /* resetting to an empty operand stack */
169
170 #define STACKRESET \
171     do { \
172         curstack = 0; \
173         stackdepth = 0; \
174     } while (0)
175
176
177 /* set the output stack of the current instruction */
178
179 #define SETDST    iptr->dst = curstack;
180
181
182 /* The following macros do NOT check stackdepth, set stackdepth or iptr->dst */
183
184 #define POP(s) \
185     do { \
186                 CHECK_BASIC_TYPE((s),curstack->type); \
187         if (curstack->varkind == UNDEFVAR) \
188             curstack->varkind = TEMPVAR; \
189         curstack = curstack->prev; \
190     } while (0)
191
192 #define POPANY \
193     do { \
194         if (curstack->varkind == UNDEFVAR) \
195             curstack->varkind = TEMPVAR; \
196         curstack = curstack->prev; \
197     } while (0)
198
199 /* Do not copy Interface Stackslots over DUPx, Swaps! */
200 #define COPY(s,d) \
201     do { \
202         (d)->flags = 0; \
203         (d)->type = (s)->type; \
204                 if ( (s)->varkind != STACKVAR) {                \
205                         (d)->varkind = (s)->varkind; \
206                         (d)->varnum = (s)->varnum;       \
207                 } else { \
208                         (d)->varkind = TEMPVAR; \
209                         (d)->varnum = 0; \
210                 } \
211     } while (0)
212
213
214 /*--------------------------------------------------*/
215 /* STACK OPERATIONS MODELING                        */
216 /*--------------------------------------------------*/
217
218 /* The following macros are used to model the stack manipulations of
219  * different kinds of instructions.
220  *
221  * These macros check the input stackdepth and they set the output
222  * stackdepth and the output stack of the instruction (iptr->dst).
223  *
224  * These macros do *not* check for stack overflows!
225  */
226
227 #define PUSHCONST(s){NEWSTACKn(s,stackdepth);SETDST;stackdepth++;}
228 #define LOAD(s,v,n) {NEWSTACK(s,v,n);SETDST;stackdepth++;}
229 #define STORE(s)    {REQUIRE_1;POP(s);SETDST;stackdepth--;}
230
231 #define OP1_0(s) \
232     do { \
233         REQUIRE_1; \
234         POP(s); \
235         SETDST; \
236         stackdepth--; \
237     } while (0)
238
239 #define OP1_0ANY \
240     do { \
241         REQUIRE_1; \
242         POPANY; \
243         SETDST; \
244         stackdepth--; \
245     } while (0)
246
247 #define OP0_1(s) \
248     do { \
249         NEWSTACKn(s, stackdepth); \
250         SETDST; \
251         stackdepth++; \
252     } while (0)
253
254 #define OP1_1(s,d) \
255     do { \
256         REQUIRE_1; \
257         POP(s); \
258         NEWSTACKn(d, stackdepth - 1);\
259         SETDST; \
260     } while (0)
261
262 #define OP2_0(s) \
263     do { \
264         REQUIRE_2; \
265         POP(s); \
266         POP(s); \
267         SETDST; \
268         stackdepth -= 2; \
269     } while (0)
270
271 #define OPTT2_0(t,b) \
272     do { \
273         REQUIRE_2; \
274         POP(t); \
275         POP(b); \
276         SETDST; \
277         stackdepth -= 2; \
278     } while (0)
279
280 #define OP2_1(s) \
281     do { \
282         REQUIRE_2; \
283         POP(s); \
284         POP(s); \
285         NEWSTACKn(s, stackdepth - 2); \
286         SETDST; \
287         stackdepth--; \
288     } while (0)
289
290 #define OP2IAT_1(s) \
291     do { \
292         REQUIRE_2; \
293         POP(TYPE_INT); \
294         POP(TYPE_ADR); \
295         NEWSTACKn(s, stackdepth - 2); \
296         SETDST; \
297         stackdepth--; \
298     } while (0)
299
300 #define OP2IT_1(s) \
301     do { \
302         REQUIRE_2; \
303         POP(TYPE_INT); \
304         POP(s); \
305         NEWSTACKn(s, stackdepth - 2); \
306         SETDST; \
307         stackdepth--; \
308     } while (0)
309
310 #define OPTT2_1(s,d) \
311     do { \
312         REQUIRE_2; \
313         POP(s); \
314         POP(s); \
315         NEWSTACKn(d, stackdepth - 2); \
316         SETDST; \
317         stackdepth--; \
318     } while (0)
319
320 #define OP2_2(s) \
321     do { \
322         REQUIRE_2; \
323         POP(s); \
324         POP(s); \
325         NEWSTACKn(s, stackdepth - 2); \
326         NEWSTACKn(s, stackdepth - 1); \
327         SETDST; \
328     } while (0)
329
330 #define OP3TIA_0(s) \
331     do { \
332         REQUIRE_3; \
333         POP(s); \
334         POP(TYPE_INT); \
335         POP(TYPE_ADR); \
336         SETDST; \
337         stackdepth -= 3; \
338     } while (0)
339
340 #define OP3_0(s) \
341     do { \
342         REQUIRE_3; \
343         POP(s); \
344         POP(s); \
345         POP(s); \
346         SETDST; \
347         stackdepth -= 3; \
348     } while (0)
349
350 #define POPMANY(i) \
351     do { \
352         REQUIRE((i)); \
353         stackdepth -= (i); \
354         while(--(i) >= 0) { \
355             POPANY; \
356         } \
357         SETDST; \
358     } while (0)
359
360 /* Do not copy Interface Stackslots over DUP! */
361 #define DUP         {REQUIRE_1; \
362                              if (CURKIND != STACKVAR) { \
363                                                  NEWSTACK(CURTYPE,CURKIND,curstack->varnum); \
364                                          } else { \
365                                                  NEWSTACK(CURTYPE, TEMPVAR, stackdepth); \
366                                          } \
367                                          SETDST; stackdepth++; INC_LIFETIMES(1);}
368 #define SWAP        {REQUIRE_2;COPY(curstack,new);POPANY;COPY(curstack,new+1);POPANY;\
369                     new[0].prev=curstack;new[1].prev=new;\
370                     curstack=new+1;new+=2;SETDST;}
371 #define DUP_X1      {REQUIRE_2;COPY(curstack,new);COPY(curstack,new+2);POPANY;\
372                     COPY(curstack,new+1);POPANY;new[0].prev=curstack;\
373                     new[1].prev=new;new[2].prev=new+1;\
374                     curstack=new+2;new+=3;SETDST;stackdepth++; INC_LIFETIMES(3);}
375 #define DUP2_X1     {REQUIRE_3;COPY(curstack,new+1);COPY(curstack,new+4);POPANY;\
376                     COPY(curstack,new);COPY(curstack,new+3);POPANY;\
377                     COPY(curstack,new+2);POPANY;new[0].prev=curstack;\
378                     new[1].prev=new;new[2].prev=new+1;\
379                     new[3].prev=new+2;new[4].prev=new+3;\
380                     curstack=new+4;new+=5;SETDST;stackdepth+=2; INC_LIFETIMES(5);}
381 #define DUP_X2      {REQUIRE_3;COPY(curstack,new);COPY(curstack,new+3);POPANY;\
382                     COPY(curstack,new+2);POPANY;COPY(curstack,new+1);POPANY;\
383                     new[0].prev=curstack;new[1].prev=new;\
384                     new[2].prev=new+1;new[3].prev=new+2;\
385                     curstack=new+3;new+=4;SETDST;stackdepth++; INC_LIFETIMES(4);}
386 #define DUP2_X2     {REQUIRE_4;COPY(curstack,new+1);COPY(curstack,new+5);POPANY;\
387                     COPY(curstack,new);COPY(curstack,new+4);POPANY;\
388                     COPY(curstack,new+3);POPANY;COPY(curstack,new+2);POPANY;\
389                     new[0].prev=curstack;new[1].prev=new;\
390                     new[2].prev=new+1;new[3].prev=new+2;\
391                     new[4].prev=new+3;new[5].prev=new+4;\
392                     curstack=new+5;new+=6;SETDST;stackdepth+=2; INC_LIFETIMES(6);}
393
394
395 /*--------------------------------------------------*/
396 /* MACROS FOR HANDLING BASIC BLOCKS                 */
397 /*--------------------------------------------------*/
398
399 /* COPYCURSTACK makes a copy of the current operand stack (curstack)
400  * and returns it in the variable copy.
401  *
402  * This macro is used to propagate the operand stack from one basic
403  * block to another. The destination block receives the copy as its
404  * input stack.
405  */
406 #define COPYCURSTACK(copy) {\
407         int d;\
408         stackptr s;\
409         if(curstack){\
410                 s=curstack;\
411                 new+=stackdepth;\
412                 d=stackdepth;\
413                 copy=new;\
414                 while(s){\
415                         copy--;d--;\
416                         copy->prev=copy-1;\
417                         copy->type=s->type;\
418                         copy->flags=0;\
419                         copy->varkind=STACKVAR;\
420                         copy->varnum=d;\
421                         s=s->prev;\
422                         }\
423                 copy->prev=NULL;\
424                 copy=new-1;\
425                 }\
426         else\
427                 copy=NULL;\
428 }
429
430 /* MARKREACHED marks the destination block <b> as reached. If this
431  * block has been reached before we check if stack depth and types
432  * match. Otherwise the destination block receives a copy of the
433  * current stack as its input stack.
434  *
435  * b...destination block
436  * c...current stack
437  */
438
439 #define MARKREACHED(b,c) \
440     do { \
441                 if ((b) <= (bptr)) \
442                         (b)->bitflags |= BBFLAG_REPLACEMENT; \
443             if ((b)->flags < BBREACHED) { \
444                     COPYCURSTACK((c)); \
445             (b)->flags = BBREACHED; \
446             (b)->instack = (c); \
447             (b)->indepth = stackdepth; \
448         } else { \
449             stackptr s = curstack; \
450             stackptr t = (b)->instack; \
451                         CHECK_STACK_DEPTH((b)->indepth, stackdepth); \
452                     while (s) { \
453                                 CHECK_BASIC_TYPE(s->type,t->type); \
454                             s = s->prev; \
455                 t = t->prev; \
456                         } \
457                 } \
458     } while (0)
459
460
461 /* function prototypes ********************************************************/
462
463 bool stack_init(void);
464
465 bool stack_analyse(jitdata *jd);
466
467 #if !defined(NDEBUG)
468 void stack_show_method(jitdata *jd);
469 void stack_show_basicblock(jitdata *jd, basicblock *bptr);
470 void stack_show_icmd(instruction *iptr, bool deadcode);
471 #endif
472
473 /* machine dependent return value handling function */
474 void md_return_alloc(methodinfo *m, registerdata *rd, s4 return_type,
475                                          stackptr stackslot);
476
477 #endif /* _STACK_H */
478
479
480 /*
481  * These are local overrides for various environment variables in Emacs.
482  * Please do not remove this and leave it at the end of the file, where
483  * Emacs will automagically detect them.
484  * ---------------------------------------------------------------------
485  * Local variables:
486  * mode: c
487  * indent-tabs-mode: t
488  * c-basic-offset: 4
489  * tab-width: 4
490  * End:
491  * vim:noexpandtab:sw=4:ts=4:
492  */