-/* from codegen.inc */
-extern int dseglen;
-
-/**********************************************************************/
-/* Macros used internally by analyse_stack */
-/**********************************************************************/
-
-#ifdef STATISTICS
-#define COUNT(cnt) cnt++
-#else
-#define COUNT(cnt)
-#endif
-
-/* convenient abbreviations */
-#define CURKIND curstack->varkind
-#define CURTYPE curstack->type
-
-/*--------------------------------------------------*/
-/* SIGNALING ERRORS */
-/*--------------------------------------------------*/
-
-#define TYPEPANIC {panic("Stack type mismatch");}
-
-
-/*--------------------------------------------------*/
-/* STACK UNDERFLOW/OVERFLOW CHECKS */
-/*--------------------------------------------------*/
-
-/* underflow checks */
-
-#define REQUIRE(num) \
- do { \
- if (stackdepth < (num)) { \
- sprintf(msg, "(class: "); \
- utf_sprint(msg + strlen(msg), m->class->name); \
- sprintf(msg + strlen(msg), ", method: "); \
- utf_sprint(msg + strlen(msg), m->name); \
- sprintf(msg + strlen(msg), ", signature: "); \
- utf_sprint(msg + strlen(msg), m->descriptor); \
- sprintf(msg + strlen(msg), ") Unable to pop operand off an empty stack"); \
- *exceptionptr = \
- new_exception_message(string_java_lang_VerifyError, msg); \
- return NULL; \
- } \
- } while(0)
-
-#define REQUIRE_1 REQUIRE(1)
-#define REQUIRE_2 REQUIRE(2)
-#define REQUIRE_3 REQUIRE(3)
-#define REQUIRE_4 REQUIRE(4)
-
-
-/* overflow check */
-/* We allow ACONST instructions inserted as arguments to builtin
- * functions to exceed the maximum stack depth. Maybe we should check
- * against maximum stack depth only at block boundaries?
- */
-
-#define CHECKOVERFLOW \
- do { \
- if (stackdepth > m->maxstack) { \
- if (iptr[0].opc != ICMD_ACONST \
- || iptr[0].op1 == 0) { \
- sprintf(msg, "(class: "); \
- utf_sprint_classname(msg + strlen(msg), m->class->name); \
- sprintf(msg + strlen(msg), ", method: "); \
- utf_sprint(msg + strlen(msg), m->name); \
- sprintf(msg + strlen(msg), ", signature: "); \
- utf_sprint(msg + strlen(msg), m->descriptor); \
- sprintf(msg + strlen(msg), ") Stack size too large"); \
- *exceptionptr = \
- new_exception_message(string_java_lang_VerifyError, msg); \
- return NULL; \
- } \
- } \
- } while(0)
-
-
-/*--------------------------------------------------*/
-/* ALLOCATING STACK SLOTS */
-/*--------------------------------------------------*/
-
-#define NEWSTACK(s,v,n) {new->prev=curstack;new->type=s;new->flags=0; \
- new->varkind=v;new->varnum=n;curstack=new;new++;}
-#define NEWSTACKn(s,n) NEWSTACK(s,UNDEFVAR,n)
-#define NEWSTACK0(s) NEWSTACK(s,UNDEFVAR,0)
-
-/* allocate the input stack for an exception handler */
-#define NEWXSTACK {NEWSTACK(TYPE_ADR,STACKVAR,0);curstack=0;}
-
-
-/*--------------------------------------------------*/
-/* STACK MANIPULATION */
-/*--------------------------------------------------*/
-
-/* resetting to an empty operand stack */
-#define STACKRESET {curstack=0;stackdepth=0;}
-
-/* set the output stack of the current instruction */
-#define SETDST {iptr->dst=curstack;}
-
-/* The following macros do NOT check stackdepth, set stackdepth or iptr->dst */
-#define POP(s) {if(s!=curstack->type){TYPEPANIC;} \
- if(curstack->varkind==UNDEFVAR)curstack->varkind=TEMPVAR;\
- curstack=curstack->prev;}
-#define POPANY {if(curstack->varkind==UNDEFVAR)curstack->varkind=TEMPVAR; \
- curstack=curstack->prev;}
-#define COPY(s,d) {(d)->flags=0;(d)->type=(s)->type;\
- (d)->varkind=(s)->varkind;(d)->varnum=(s)->varnum;}
-
-
-/*--------------------------------------------------*/
-/* STACK OPERATIONS MODELING */
-/*--------------------------------------------------*/
-
-/* The following macros are used to model the stack manipulations of
- * different kinds of instructions.
- *
- * These macros check the input stackdepth and they set the output
- * stackdepth and the output stack of the instruction (iptr->dst).
- *
- * These macros do *not* check for stack overflows!
- */
-
-#define PUSHCONST(s){NEWSTACKn(s,stackdepth);SETDST;stackdepth++;}
-#define LOAD(s,v,n) {NEWSTACK(s,v,n);SETDST;stackdepth++;}
-#define STORE(s) {REQUIRE_1;POP(s);SETDST;stackdepth--;}
-#define OP1_0(s) {REQUIRE_1;POP(s);SETDST;stackdepth--;}
-#define OP1_0ANY {REQUIRE_1;POPANY;SETDST;stackdepth--;}
-#define OP0_1(s) {NEWSTACKn(s,stackdepth);SETDST;stackdepth++;}
-#define OP1_1(s,d) {REQUIRE_1;POP(s);NEWSTACKn(d,stackdepth-1);SETDST;}
-#define OP2_0(s) {REQUIRE_2;POP(s);POP(s);SETDST;stackdepth-=2;}
-#define OPTT2_0(t,b){REQUIRE_2;POP(t);POP(b);SETDST;stackdepth-=2;}
-#define OP2_1(s) {REQUIRE_2;POP(s);POP(s);NEWSTACKn(s,stackdepth-2);SETDST;stackdepth--;}
-#define OP2IAT_1(s) {REQUIRE_2;POP(TYPE_INT);POP(TYPE_ADR);NEWSTACKn(s,stackdepth-2);\
- SETDST;stackdepth--;}
-#define OP2IT_1(s) {REQUIRE_2;POP(TYPE_INT);POP(s);NEWSTACKn(s,stackdepth-2);\
- SETDST;stackdepth--;}
-#define OPTT2_1(s,d){REQUIRE_2;POP(s);POP(s);NEWSTACKn(d,stackdepth-2);SETDST;stackdepth--;}
-#define OP2_2(s) {REQUIRE_2;POP(s);POP(s);NEWSTACKn(s,stackdepth-2);\
- NEWSTACKn(s,stackdepth-1);SETDST;}
-#define OP3TIA_0(s) {REQUIRE_3;POP(s);POP(TYPE_INT);POP(TYPE_ADR);SETDST;stackdepth-=3;}
-#define OP3_0(s) {REQUIRE_3;POP(s);POP(s);POP(s);SETDST;stackdepth-=3;}
-#define POPMANY(i) {REQUIRE(i);stackdepth-=i;while(--i>=0){POPANY;}SETDST;}
-#define DUP {REQUIRE_1;NEWSTACK(CURTYPE,CURKIND,curstack->varnum);SETDST; \
- stackdepth++;}
-#define SWAP {REQUIRE_2;COPY(curstack,new);POPANY;COPY(curstack,new+1);POPANY;\
- new[0].prev=curstack;new[1].prev=new;\
- curstack=new+1;new+=2;SETDST;}
-#define DUP_X1 {REQUIRE_2;COPY(curstack,new);COPY(curstack,new+2);POPANY;\
- COPY(curstack,new+1);POPANY;new[0].prev=curstack;\
- new[1].prev=new;new[2].prev=new+1;\
- curstack=new+2;new+=3;SETDST;stackdepth++;}
-#define DUP2_X1 {REQUIRE_3;COPY(curstack,new+1);COPY(curstack,new+4);POPANY;\
- COPY(curstack,new);COPY(curstack,new+3);POPANY;\
- COPY(curstack,new+2);POPANY;new[0].prev=curstack;\
- new[1].prev=new;new[2].prev=new+1;\
- new[3].prev=new+2;new[4].prev=new+3;\
- curstack=new+4;new+=5;SETDST;stackdepth+=2;}
-#define DUP_X2 {REQUIRE_3;COPY(curstack,new);COPY(curstack,new+3);POPANY;\
- COPY(curstack,new+2);POPANY;COPY(curstack,new+1);POPANY;\
- new[0].prev=curstack;new[1].prev=new;\
- new[2].prev=new+1;new[3].prev=new+2;\
- curstack=new+3;new+=4;SETDST;stackdepth++;}
-#define DUP2_X2 {REQUIRE_4;COPY(curstack,new+1);COPY(curstack,new+5);POPANY;\
- COPY(curstack,new);COPY(curstack,new+4);POPANY;\
- COPY(curstack,new+3);POPANY;COPY(curstack,new+2);POPANY;\
- new[0].prev=curstack;new[1].prev=new;\
- new[2].prev=new+1;new[3].prev=new+2;\
- new[4].prev=new+3;new[5].prev=new+4;\
- curstack=new+5;new+=6;SETDST;stackdepth+=2;}
-
-
-/*--------------------------------------------------*/
-/* MACROS FOR HANDLING BASIC BLOCKS */
-/*--------------------------------------------------*/
-
-/* COPYCURSTACK makes a copy of the current operand stack (curstack)
- * and returns it in the variable copy.
- *
- * This macro is used to propagate the operand stack from one basic
- * block to another. The destination block receives the copy as its
- * input stack.
- */
-#define COPYCURSTACK(copy) {\
- int d;\
- stackptr s;\
- if(curstack){\
- s=curstack;\
- new+=stackdepth;\
- d=stackdepth;\
- copy=new;\
- while(s){\
- copy--;d--;\
- copy->prev=copy-1;\
- copy->type=s->type;\
- copy->flags=0;\
- copy->varkind=STACKVAR;\
- copy->varnum=d;\
- s=s->prev;\
- }\
- copy->prev=NULL;\
- copy=new-1;\
- }\
- else\
- copy=NULL;\
-}
-
-/* BBEND is called at the end of each basic block (after the last
- * instruction of the block has been processed).
- */
-
-#define BBEND(s,i){ \
- i = stackdepth - 1; \
- copy = s; \
- while (copy) { \
- if ((copy->varkind == STACKVAR) && (copy->varnum > i)) \
- copy->varkind = TEMPVAR; \
- else { \
- copy->varkind = STACKVAR; \
- copy->varnum = i;\
- } \
- m->registerdata->interfaces[i][copy->type].type = copy->type; \
- m->registerdata->interfaces[i][copy->type].flags |= copy->flags; \
- i--; copy = copy->prev; \
- } \
- i = bptr->indepth - 1; \
- copy = bptr->instack; \
- while (copy) { \
- m->registerdata->interfaces[i][copy->type].type = copy->type; \
- if (copy->varkind == STACKVAR) { \
- if (copy->flags & SAVEDVAR) \
- m->registerdata->interfaces[i][copy->type].flags |= SAVEDVAR; \
- } \
- i--; copy = copy->prev; \
- } \
-}
-
-
-/* MARKREACHED marks the destination block <b> as reached. If this
- * block has been reached before we check if stack depth and types
- * match. Otherwise the destination block receives a copy of the
- * current stack as its input stack.
- *
- * b...destination block
- * c...current stack
- */
-#define MARKREACHED(b,c) { \
- if(b->flags<0) \
- {COPYCURSTACK(c);b->flags=0;b->instack=c;b->indepth=stackdepth;} \
- else {stackptr s=curstack;stackptr t=b->instack; \
- if(b->indepth!=stackdepth) \
- {show_icmd_method(m);panic("Stack depth mismatch");} \
- while(s){if (s->type!=t->type) \
- TYPEPANIC \
- s=s->prev;t=t->prev; \
- } \
- } \
-}
-
-