1 /* vm/jit/stack.h - stack analysis header
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
8 This file is part of CACAO.
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.
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.
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
25 Contact: cacao@cacaojvm.org
27 Authors: Christian Thalinger
29 Changes: Christian Ullrich
31 $Id: stack.h 4482 2006-02-07 23:18:23Z edwin $
43 #include "vm/exceptions.h"
44 #include "vm/global.h"
45 #include "vm/jit/jit.h"
46 #include "vm/jit/reg.h"
49 /* macros used internally by analyse_stack ************************************/
51 #if defined(ENABLE_LSRA)
52 # define INC_LIFETIMES(a) { m->maxlifetimes += (a); }
54 # define INC_LIFETIMES(a)
57 /* convenient abbreviations */
58 #define CURKIND curstack->varkind
59 #define CURTYPE curstack->type
62 /*--------------------------------------------------*/
63 /* SIGNALING ERRORS */
64 /*--------------------------------------------------*/
66 #define TYPE_VERIFYERROR(t) \
68 exceptions_throw_verifyerror_for_stack(m,t); \
73 /*--------------------------------------------------*/
74 /* STACK UNDERFLOW/OVERFLOW CHECKS */
75 /*--------------------------------------------------*/
77 /* underflow checks */
79 #define REQUIRE(num) \
81 if (stackdepth < (num)) { \
83 new_verifyerror(m, "Unable to pop operand off an empty stack"); \
88 #define REQUIRE_1 REQUIRE(1)
89 #define REQUIRE_2 REQUIRE(2)
90 #define REQUIRE_3 REQUIRE(3)
91 #define REQUIRE_4 REQUIRE(4)
95 /* We allow ACONST instructions inserted as arguments to builtin
96 * functions to exceed the maximum stack depth. Maybe we should check
97 * against maximum stack depth only at block boundaries?
100 #define CHECKOVERFLOW \
102 if (stackdepth > m->maxstack) { \
103 if (iptr[0].opc != ICMD_ACONST || iptr[0].op1 == 0) { \
104 *exceptionptr = new_verifyerror(m, "Stack size too large"); \
111 /*--------------------------------------------------*/
112 /* ALLOCATING STACK SLOTS */
113 /*--------------------------------------------------*/
115 #define NEWSTACK_(s,v,n) \
117 new->prev = curstack; \
120 new->varkind = (v); \
127 /* Initialize regoff, so -sia can show regnames even before reg.inc */
128 /* regs[rd->intregargnum has to be set for this */
129 /* new->regoff = (IS_FLT_DBL_TYPE(s))?-1:rd->intreg_argnum; }*/
131 #define NEWSTACK(s,v,n) { NEWSTACK_(s,v,n); INC_LIFETIMES(1); }
133 #define NEWSTACKn(s,n) NEWSTACK(s,UNDEFVAR,n)
134 #define NEWSTACK0(s) NEWSTACK(s,UNDEFVAR,0)
136 /* allocate the input stack for an exception handler */
137 #define NEWXSTACK {NEWSTACK(TYPE_ADR,STACKVAR,0);curstack=0;}
140 /*--------------------------------------------------*/
141 /* STACK MANIPULATION */
142 /*--------------------------------------------------*/
144 /* resetting to an empty operand stack */
153 /* set the output stack of the current instruction */
155 #define SETDST iptr->dst = curstack;
158 /* The following macros do NOT check stackdepth, set stackdepth or iptr->dst */
162 if ((s) != curstack->type) { \
163 TYPE_VERIFYERROR((s)); \
165 if (curstack->varkind == UNDEFVAR) \
166 curstack->varkind = TEMPVAR; \
167 curstack = curstack->prev; \
172 if (curstack->varkind == UNDEFVAR) \
173 curstack->varkind = TEMPVAR; \
174 curstack = curstack->prev; \
177 /*******************************************************
178 Quick Fix to prevent dependence problems of local vars
179 varnum is not set to the according position within the stack
180 like it is done normaly in stack.c
181 -> if this shows to be a problem this can be solved in all the
183 TODO: dependences should be prevented as described in the
185 *******************************************************/
189 (d)->type = (s)->type; \
190 if ((s)->varkind == LOCALVAR) \
191 (s)->varkind = TEMPVAR; \
192 (d)->varkind = (s)->varkind; \
193 (d)->varnum = (s)->varnum; \
197 /*--------------------------------------------------*/
198 /* STACK OPERATIONS MODELING */
199 /*--------------------------------------------------*/
201 /* The following macros are used to model the stack manipulations of
202 * different kinds of instructions.
204 * These macros check the input stackdepth and they set the output
205 * stackdepth and the output stack of the instruction (iptr->dst).
207 * These macros do *not* check for stack overflows!
210 #define PUSHCONST(s){NEWSTACKn(s,stackdepth);SETDST;stackdepth++;}
211 #define LOAD(s,v,n) {NEWSTACK(s,v,n);SETDST;stackdepth++;}
212 #define STORE(s) {REQUIRE_1;POP(s);SETDST;stackdepth--;}
232 NEWSTACKn(s, stackdepth); \
241 NEWSTACKn(d, stackdepth - 1);\
254 #define OPTT2_0(t,b) \
268 NEWSTACKn(s, stackdepth - 2); \
273 #define OP2IAT_1(s) \
278 NEWSTACKn(s, stackdepth - 2); \
288 NEWSTACKn(s, stackdepth - 2); \
293 #define OPTT2_1(s,d) \
298 NEWSTACKn(d, stackdepth - 2); \
308 NEWSTACKn(s, stackdepth - 2); \
309 NEWSTACKn(s, stackdepth - 1); \
313 #define OP3TIA_0(s) \
337 while(--(i) >= 0) { \
343 /* Same dependency quick fix as at COPY */
344 #define DUP {REQUIRE_1; \
345 if (CURKIND == LOCALVAR) \
347 NEWSTACK(CURTYPE,CURKIND,curstack->varnum);SETDST; \
348 stackdepth++; INC_LIFETIMES(1);}
349 #define SWAP {REQUIRE_2;COPY(curstack,new);POPANY;COPY(curstack,new+1);POPANY;\
350 new[0].prev=curstack;new[1].prev=new;\
351 curstack=new+1;new+=2;SETDST;}
352 #define DUP_X1 {REQUIRE_2;COPY(curstack,new);COPY(curstack,new+2);POPANY;\
353 COPY(curstack,new+1);POPANY;new[0].prev=curstack;\
354 new[1].prev=new;new[2].prev=new+1;\
355 curstack=new+2;new+=3;SETDST;stackdepth++; INC_LIFETIMES(3);}
356 #define DUP2_X1 {REQUIRE_3;COPY(curstack,new+1);COPY(curstack,new+4);POPANY;\
357 COPY(curstack,new);COPY(curstack,new+3);POPANY;\
358 COPY(curstack,new+2);POPANY;new[0].prev=curstack;\
359 new[1].prev=new;new[2].prev=new+1;\
360 new[3].prev=new+2;new[4].prev=new+3;\
361 curstack=new+4;new+=5;SETDST;stackdepth+=2; INC_LIFETIMES(5);}
362 #define DUP_X2 {REQUIRE_3;COPY(curstack,new);COPY(curstack,new+3);POPANY;\
363 COPY(curstack,new+2);POPANY;COPY(curstack,new+1);POPANY;\
364 new[0].prev=curstack;new[1].prev=new;\
365 new[2].prev=new+1;new[3].prev=new+2;\
366 curstack=new+3;new+=4;SETDST;stackdepth++; INC_LIFETIMES(4);}
367 #define DUP2_X2 {REQUIRE_4;COPY(curstack,new+1);COPY(curstack,new+5);POPANY;\
368 COPY(curstack,new);COPY(curstack,new+4);POPANY;\
369 COPY(curstack,new+3);POPANY;COPY(curstack,new+2);POPANY;\
370 new[0].prev=curstack;new[1].prev=new;\
371 new[2].prev=new+1;new[3].prev=new+2;\
372 new[4].prev=new+3;new[5].prev=new+4;\
373 curstack=new+5;new+=6;SETDST;stackdepth+=2; INC_LIFETIMES(6);}
376 /*--------------------------------------------------*/
377 /* MACROS FOR HANDLING BASIC BLOCKS */
378 /*--------------------------------------------------*/
380 /* COPYCURSTACK makes a copy of the current operand stack (curstack)
381 * and returns it in the variable copy.
383 * This macro is used to propagate the operand stack from one basic
384 * block to another. The destination block receives the copy as its
387 #define COPYCURSTACK(copy) {\
400 copy->varkind=STACKVAR;\
411 /* BBEND is called at the end of each basic block (after the last
412 * instruction of the block has been processed).
416 #if defined(ENABLE_INTRP)
417 #define IF_NO_INTRP(x) if (!opt_intrp) { x }
419 #define IF_NO_INTRP(x) { x }
422 #define BBEND(s,i) { \
423 (i) = stackdepth - 1; \
426 if ((copy->varkind == STACKVAR) && (copy->varnum > (i))) \
427 copy->varkind = TEMPVAR; \
429 copy->varkind = STACKVAR; \
432 IF_NO_INTRP(rd->interfaces[(i)][copy->type].type = copy->type; \
433 rd->interfaces[(i)][copy->type].flags |= copy->flags;) \
434 (i)--; copy = copy->prev; \
436 (i) = bptr->indepth - 1; \
437 copy = bptr->instack; \
440 rd->interfaces[(i)][copy->type].type = copy->type; \
441 if (copy->varkind == STACKVAR) { \
442 if (copy->flags & SAVEDVAR) \
443 rd->interfaces[(i)][copy->type].flags |= SAVEDVAR; \
446 (i)--; copy = copy->prev; \
451 /* MARKREACHED marks the destination block <b> as reached. If this
452 * block has been reached before we check if stack depth and types
453 * match. Otherwise the destination block receives a copy of the
454 * current stack as its input stack.
456 * b...destination block
460 #define MARKREACHED(b,c) \
462 if ((b)->flags < BBREACHED) { \
464 (b)->flags = BBREACHED; \
465 (b)->instack = (c); \
466 (b)->indepth = stackdepth; \
468 stackptr s = curstack; \
469 stackptr t = (b)->instack; \
470 if ((b)->indepth != stackdepth) { \
471 *exceptionptr = new_verifyerror(m,"Stack depth mismatch"); \
475 if (s->type != t->type) \
476 TYPE_VERIFYERROR(t->type); \
484 /* function prototypes ********************************************************/
486 bool stack_init(void);
488 methodinfo *analyse_stack(methodinfo *m, codegendata *cd, registerdata *rd);
490 void icmd_print_stack(codegendata *cd, stackptr s);
491 void show_icmd_method(methodinfo *m, codegendata *cd, registerdata *rd);
492 void show_icmd_block(methodinfo *m, codegendata *cd, basicblock *bptr);
493 void show_icmd(instruction *iptr, bool deadcode);
495 /* machine dependent return value handling function */
496 void md_return_alloc(methodinfo *m, registerdata *rd, s4 return_type,
499 #endif /* _STACK_H */
503 * These are local overrides for various environment variables in Emacs.
504 * Please do not remove this and leave it at the end of the file, where
505 * Emacs will automagically detect them.
506 * ---------------------------------------------------------------------
509 * indent-tabs-mode: t
513 * vim:noexpandtab:sw=4:ts=4: