+/* stack_change_to_tempvar *****************************************************
+
+ Change the given stackslot to a TEMPVAR. This includes creating a new
+ temporary variable and changing the dst.varindex of the creator of the
+ stacklot to the new variable index. If this stackslot has been passed
+ through ICMDs between the point of its creation and the current point,
+ then the variable index is also changed in these ICMDs.
+
+ IN:
+ sd...........stack analysis data
+ sp...........stackslot to change
+ ilimit.......instruction up to which to look for ICMDs passing-through
+ the stackslot (exclusive). This may point exactly after the
+ last instruction, in which case the search is done to the
+ basic block end.
+
+*******************************************************************************/
+
+static void stack_change_to_tempvar(stackdata_t *sd, stackelement_t * sp,
+ instruction *ilimit)
+{
+ s4 newindex;
+ s4 oldindex;
+ instruction *iptr;
+ s4 depth;
+ s4 i;
+
+ oldindex = sp->varnum;
+
+ /* create a new temporary variable */
+
+ GET_NEW_VAR(*sd, newindex, sp->type);
+
+ sd->var[newindex].flags = sp->flags;
+
+ /* change the stackslot */
+
+ sp->varnum = newindex;
+ sp->varkind = TEMPVAR;
+
+ /* change the dst.varindex of the stackslot's creator */
+
+ if (sp->creator)
+ sp->creator->dst.varindex = newindex;
+
+ /* handle ICMDs this stackslot passed through, if any */
+
+ if (sp->flags & PASSTHROUGH) {
+ iptr = (sp->creator) ? (sp->creator + 1) : sd->bptr->iinstr;
+
+ /* assert that the limit points to an ICMD, or after the last one */
+
+ assert(ilimit >= sd->bptr->iinstr);
+ assert(ilimit <= sd->bptr->iinstr + sd->bptr->icount);
+
+ /* find the stackdepth under sp plus one */
+ /* Note: This number is usually known when this function is called, */
+ /* but calculating it here is less error-prone and should not be */
+ /* a performance problem. */
+
+ for (depth = 0; sp != NULL; sp = sp->prev)
+ depth++;
+
+ /* iterate over all instructions in the range and replace */
+
+ for (; iptr < ilimit; ++iptr) {
+ switch (iptr->opc) {
+ case ICMD_INVOKESTATIC:
+ case ICMD_INVOKESPECIAL:
+ case ICMD_INVOKEVIRTUAL:
+ case ICMD_INVOKEINTERFACE:
+ case ICMD_BUILTIN:
+ i = iptr->s1.argcount - depth;
+ if (iptr->sx.s23.s2.args[i] == oldindex) {
+ iptr->sx.s23.s2.args[i] = newindex;
+ }
+ break;
+ /* IMPORTANT: If any ICMD sets the PASSTHROUGH flag of a */
+ /* stackslot, it must be added in this switch! */
+ }
+ }
+ }
+}
+
+
+/* stack_init_javalocals *******************************************************
+
+ Initialize the mapping from Java locals to cacao variables at method entry.
+
+ IN:
+ sd...........stack analysis data
+
+*******************************************************************************/
+
+static void stack_init_javalocals(stackdata_t *sd)
+{
+ s4 *jl;
+ s4 type,i,j;
+ methoddesc *md;
+ jitdata *jd;
+
+ jd = sd->jd;
+
+ jl = DMNEW(s4, sd->maxlocals);
+ jd->basicblocks[0].javalocals = jl;
+
+ for (i=0; i<sd->maxlocals; ++i)
+ jl[i] = UNUSED;
+
+ md = jd->m->parseddesc;
+ j = 0;
+ for (i=0; i<md->paramcount; ++i) {
+ type = md->paramtypes[i].type;
+ jl[j] = jd->local_map[5*j + type];
+ j++;
+ if (IS_2_WORD_TYPE(type))
+ j++;
+ }
+}
+
+