/* src/vm/jit/stack.h - stack analysis header Copyright (C) 1996-2005, 2006, 2008 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO This file is part of CACAO. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _STACK_H #define _STACK_H /* forward typedefs ***********************************************************/ typedef struct stackelement_t stackelement_t; #include "config.h" #include #include "vm/types.h" #include "vm/global.h" #include "vm/jit/jit.hpp" #include "vm/jit/reg.h" /* stack element structure ****************************************************/ /* flags */ #define SAVEDVAR 1 /* variable has to survive method invocations */ #define INMEMORY 2 /* variable stored in memory */ #define SAVREG 4 /* allocated to a saved register */ #define ARGREG 8 /* allocated to an arg register */ #define PASSTHROUGH 32 /* stackslot was passed-through by an ICMD */ #define PREALLOC 64 /* preallocated var like for ARGVARS. Used */ /* with the new var system */ #define INOUT 128 /* variable is an invar or/and an outvar */ #define IS_SAVEDVAR(x) ((x) & SAVEDVAR) #define IS_INMEMORY(x) ((x) & INMEMORY) /* variable kinds */ #define UNDEFVAR 0 /* stack slot will become temp during regalloc*/ #define TEMPVAR 1 /* stack slot is temp register */ #define STACKVAR 2 /* stack slot is numbered stack slot */ #define LOCALVAR 3 /* stack slot is local variable */ #define ARGVAR 4 /* stack slot is argument variable */ struct stackelement_t { stackelement_t *prev; /* pointer to next element towards bottom */ instruction *creator; /* instruction that created this element */ s4 type; /* slot type of stack element */ s4 flags; /* flags (SAVED, INMEMORY) */ s4 varkind; /* kind of variable or register */ s4 varnum; /* number of variable */ }; /* macros used internally by analyse_stack ************************************/ /*--------------------------------------------------*/ /* BASIC TYPE CHECKING */ /*--------------------------------------------------*/ /* XXX would be nice if we did not have to pass the expected type */ #if defined(ENABLE_VERIFIER) #define CHECK_BASIC_TYPE(expected,actual) \ do { \ if ((actual) != (expected)) { \ expectedtype = (expected); \ goto throw_stack_type_error; \ } \ } while (0) #else /* !ENABLE_VERIFIER */ #define CHECK_BASIC_TYPE(expected,actual) #endif /* ENABLE_VERIFIER */ /*--------------------------------------------------*/ /* STACK UNDERFLOW/OVERFLOW CHECKS */ /*--------------------------------------------------*/ /* underflow checks */ #if defined(ENABLE_VERIFIER) #define REQUIRE(num) \ do { \ if (stackdepth < (num)) \ goto throw_stack_underflow; \ } while (0) #else /* !ENABLE_VERIFIER */ #define REQUIRE(num) #endif /* ENABLE_VERIFIER */ /* overflow check */ /* We allow ACONST instructions inserted as arguments to builtin * functions to exceed the maximum stack depth. Maybe we should check * against maximum stack depth only at block boundaries? */ /* XXX we should find a way to remove the opc/op1 check */ #if defined(ENABLE_VERIFIER) #define CHECKOVERFLOW \ do { \ if (stackdepth > m->maxstack) \ if ((iptr->opc != ICMD_ACONST) || INSTRUCTION_MUST_CHECK(iptr))\ goto throw_stack_overflow; \ } while(0) #else /* !ENABLE_VERIFIER */ #define CHECKOVERFLOW #endif /* ENABLE_VERIFIER */ /*--------------------------------------------------*/ /* ALLOCATING STACK SLOTS */ /*--------------------------------------------------*/ #define NEWSTACK(s,v,n) \ do { \ sd.new->prev = curstack; \ sd.new->type = (s); \ sd.new->flags = 0; \ sd.new->varkind = (v); \ sd.new->varnum = (n); \ curstack = sd.new; \ sd.var[(n)].type = (s); \ sd.var[(n)].flags = 0; \ sd.new++; \ } while (0) /* Initialize regoff, so -sia can show regnames even before reg.inc */ /* regs[rd->intregargnum] has to be set for this */ /* new->regoff = (IS_FLT_DBL_TYPE(s))?-1:rd->intreg_argnum; } */ #define NEWSTACKn(s,n) NEWSTACK(s,UNDEFVAR,n) #define NEWSTACK0(s) NEWSTACK(s,UNDEFVAR,0) /* function prototypes ********************************************************/ #ifdef __cplusplus extern "C" { #endif bool stack_init(void); bool stack_analyse(jitdata *jd); void stack_javalocals_store(instruction *iptr, s4 *javalocals); #ifdef __cplusplus } #endif #endif /* _STACK_H */ /* * These are local overrides for various environment variables in Emacs. * Please do not remove this and leave it at the end of the file, where * Emacs will automagically detect them. * --------------------------------------------------------------------- * Local variables: * mode: c * indent-tabs-mode: t * c-basic-offset: 4 * tab-width: 4 * End: * vim:noexpandtab:sw=4:ts=4: */