1 /* vm/jit/stack.h - stack analysis header
3 Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4 R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5 C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6 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., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Christian Thalinger
29 Changes: Christian Ullrich
31 $Id: stack.h 3994 2005-12-22 14:00:06Z twisti $
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) \
83 type = "object/array"; \
86 *exceptionptr = new_verifyerror(m, \
87 "Expecting to find %s on stack", \
93 /*--------------------------------------------------*/
94 /* STACK UNDERFLOW/OVERFLOW CHECKS */
95 /*--------------------------------------------------*/
97 /* underflow checks */
99 #define REQUIRE(num) \
101 if (stackdepth < (num)) { \
103 new_verifyerror(m, "Unable to pop operand off an empty stack"); \
108 #define REQUIRE_1 REQUIRE(1)
109 #define REQUIRE_2 REQUIRE(2)
110 #define REQUIRE_3 REQUIRE(3)
111 #define REQUIRE_4 REQUIRE(4)
115 /* We allow ACONST instructions inserted as arguments to builtin
116 * functions to exceed the maximum stack depth. Maybe we should check
117 * against maximum stack depth only at block boundaries?
120 #define CHECKOVERFLOW \
122 if (stackdepth > m->maxstack) { \
123 if (iptr[0].opc != ICMD_ACONST || iptr[0].op1 == 0) { \
124 *exceptionptr = new_verifyerror(m, "Stack size too large"); \
131 /*--------------------------------------------------*/
132 /* ALLOCATING STACK SLOTS */
133 /*--------------------------------------------------*/
135 #define NEWSTACK_(s,v,n) \
137 new->prev = curstack; \
140 new->varkind = (v); \
147 /* Initialize regoff, so -sia can show regnames even before reg.inc */
148 /* regs[rd->intregargnum has to be set for this */
149 /* new->regoff = (IS_FLT_DBL_TYPE(s))?-1:rd->intreg_argnum; }*/
151 #define NEWSTACK(s,v,n) { NEWSTACK_(s,v,n); INC_LIFETIMES(1); }
153 #define NEWSTACKn(s,n) NEWSTACK(s,UNDEFVAR,n)
154 #define NEWSTACK0(s) NEWSTACK(s,UNDEFVAR,0)
156 /* allocate the input stack for an exception handler */
157 #define NEWXSTACK {NEWSTACK(TYPE_ADR,STACKVAR,0);curstack=0;}
160 /*--------------------------------------------------*/
161 /* STACK MANIPULATION */
162 /*--------------------------------------------------*/
164 /* resetting to an empty operand stack */
173 /* set the output stack of the current instruction */
175 #define SETDST iptr->dst = curstack;
178 /* The following macros do NOT check stackdepth, set stackdepth or iptr->dst */
182 if ((s) != curstack->type) { \
183 TYPE_VERIFYERROR((s)); \
185 if (curstack->varkind == UNDEFVAR) \
186 curstack->varkind = TEMPVAR; \
187 curstack = curstack->prev; \
192 if (curstack->varkind == UNDEFVAR) \
193 curstack->varkind = TEMPVAR; \
194 curstack = curstack->prev; \
197 /*******************************************************
198 Quick Fix to prevent dependence problems of local vars
199 varnum is not set to the according position within the stack
200 like it is done normaly in stack.c
201 -> if this shows to be a problem this can be solved in all the
203 TODO: dependences should be prevented as described in the
205 *******************************************************/
209 (d)->type = (s)->type; \
210 if ((s)->varkind == LOCALVAR) \
211 (s)->varkind = TEMPVAR; \
212 (d)->varkind = (s)->varkind; \
213 (d)->varnum = (s)->varnum; \
217 /*--------------------------------------------------*/
218 /* STACK OPERATIONS MODELING */
219 /*--------------------------------------------------*/
221 /* The following macros are used to model the stack manipulations of
222 * different kinds of instructions.
224 * These macros check the input stackdepth and they set the output
225 * stackdepth and the output stack of the instruction (iptr->dst).
227 * These macros do *not* check for stack overflows!
230 #define PUSHCONST(s){NEWSTACKn(s,stackdepth);SETDST;stackdepth++;}
231 #define LOAD(s,v,n) {NEWSTACK(s,v,n);SETDST;stackdepth++;}
232 #define STORE(s) {REQUIRE_1;POP(s);SETDST;stackdepth--;}
252 NEWSTACKn(s, stackdepth); \
261 NEWSTACKn(d, stackdepth - 1);\
274 #define OPTT2_0(t,b) \
288 NEWSTACKn(s, stackdepth - 2); \
293 #define OP2IAT_1(s) \
298 NEWSTACKn(s, stackdepth - 2); \
308 NEWSTACKn(s, stackdepth - 2); \
313 #define OPTT2_1(s,d) \
318 NEWSTACKn(d, stackdepth - 2); \
328 NEWSTACKn(s, stackdepth - 2); \
329 NEWSTACKn(s, stackdepth - 1); \
333 #define OP3TIA_0(s) \
357 while(--(i) >= 0) { \
363 /* Same dependency quick fix as at COPY */
364 #define DUP {REQUIRE_1; \
365 if (CURKIND == LOCALVAR) \
367 NEWSTACK(CURTYPE,CURKIND,curstack->varnum);SETDST; \
368 stackdepth++; INC_LIFETIMES(1);}
369 #define SWAP {REQUIRE_2;COPY(curstack,new);POPANY;COPY(curstack,new+1);POPANY;\
370 new[0].prev=curstack;new[1].prev=new;\
371 curstack=new+1;new+=2;SETDST;}
372 #define DUP_X1 {REQUIRE_2;COPY(curstack,new);COPY(curstack,new+2);POPANY;\
373 COPY(curstack,new+1);POPANY;new[0].prev=curstack;\
374 new[1].prev=new;new[2].prev=new+1;\
375 curstack=new+2;new+=3;SETDST;stackdepth++; INC_LIFETIMES(3);}
376 #define DUP2_X1 {REQUIRE_3;COPY(curstack,new+1);COPY(curstack,new+4);POPANY;\
377 COPY(curstack,new);COPY(curstack,new+3);POPANY;\
378 COPY(curstack,new+2);POPANY;new[0].prev=curstack;\
379 new[1].prev=new;new[2].prev=new+1;\
380 new[3].prev=new+2;new[4].prev=new+3;\
381 curstack=new+4;new+=5;SETDST;stackdepth+=2; INC_LIFETIMES(5);}
382 #define DUP_X2 {REQUIRE_3;COPY(curstack,new);COPY(curstack,new+3);POPANY;\
383 COPY(curstack,new+2);POPANY;COPY(curstack,new+1);POPANY;\
384 new[0].prev=curstack;new[1].prev=new;\
385 new[2].prev=new+1;new[3].prev=new+2;\
386 curstack=new+3;new+=4;SETDST;stackdepth++; INC_LIFETIMES(4);}
387 #define DUP2_X2 {REQUIRE_4;COPY(curstack,new+1);COPY(curstack,new+5);POPANY;\
388 COPY(curstack,new);COPY(curstack,new+4);POPANY;\
389 COPY(curstack,new+3);POPANY;COPY(curstack,new+2);POPANY;\
390 new[0].prev=curstack;new[1].prev=new;\
391 new[2].prev=new+1;new[3].prev=new+2;\
392 new[4].prev=new+3;new[5].prev=new+4;\
393 curstack=new+5;new+=6;SETDST;stackdepth+=2; INC_LIFETIMES(6);}
396 /*--------------------------------------------------*/
397 /* MACROS FOR HANDLING BASIC BLOCKS */
398 /*--------------------------------------------------*/
400 /* COPYCURSTACK makes a copy of the current operand stack (curstack)
401 * and returns it in the variable copy.
403 * This macro is used to propagate the operand stack from one basic
404 * block to another. The destination block receives the copy as its
407 #define COPYCURSTACK(copy) {\
420 copy->varkind=STACKVAR;\
431 /* BBEND is called at the end of each basic block (after the last
432 * instruction of the block has been processed).
436 #if defined(ENABLE_INTRP)
437 #define IF_NO_INTRP(x) if (!opt_intrp) { x }
439 #define IF_NO_INTRP(x) { x }
442 #define BBEND(s,i) { \
443 (i) = stackdepth - 1; \
446 if ((copy->varkind == STACKVAR) && (copy->varnum > (i))) \
447 copy->varkind = TEMPVAR; \
449 copy->varkind = STACKVAR; \
452 IF_NO_INTRP(rd->interfaces[(i)][copy->type].type = copy->type; \
453 rd->interfaces[(i)][copy->type].flags |= copy->flags;) \
454 (i)--; copy = copy->prev; \
456 (i) = bptr->indepth - 1; \
457 copy = bptr->instack; \
460 rd->interfaces[(i)][copy->type].type = copy->type; \
461 if (copy->varkind == STACKVAR) { \
462 if (copy->flags & SAVEDVAR) \
463 rd->interfaces[(i)][copy->type].flags |= SAVEDVAR; \
466 (i)--; copy = copy->prev; \
471 /* MARKREACHED marks the destination block <b> as reached. If this
472 * block has been reached before we check if stack depth and types
473 * match. Otherwise the destination block receives a copy of the
474 * current stack as its input stack.
476 * b...destination block
480 #define MARKREACHED(b,c) \
482 if ((b)->flags < 0) { \
485 (b)->instack = (c); \
486 (b)->indepth = stackdepth; \
488 stackptr s = curstack; \
489 stackptr t = (b)->instack; \
490 if ((b)->indepth != stackdepth) { \
491 *exceptionptr = new_verifyerror(m,"Stack depth mismatch"); \
495 if (s->type != t->type) \
496 TYPE_VERIFYERROR(t->type); \
504 /* function prototypes ********************************************************/
506 bool stack_init(void);
508 methodinfo *analyse_stack(methodinfo *m, codegendata *cd, registerdata *rd);
510 void icmd_print_stack(codegendata *cd, stackptr s);
511 void show_icmd_method(methodinfo *m, codegendata *cd, registerdata *rd);
512 void show_icmd_block(methodinfo *m, codegendata *cd, basicblock *bptr);
513 void show_icmd(instruction *iptr, bool deadcode);
515 /* machine dependent return value handling function */
516 void md_return_alloc(methodinfo *m, registerdata *rd, s4 return_type,
519 #endif /* _STACK_H */
523 * These are local overrides for various environment variables in Emacs.
524 * Please do not remove this and leave it at the end of the file, where
525 * Emacs will automagically detect them.
526 * ---------------------------------------------------------------------
529 * indent-tabs-mode: t