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 4483 2006-02-11 21:25:45Z christian $
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 Interface Stackslots (STACKVAR) are not allowed to be copied.
186 ARGVAR are taken out, too.
187 *******************************************************/
191 (d)->type = (s)->type; \
192 (d)->varkind = TEMPVAR; \
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 NEWSTACK(CURTYPE,TEMPVAR,stackdepth-1);SETDST; \
346 stackdepth++; INC_LIFETIMES(1);}
347 #define SWAP {REQUIRE_2;COPY(curstack,new);POPANY;COPY(curstack,new+1);POPANY;\
348 new[0].prev=curstack;new[1].prev=new;\
349 curstack=new+1;new+=2;SETDST;}
350 #define DUP_X1 {REQUIRE_2;COPY(curstack,new);COPY(curstack,new+2);POPANY;\
351 COPY(curstack,new+1);POPANY;new[0].prev=curstack;\
352 new[1].prev=new;new[2].prev=new+1;\
353 curstack=new+2;new+=3;SETDST;stackdepth++; INC_LIFETIMES(3);}
354 #define DUP2_X1 {REQUIRE_3;COPY(curstack,new+1);COPY(curstack,new+4);POPANY;\
355 COPY(curstack,new);COPY(curstack,new+3);POPANY;\
356 COPY(curstack,new+2);POPANY;new[0].prev=curstack;\
357 new[1].prev=new;new[2].prev=new+1;\
358 new[3].prev=new+2;new[4].prev=new+3;\
359 curstack=new+4;new+=5;SETDST;stackdepth+=2; INC_LIFETIMES(5);}
360 #define DUP_X2 {REQUIRE_3;COPY(curstack,new);COPY(curstack,new+3);POPANY;\
361 COPY(curstack,new+2);POPANY;COPY(curstack,new+1);POPANY;\
362 new[0].prev=curstack;new[1].prev=new;\
363 new[2].prev=new+1;new[3].prev=new+2;\
364 curstack=new+3;new+=4;SETDST;stackdepth++; INC_LIFETIMES(4);}
365 #define DUP2_X2 {REQUIRE_4;COPY(curstack,new+1);COPY(curstack,new+5);POPANY;\
366 COPY(curstack,new);COPY(curstack,new+4);POPANY;\
367 COPY(curstack,new+3);POPANY;COPY(curstack,new+2);POPANY;\
368 new[0].prev=curstack;new[1].prev=new;\
369 new[2].prev=new+1;new[3].prev=new+2;\
370 new[4].prev=new+3;new[5].prev=new+4;\
371 curstack=new+5;new+=6;SETDST;stackdepth+=2; INC_LIFETIMES(6);}
374 /*--------------------------------------------------*/
375 /* MACROS FOR HANDLING BASIC BLOCKS */
376 /*--------------------------------------------------*/
378 /* COPYCURSTACK makes a copy of the current operand stack (curstack)
379 * and returns it in the variable copy.
381 * This macro is used to propagate the operand stack from one basic
382 * block to another. The destination block receives the copy as its
385 #define COPYCURSTACK(copy) {\
398 copy->varkind=STACKVAR;\
409 /* BBEND is called at the end of each basic block (after the last
410 * instruction of the block has been processed).
414 #if defined(ENABLE_INTRP)
415 #define IF_NO_INTRP(x) if (!opt_intrp) { x }
417 #define IF_NO_INTRP(x) { x }
420 #define BBEND(s,i) { \
421 (i) = stackdepth - 1; \
424 if ((copy->varkind == STACKVAR) && (copy->varnum > (i))) \
425 copy->varkind = TEMPVAR; \
427 copy->varkind = STACKVAR; \
430 IF_NO_INTRP(rd->interfaces[(i)][copy->type].type = copy->type; \
431 rd->interfaces[(i)][copy->type].flags |= copy->flags;) \
432 (i)--; copy = copy->prev; \
434 (i) = bptr->indepth - 1; \
435 copy = bptr->instack; \
438 rd->interfaces[(i)][copy->type].type = copy->type; \
439 if (copy->varkind == STACKVAR) { \
440 if (copy->flags & SAVEDVAR) \
441 rd->interfaces[(i)][copy->type].flags |= SAVEDVAR; \
444 (i)--; copy = copy->prev; \
449 /* MARKREACHED marks the destination block <b> as reached. If this
450 * block has been reached before we check if stack depth and types
451 * match. Otherwise the destination block receives a copy of the
452 * current stack as its input stack.
454 * b...destination block
458 #define MARKREACHED(b,c) \
460 if ((b)->flags < BBREACHED) { \
462 (b)->flags = BBREACHED; \
463 (b)->instack = (c); \
464 (b)->indepth = stackdepth; \
466 stackptr s = curstack; \
467 stackptr t = (b)->instack; \
468 if ((b)->indepth != stackdepth) { \
469 *exceptionptr = new_verifyerror(m,"Stack depth mismatch"); \
473 if (s->type != t->type) \
474 TYPE_VERIFYERROR(t->type); \
482 /* function prototypes ********************************************************/
484 bool stack_init(void);
486 methodinfo *analyse_stack(methodinfo *m, codegendata *cd, registerdata *rd);
488 void icmd_print_stack(codegendata *cd, stackptr s);
489 void show_icmd_method(methodinfo *m, codegendata *cd, registerdata *rd);
490 void show_icmd_block(methodinfo *m, codegendata *cd, basicblock *bptr);
491 void show_icmd(instruction *iptr, bool deadcode);
493 /* machine dependent return value handling function */
494 void md_return_alloc(methodinfo *m, registerdata *rd, s4 return_type,
497 #endif /* _STACK_H */
501 * These are local overrides for various environment variables in Emacs.
502 * Please do not remove this and leave it at the end of the file, where
503 * Emacs will automagically detect them.
504 * ---------------------------------------------------------------------
507 * indent-tabs-mode: t
511 * vim:noexpandtab:sw=4:ts=4: