+static bool
+typestate_merge(stackptr deststack,typevector *destloc,
+ stackptr ystack,typevector *yloc,
+ int locsize,bool jsrencountered)
+{
+ typevector *dvec,*yvec;
+ int kd,ky;
+ bool changed = false;
+
+ LOG("merge:");
+ LOGSTR("dstack: "); DOLOG(typestack_print(get_logfile(),deststack)); LOGNL;
+ LOGSTR("ystack: "); DOLOG(typestack_print(get_logfile(),ystack)); LOGNL;
+ LOGSTR("dloc : "); DOLOG(typevectorset_print(get_logfile(),destloc,locsize)); LOGNL;
+ LOGSTR("yloc : "); DOLOG(typevectorset_print(get_logfile(),yloc,locsize)); LOGNL;
+ LOGFLUSH;
+
+ /* The stack is always merged. If there are returnAddresses on
+ * the stack they are ignored in this step. */
+
+ changed |= typestack_merge(deststack,ystack);
+
+ if (!jsrencountered)
+ return typevector_merge(destloc,yloc,locsize);
+
+ for (yvec=yloc; yvec; yvec=yvec->alt) {
+ ky = yvec->k;
+
+ /* Check if the typestates (deststack,destloc) will be
+ * separable when (ystack,yvec) is added. */
+
+ if (!typestack_separable_with(deststack,ystack,ky)
+ && !typevectorset_separable_with(destloc,yvec,locsize))
+ {
+ /* No, the resulting set won't be separable, thus we
+ * may merge all states in (deststack,destloc) and
+ * (ystack,yvec). */
+
+ typestack_collapse(deststack);
+ typevectorset_collapse(destloc,locsize);
+ typevector_merge(destloc,yvec,locsize);
+ }
+ else {
+ /* Yes, the resulting set will be separable. Thus we check
+ * if we may merge (ystack,yvec) with a single state in
+ * (deststack,destloc). */
+
+ for (dvec=destloc,kd=0; dvec; dvec=dvec->alt, kd++) {
+ if (!typestack_separable_from(ystack,ky,deststack,kd)
+ && !typevector_separable_from(yvec,dvec,locsize))
+ {
+ /* The typestate (ystack,yvec) is not separable from
+ * (deststack,dvec) by any returnAddress. Thus we may
+ * merge the states. */
+
+ changed |= typevector_merge(dvec,yvec,locsize);
+
+ goto merged;
+ }
+ }
+
+ /* The typestate (ystack,yvec) is separable from all typestates
+ * (deststack,destloc). Thus we must add this state to the
+ * result set. */
+
+ typestack_add(deststack,ystack,ky);
+ typevectorset_add(destloc,yvec,locsize);
+ changed = true;
+ }
+
+ merged:
+ ;
+ }
+
+ LOG("result:");
+ LOGSTR("dstack: "); DOLOG(typestack_print(get_logfile(),deststack)); LOGNL;
+ LOGSTR("dloc : "); DOLOG(typevectorset_print(get_logfile(),destloc,locsize)); LOGNL;
+ LOGFLUSH;
+
+ return changed;
+}
+
+
+static bool
+typestate_reach(codegendata *cd, registerdata *rd,void *localbuf,
+ basicblock *current,
+ basicblock *destblock,
+ stackptr ystack,typevector *yloc,
+ int locsize,bool jsrencountered)
+{
+ typevector *destloc;
+ int destidx;
+ bool changed = false;
+
+ LOG1("reaching block L%03d",destblock->debug_nr);
+ TYPECHECK_COUNT(stat_reached);
+
+ destidx = destblock - cd->method->basicblocks;
+ destloc = MGET_TYPEVECTOR(localbuf,destidx,locsize);
+
+ /* When branching backwards we have to check for uninitialized objects */
+
+ if (destblock <= current) {
+ stackptr sp;
+ int i;
+#if defined(__GNUC__)
+#warning FIXME FOR INLINING
+#endif
+ if (!useinlining) {
+ TYPECHECK_COUNT(stat_backwards);
+ LOG("BACKWARDS!");
+ for (sp = ystack; sp; sp=sp->prev)
+ if (sp->type == TYPE_ADR &&
+ TYPEINFO_IS_NEWOBJECT(sp->typeinfo)) {
+ show_icmd_method(cd->method,cd,rd);
+ printf("current: %ld, dest: %ld\n",current->debug_nr,destblock->debug_nr);
+ panic("Branching backwards with uninitialized object on stack");
+ }
+
+ for (i=0; i<locsize; ++i)
+ if (yloc->td[i].type == TYPE_ADR &&
+ TYPEINFO_IS_NEWOBJECT(yloc->td[i].info))
+ panic("Branching backwards with uninitialized object in local variable");
+ }
+ }
+
+ if (destblock->flags == BBTYPECHECK_UNDEF) {
+ /* The destblock has never been reached before */
+
+ TYPECHECK_COUNT(stat_copied);
+ LOG1("block (index %04d) reached first time",destidx);
+
+ typestack_copy(destblock->instack,ystack,yloc);
+ COPY_TYPEVECTORSET(yloc,destloc,locsize);
+ changed = true;
+ }
+ else {
+ /* The destblock has already been reached before */
+
+ TYPECHECK_COUNT(stat_merged);
+ LOG1("block (index %04d) reached before",destidx);
+
+ changed = typestate_merge(destblock->instack,destloc,
+ ystack,yloc,locsize,
+ jsrencountered);
+ TYPECHECK_COUNTIF(changed,stat_merging_changed);
+ }
+
+ if (changed) {
+ LOG("changed!");
+ destblock->flags = BBTYPECHECK_REACHED;
+ if (destblock <= current) {LOG("REPEAT!"); return true;}
+ }
+ return false;
+}