/* src/vm/jit/allocator/simplereg.c - register allocator
- Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
+ Copyright (C) 1996-2005, 2007 R. Grafl, A. Krall, C. Kruegel, C. Oates,
R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
Institut f. Computersprachen - TU Wien
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
- Contact: cacao@complang.tuwien.ac.at
-
- Authors: Andreas Krall
- Stefan Ring
- Christian Thalinger
- Christian Ullrich
- Michael Starzinger
- Edwin Steiner
-
- $Id: simplereg.c 5980 2006-11-15 12:25:13Z twisti $
-
*/
#include "config.h"
-#include "vm/types.h"
#include <assert.h>
+#include <stdint.h>
+
+#include "vm/types.h"
#include "arch.h"
#include "md-abi.h"
+#include "mm/memory.h"
+
#include "vm/builtin.h"
#include "vm/exceptions.h"
-#include "mm/memory.h"
-#include "vm/method.h"
-#include "vm/options.h"
#include "vm/resolve.h"
#include "vm/stringlocal.h"
+
+#include "vm/jit/abi.h"
#include "vm/jit/reg.h"
-#include "vm/jit/allocator/simplereg.h"
#include "vm/jit/show.h"
+#include "vm/jit/allocator/simplereg.h"
+
+#include "vmcore/method.h"
+#include "vmcore/options.h"
#if 0
static void simplereg_allocate_temporaries(jitdata *jd);
+/* size of a stackslot used by the internal ABI */
+
+#if defined(HAS_4BYTE_STACKSLOT)
+# define SIZE_OF_STACKSLOT 4
+#else
+# define SIZE_OF_STACKSLOT 8
+#endif
+
+
/* total number of registers */
#if defined(HAS_ADDRESS_REGISTER_FILE)
#define AVAIL_FREE_TMP_INT AVAIL_BACK_INT(rd->freetmpinttop)
#define AVAIL_FREE_SAV_INT AVAIL_BACK_INT(rd->freesavinttop)
-#define TAKE_ARG_FLT(r) POP_FRONT(rd->argfltregs, rd->argfltreguse, r)
+#define TAKE_ARG_FLT(r) POP_FRONT(abi_registers_float_argument, rd->argfltreguse, r)
#define TAKE_TMP_FLT(r) POP_BACK(rd->tmpfltregs, rd->tmpfltreguse, r)
#define TAKE_SAV_FLT(r) POP_BACK(rd->savfltregs, rd->savfltreguse, r)
#define TAKE_TMP_ADR(r) POP_BACK(rd->tmpadrregs, rd->tmpadrreguse, r)
#define TAKE_SAV_ADR(r) POP_BACK(rd->savadrregs, rd->savadrreguse, r)
-#define TAKE_ARG_INT(r) POP_FRONT_INT(rd->argintregs, rd->argintreguse, r)
+#define TAKE_ARG_INT(r) POP_FRONT_INT(abi_registers_integer_argument, rd->argintreguse, r)
#define TAKE_TMP_INT(r) POP_BACK_INT(rd->tmpintregs, rd->tmpintreguse, r)
#define TAKE_SAV_INT(r) POP_BACK_INT(rd->savintregs, rd->savintreguse, r)
#define NEW_MEM_SLOT(r) \
do { \
- (r) = rd->memuse; \
+ (r) = rd->memuse * SIZE_OF_STACKSLOT; \
rd->memuse += memneeded + 1; \
} while (0)
do { \
if ( (memneeded) && (rd->memuse & 1)) \
rd->memuse++; \
- (r) = rd->memuse; \
+ (r) = rd->memuse * SIZE_OF_STACKSLOT; \
rd->memuse += memneeded + 1; \
} while (0)
PUSH_BACK(rd->freemem, rd->freememtop, rd->memuse); \
rd->memuse++; \
} \
- (r) = rd->memuse; \
+ (r) = rd->memuse * SIZE_OF_STACKSLOT; \
rd->memuse += memneeded + 1; \
} while (0)
static void simplereg_allocate_interfaces(jitdata *jd)
{
methodinfo *m;
+ codeinfo *code;
codegendata *cd;
registerdata *rd;
/* get required compiler data */
- m = jd->m;
- cd = jd->cd;
- rd = jd->rd;
+ m = jd->m;
+ code = jd->code;
+ cd = jd->cd;
+ rd = jd->rd;
/* rd->memuse was already set in stack.c to allocate stack space
for passing arguments to called methods. */
}
#endif
- if (jd->isleafmethod) {
+ if (code_is_leafmethod(code)) {
/* Reserve argument register, which will be used for Locals acting */
/* as Parameters */
if (rd->argintreguse < m->parseddesc->argintreguse)
if (!saved) {
#if defined(HAS_ADDRESS_REGISTER_FILE)
if (IS_ADR_TYPE(t)) {
- if (!jd->isleafmethod && AVAIL_ARG_ADR) {
+ if (!code_is_leafmethod(code) && AVAIL_ARG_ADR) {
flags |= ARGREG;
TAKE_ARG_ADR(regoff);
}
}
else {
flags |= INMEMORY;
- regoff = rd->memuse++;
+ regoff = rd->memuse++ * SIZE_OF_STACKSLOT;
}
}
else /* !IS_ADR_TYPE */
fltalloc = s * 5 + t;
}
else { /* !IS_FLT_DBL_TYPE(t) */
-#if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
+#if (SIZEOF_VOID_P == 4) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
/*
* for i386 put all longs in memory
*/
NEW_MEM_SLOT_INT_LNG(regoff);
}
else
-#endif /* defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE...GISTERS) */
+#endif
if (intalloc >= 0) {
/* Reuse memory slot(s)/register(s) for shared interface slots */
flags |= jd->interface_map[intalloc].flags & ~SAVEDVAR;
}
else {
flags |= INMEMORY;
- regoff = rd->memuse++;
+ regoff = rd->memuse++ * SIZE_OF_STACKSLOT;
}
}
else
fltalloc = s * 5 + t;
}
else { /* IS_INT_LNG */
-#if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
+#if (SIZEOF_VOID_P == 4) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
/*
* for i386 put all longs in memory
*/
registerdata *rd;
methoddesc *md;
- int p, s, t, tt, lm;
+ int p, s, t, tt, varindex;
int intalloc, fltalloc;
varinfo *v;
int intregsneeded = 0;
intalloc = -1; fltalloc = -1;
for (tt = 0; tt <= 4; tt++) {
t = typeloop[tt];
- lm = jd->local_map[s * 5 + t];
- if (lm == UNUSED)
+ varindex = jd->local_map[s * 5 + t];
+ if (varindex == UNUSED)
continue;
- v = VAR(lm);
+ v = VAR(varindex);
#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
}
else {
v->flags |= INMEMORY;
- v->vv.regoff = rd->memuse++;
+ v->vv.regoff = rd->memuse++ * SIZE_OF_STACKSLOT;
}
}
else {
#if !defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
/* We can only use float arguments as local variables,
* if we do not pass them in integer registers. */
- else if ((p < md->paramcount) &&
- !md->params[p].inmemory)
- {
+ else if ((p < md->paramcount) && !md->params[p].inmemory) {
v->flags = 0;
- v->vv.regoff = rd->argfltregs[md->params[p].regoff];
+ v->vv.regoff = md->params[p].regoff;
}
#endif
else if (AVAIL_TMP_FLT) {
TAKE_TMP_FLT(v->vv.regoff);
}
/* use unused argument registers as local registers */
- else if ((p >= md->paramcount) &&
- (fargcnt < FLT_ARG_CNT))
- {
+ else if ((p >= md->paramcount) && (fargcnt < FLT_ARG_CNT)) {
v->flags = 0;
- POP_FRONT(rd->argfltregs, fargcnt, v->vv.regoff);
+ POP_FRONT(abi_registers_float_argument,
+ fargcnt, v->vv.regoff);
}
else if (AVAIL_SAV_FLT) {
v->flags = 0;
}
else {
-#if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
+#if (SIZEOF_VOID_P == 4) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
/*
* for i386 put all longs in memory
*/
v->flags = 0;
#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
if (IS_2_WORD_TYPE(t))
- v->vv.regoff = PACK_REGS(
- rd->argintregs[GET_LOW_REG(md->params[p].regoff)],
- rd->argintregs[GET_HIGH_REG(md->params[p].regoff)]);
+ v->vv.regoff =
+ PACK_REGS(GET_LOW_REG(md->params[p].regoff),
+ GET_HIGH_REG(md->params[p].regoff));
else
#endif
- v->vv.regoff =
- rd->argintregs[md->params[p].regoff];
+ v->vv.regoff = md->params[p].regoff;
}
else if (AVAIL_TMP_INT) {
v->flags = 0;
(iargcnt + intregsneeded < INT_ARG_CNT))
{
v->flags = 0;
- POP_FRONT_INT(rd->argintregs, iargcnt, v->vv.regoff);
+ POP_FRONT_INT(abi_registers_integer_argument,
+ iargcnt, v->vv.regoff);
}
else if (AVAIL_SAV_INT) {
v->flags = 0;
static void simplereg_allocate_locals(jitdata *jd)
{
+ codeinfo *code;
codegendata *cd;
registerdata *rd;
- int s, t, tt, lm;
+ int s, t, tt, varindex;
int intalloc, fltalloc;
varinfo *v;
int memneeded = 0;
/* get required compiler data */
- cd = jd->cd;
- rd = jd->rd;
+ code = jd->code;
+ cd = jd->cd;
+ rd = jd->rd;
- if (jd->isleafmethod) {
+ if (code_is_leafmethod(code)) {
simplereg_allocate_locals_leafmethod(jd);
return;
}
for (tt=0; tt<=4; tt++) {
t = typeloop[tt];
- lm = jd->local_map[s * 5 + t];
- if (lm == UNUSED)
+ varindex = jd->local_map[s * 5 + t];
+ if (varindex == UNUSED)
continue;
- v = VAR(lm);
+ v = VAR(varindex);
#ifdef SUPPORT_COMBINE_INTEGER_REGISTERS
intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
}
else {
v->flags = INMEMORY;
- v->vv.regoff = rd->memuse++;
+ v->vv.regoff = rd->memuse++ * SIZE_OF_STACKSLOT;
}
}
else {
fltalloc = jd->local_map[s * 5 + t];
}
else {
-#if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
+#if (SIZEOF_VOID_P == 4) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
/*
* for i386 put all longs in memory
*/
v->flags = INMEMORY;
NEW_MEM_SLOT_INT_LNG(v->vv.regoff);
}
-#if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
+#if (SIZEOF_VOID_P == 4) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
}
#endif
intalloc = jd->local_map[s * 5 + t];
/* record the interface registers as used */
for (i=0; i<rd->argintreguse; ++i)
- rd->intusedinout[rd->argintregs[i]] = 1;
+ rd->intusedinout[abi_registers_integer_argument[i]] = 1;
for (i=rd->tmpintreguse; i<INT_TMP_CNT; ++i)
rd->intusedinout[rd->tmpintregs[i]] = 1;
for (i=rd->savintreguse; i<INT_SAV_CNT; ++i)
rd->intusedinout[rd->savintregs[i]] = 1;
for (i=0; i<rd->argfltreguse; ++i)
- rd->fltusedinout[rd->argfltregs[i]] = 1;
+ rd->fltusedinout[abi_registers_float_argument[i]] = 1;
for (i=rd->tmpfltreguse; i<FLT_TMP_CNT; ++i)
rd->fltusedinout[rd->tmpfltregs[i]] = 1;
for (i=rd->savfltreguse; i<FLT_SAV_CNT; ++i)
rd = jd->rd;
v = VAR(index);
+ /* assert that constants are not allocated */
+
+ assert(v->type != TYPE_RET);
+
/* Try to allocate a saved register if there is no temporary one */
/* available. This is what happens during the second run. */
tryagain = (v->flags & SAVEDVAR) ? 1 : 2;
}
}
else {
-#if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
+#if (SIZEOF_VOID_P == 4) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
/*
* for i386 put all longs in memory
*/
}
else {
-#if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
+#if (SIZEOF_VOID_P == 4) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
/*
* for i386 put all longs in memory
*/
static void simplereg_free(registerdata *rd, s4 flags, s4 regoff, s4 type)
{
- /* if this is a copy of another variable, just decrement the copy counter */
+ /* assert that constants are not freed */
+
+ assert(type != TYPE_RET);
- /* XXX split reg/mem variables on arm may need special handling here */
+ /* if this is a copy of another variable, just decrement the copy counter */
if (flags & INMEMORY) {
+ int32_t memindex;
+
if (flags & INOUT)
return;
- if (regoff < rd->memcopycountsize && rd->memcopycount[regoff]) {
- rd->memcopycount[regoff]--;
+ memindex = regoff / SIZE_OF_STACKSLOT;
+
+ if (memindex < rd->memcopycountsize && rd->memcopycount[memindex]) {
+ rd->memcopycount[memindex]--;
return;
}
}
for (i=0; i<bptr->indepth; ++i)
{
v = VAR(bptr->invars[i]);
+ if (v->type == TYPE_RET)
+ continue;
v->vv.regoff = jd->interface_map[5*i + v->type].regoff;
v->flags = jd->interface_map[5*i + v->type].flags;
for (i=0; i<bptr->outdepth; ++i)
{
v = VAR(bptr->outvars[i]);
+ if (v->type == TYPE_RET)
+ continue;
v->vv.regoff = jd->interface_map[5*i + v->type].regoff;
v->flags = jd->interface_map[5*i + v->type].flags;
/* pop 0 push 0 */
case ICMD_JSR:
-#if !defined(NDEBUG)
- /* avoid problems with show_allocation */
- VAROP(iptr->dst)->vv.regoff = 0;
-#endif
case ICMD_NOP:
+ case ICMD_CHECKNULL:
case ICMD_IINC:
case ICMD_RET:
case ICMD_RETURN:
case ICMD_PUTSTATICCONST:
case ICMD_INLINE_START:
case ICMD_INLINE_END:
- case ICMD_INLINE_GOTO:
+ case ICMD_INLINE_BODY:
break;
/* pop 0 push 1 const */
/* pop 1 push 0 */
case ICMD_POP:
- case ICMD_CHECKNULL_POP:
case ICMD_IRETURN:
case ICMD_LRETURN:
case ICMD_IF_LCMPGT:
case ICMD_IF_LCMPLE:
- case ICMD_IF_FCMPEQ:
- case ICMD_IF_FCMPNE:
-
- case ICMD_IF_FCMPL_LT:
- case ICMD_IF_FCMPL_GE:
- case ICMD_IF_FCMPL_GT:
- case ICMD_IF_FCMPL_LE:
-
- case ICMD_IF_FCMPG_LT:
- case ICMD_IF_FCMPG_GE:
- case ICMD_IF_FCMPG_GT:
- case ICMD_IF_FCMPG_LE:
-
- case ICMD_IF_DCMPEQ:
- case ICMD_IF_DCMPNE:
-
- case ICMD_IF_DCMPL_LT:
- case ICMD_IF_DCMPL_GE:
- case ICMD_IF_DCMPL_GT:
- case ICMD_IF_DCMPL_LE:
-
- case ICMD_IF_DCMPG_LT:
- case ICMD_IF_DCMPG_GE:
- case ICMD_IF_DCMPG_GT:
- case ICMD_IF_DCMPG_LE:
-
case ICMD_IF_ACMPEQ:
case ICMD_IF_ACMPNE:
v = VAROP(iptr->dst);
if (v->flags & INMEMORY) {
- if (v->vv.regoff >= rd->memcopycountsize) {
- int newsize = (v->vv.regoff + 1) * 2;
+ int32_t memindex = v->vv.regoff / SIZE_OF_STACKSLOT;
+ if (memindex >= rd->memcopycountsize) {
+ int newsize = (memindex + 1) * 2;
i = rd->memcopycountsize;
rd->memcopycount = DMREALLOC(rd->memcopycount, int, i, newsize);
MZERO(rd->memcopycount + i, int, newsize - i);
rd->memcopycountsize = newsize;
}
- rd->memcopycount[v->vv.regoff]++;
+ rd->memcopycount[memindex]++;
}
else {
/* XXX split reg/mem variables on arm may need special handling here */
break;
default:
- *exceptionptr =
- new_internalerror("Unknown ICMD %d during register allocation",
- iptr->opc);
+ exceptions_throw_internalerror("Unknown ICMD %d during register allocation",
+ iptr->opc);
return;
} /* switch */
iptr++;
methodinfo *m;
codegendata *cd;
registerdata *rd;
- int i,type;
+ int i;
s4 len;
+#if 0
stackptr src, src_old;
stackptr dst;
instruction *iptr;
+#endif
basicblock *bptr;
int size_interface; /* == maximum size of in/out stack at basic block boundaries */
bool in_register;