/* 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
-
- Changes: Stefan Ring
- Christian Thalinger
- Christian Ullrich
- Michael Starzinger
- Edwin Steiner
-
- $Id: simplereg.c 6057 2006-11-27 14:58:43Z edwin $
-
*/
#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)
}
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;
codegendata *cd;
registerdata *rd;
- int s, t, tt, lm;
+ int s, t, tt, varindex;
int intalloc, fltalloc;
varinfo *v;
int memneeded = 0;
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;
}
}
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;