-#include "toolbox/loging.h"
-#include "toolbox/memory.h"
-
-
-/* from codegen.inc */
-extern int dseglen;
-
-
-#ifdef STATISTICS
-#define COUNT(cnt) cnt++
-#else
-#define COUNT(cnt)
-#endif
-
-#define STACKRESET {curstack=0;stackdepth=0;}
-
-#define TYPEPANIC {show_icmd_method();panic("Stack type mismatch");}
-#define CURKIND curstack->varkind
-#define CURTYPE curstack->type
-
-#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)
-#define NEWXSTACK {NEWSTACK(TYPE_ADR,STACKVAR,0);curstack=0;}
-
-#define SETDST {iptr->dst=curstack;}
-#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;}
-
-#define PUSHCONST(s){NEWSTACKn(s,stackdepth);SETDST;stackdepth++;}
-#define LOAD(s,v,n) {NEWSTACK(s,v,n);SETDST;stackdepth++;}
-#define STORE(s) {POP(s);SETDST;stackdepth--;}
-#define OP1_0(s) {POP(s);SETDST;stackdepth--;}
-#define OP1_0ANY {POPANY;SETDST;stackdepth--;}
-#define OP0_1(s) {NEWSTACKn(s,stackdepth);SETDST;stackdepth++;}
-#define OP1_1(s,d) {POP(s);NEWSTACKn(d,stackdepth-1);SETDST;}
-#define OP2_0(s) {POP(s);POP(s);SETDST;stackdepth-=2;}
-#define OPTT2_0(t,b){POP(t);POP(b);SETDST;stackdepth-=2;}
-#define OP2_1(s) {POP(s);POP(s);NEWSTACKn(s,stackdepth-2);SETDST;stackdepth--;}
-#define OP2IAT_1(s) {POP(TYPE_INT);POP(TYPE_ADR);NEWSTACKn(s,stackdepth-2);\
- SETDST;stackdepth--;}
-#define OP2IT_1(s) {POP(TYPE_INT);POP(s);NEWSTACKn(s,stackdepth-2);\
- SETDST;stackdepth--;}
-#define OPTT2_1(s,d){POP(s);POP(s);NEWSTACKn(d,stackdepth-2);SETDST;stackdepth--;}
-#define OP2_2(s) {POP(s);POP(s);NEWSTACKn(s,stackdepth-2);\
- NEWSTACKn(s,stackdepth-1);SETDST;}
-#define OP3TIA_0(s) {POP(s);POP(TYPE_INT);POP(TYPE_ADR);SETDST;stackdepth-=3;}
-#define OP3_0(s) {POP(s);POP(s);POP(s);SETDST;stackdepth-=3;}
-#define POPMANY(i) {stackdepth-=i;while(--i>=0){POPANY;}SETDST;}
-#define DUP {NEWSTACK(CURTYPE,CURKIND,curstack->varnum);SETDST;\
- stackdepth++;}
-#define SWAP {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 {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 {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 {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 {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;}
-
-#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;\
-}
-
-
-#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;\
- }\
- interfaces[i][copy->type].type = copy->type;\
- interfaces[i][copy->type].flags |= copy->flags;\
- i--;copy=copy->prev;\
- }\
- i=bptr->indepth-1;\
- copy=bptr->instack;\
- while(copy){\
- interfaces[i][copy->type].type = copy->type;\
- if(copy->varkind==STACKVAR){\
- if (copy->flags & SAVEDVAR)\
- interfaces[i][copy->type].flags |= SAVEDVAR;\
- }\
- i--;copy=copy->prev;\
- }\
-}
-
-
-#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();panic("Stack depth mismatch");}\
- while(s){if (s->type!=t->type)\
- TYPEPANIC\
- s=s->prev;t=t->prev;\
- }\
- }\
-}
-
+#include "mm/memory.h"
+#include "native/native.h"
+#include "toolbox/logging.h"
+#include "vm/global.h"
+#include "vm/builtin.h"
+#include "vm/options.h"
+#include "vm/statistics.h"
+#include "vm/tables.h"
+#include "vm/jit/codegen.inc.h"
+#include "vm/jit/jit.h"
+#include "vm/jit/reg.h"
+#include "vm/jit/stack.h"
+
+
+/**********************************************************************/
+/* analyse_stack */
+/**********************************************************************/
+
+/* analyse_stack uses the intermediate code created by parse.c to
+ * build a model of the JVM operand stack for the current method.
+ *
+ * The following checks are performed:
+ * - check for operand stack underflow (before each instruction)
+ * - check for operand stack overflow (after[1] each instruction)
+ * - check for matching stack depth at merging points
+ * - check for matching basic types[2] at merging points
+ * - check basic types for instruction input (except for BUILTIN*
+ * opcodes, INVOKE* opcodes and MULTIANEWARRAY)
+ *
+ * [1]) Checking this after the instruction should be ok. parse.c
+ * counts the number of required stack slots in such a way that it is
+ * only vital that we don't exceed `maxstack` at basic block
+ * boundaries.
+ *
+ * [2]) 'basic types' means the distinction between INT, LONG, FLOAT,
+ * DOUBLE and ADDRESS types. Subtypes of INT and different ADDRESS
+ * types are not discerned.
+ */