1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-06-21 03:00:19 +02:00

Implement jit_frame and jit_tramp interfaces

* include/lightning.h, include/lightning/jit_private.h,
	lib/jit_aarch64-cpu.c, lib/jit_alpha-cpu.c, lib/jit_arm-cpu.c,
	lib/jit_hppa-cpu.c, lib/jit_ia64-cpu.c, lib/jit_mips-cpu.c,
	lib/jit_ppc-cpu.c, lib/jit_s390x-cpu.c, lib/jit_sparc-cpu.c,
	lib/jit_x86-cpu.c, lib/lightning.c: Implement the new
	jit_frame and jit_tramp interfaces, that allow writing
	trampoline like calls, where a single dispatcher jit buffer
	is written, and later other jit buffers are created, with
	the same stack frame layout as the dispatcher. This is the
	logic that GNU Smalltalk used in lightning 1.x, and is required
	to make a sane port for lighting 2.x.

	* jit_ia64-cpu.c: Implement support for jit_frame and jit_tramp,
	and also correct wrong encoding for B4 instructions, that
	implement jmpr, as well as correct reverse logic in _jmpr,
	that was moving the branch register to the jump register,
	and not vice-versa.
	Also, if a stack frame is to be assumed, always assume it may
	call a function with up to 8 arguments, regardless of the
	hint frame argument.

	* lib/jit_arm.c: Add a new must_align_p() interface to ensure
	function prologs are always aligned. This condition was
	previously always true, somewhat by accident, but with
	jit_tramp it is not guaranteed.

	* jit_ia64-cpu.c: lib/jit_ppc.c: Add minor special handling
	required to implement jit_tramp, where a function descriptor
	should not be added before a prolog, as jit_tramp means omit
	prolog.

	* check/lightning.c: Update test driver for the new interfaces.

	* check/Makefile.am, check/tramp.tst, check/tramp.ok: Add
	a simple test and example of the jit_frame and jit_tramp
	usage implementing a simple Fibonacci function using a
	simulation of an interpreter stack and how it would handle
	state in language specific variables.

	* doc/body.texi: Add documentation for jit_frame and
	jit_tramp.
This commit is contained in:
pcpa 2014-10-14 17:04:40 -03:00
parent 20a2f1f9c5
commit 839341a498
20 changed files with 284 additions and 15 deletions

View file

@ -1,3 +1,47 @@
2014-10-12 Paulo Andrade <pcpa@gnu.org>
* include/lightning.h, include/lightning/jit_private.h,
lib/jit_aarch64-cpu.c, lib/jit_alpha-cpu.c, lib/jit_arm-cpu.c,
lib/jit_hppa-cpu.c, lib/jit_ia64-cpu.c, lib/jit_mips-cpu.c,
lib/jit_ppc-cpu.c, lib/jit_s390x-cpu.c, lib/jit_sparc-cpu.c,
lib/jit_x86-cpu.c, lib/lightning.c: Implement the new
jit_frame and jit_tramp interfaces, that allow writing
trampoline like calls, where a single dispatcher jit buffer
is written, and later other jit buffers are created, with
the same stack frame layout as the dispatcher. This is the
logic that GNU Smalltalk used in lightning 1.x, and is required
to make a sane port for lighting 2.x.
* jit_ia64-cpu.c: Implement support for jit_frame and jit_tramp,
and also correct wrong encoding for B4 instructions, that
implement jmpr, as well as correct reverse logic in _jmpr,
that was moving the branch register to the jump register,
and not vice-versa.
Also, if a stack frame is to be assumed, always assume it may
call a function with up to 8 arguments, regardless of the
hint frame argument.
* lib/jit_arm.c: Add a new must_align_p() interface to ensure
function prologs are always aligned. This condition was
previously always true, somewhat by accident, but with
jit_tramp it is not guaranteed.
* jit_ia64-cpu.c: lib/jit_ppc.c: Add minor special handling
required to implement jit_tramp, where a function descriptor
should not be added before a prolog, as jit_tramp means omit
prolog.
* check/lightning.c: Update test driver for the new interfaces.
* check/Makefile.am, check/tramp.tst, check/tramp.ok: Add
a simple test and example of the jit_frame and jit_tramp
usage implementing a simple Fibonacci function using a
simulation of an interpreter stack and how it would handle
state in language specific variables.
* doc/body.texi: Add documentation for jit_frame and
jit_tramp.
2014-09-29 Paulo Andrade <pcpa@gnu.org>
* lib/jit_aarch64.c, lib/jit_alpha.c, lib/jit_arm.c,

View file

@ -82,6 +82,7 @@ EXTRA_DIST = \
qalu_mul.tst qalu_mul.ok \
qalu_div.tst qalu_div.ok \
ret.tst ret.ok \
tramp.tst tramp.ok \
check.sh \
check.x87.sh \
check.arm.sh check.swf.sh \
@ -107,7 +108,7 @@ base_TESTS = \
clobber carry call \
float jmpr \
qalu_mul qalu_div \
ret
ret tramp
$(base_TESTS): check.sh
$(LN_S) $(srcdir)/check.sh $@
@ -178,7 +179,7 @@ arm_TESTS = \
fop_abs.arm fop_sqrt.arm \
varargs.arm stack.arm \
clobber.arm carry.arm call.arm \
float.arm jmpr.arm
float.arm jmpr.arm tramp.arm
$(arm_TESTS): check.arm.sh
$(LN_S) $(srcdir)/check.arm.sh $@
TESTS += $(arm_TESTS)
@ -202,7 +203,7 @@ swf_TESTS = \
fop_abs.swf fop_sqrt.swf \
varargs.swf stack.swf \
clobber.swf carry.swf call.swf \
float.swf jmpr.arm
float.swf jmpr.swf tramp.swf
$(swf_TESTS): check.swf.sh
$(LN_S) $(srcdir)/check.swf.sh $@
TESTS += $(swf_TESTS)
@ -226,7 +227,7 @@ nodata_TESTS = \
fop_abs.nodata fop_sqrt.nodata \
varargs.nodata stack.nodata \
clobber.nodata carry.nodata call.nodata \
float.nodata jmpr.nodata
float.nodata jmpr.nodata tramp.nodata
$(nodata_TESTS): check.nodata.sh
$(LN_S) $(srcdir)/check.nodata.sh $@
TESTS += $(nodata_TESTS)

View file

@ -268,7 +268,9 @@ static void make_arg(void *value);
static jit_pointer_t get_arg(void);
static long get_imm(void);
static void name(void);
static void prolog(void); static void ellipsis(void);
static void prolog(void);
static void frame(void); static void tramp(void);
static void ellipsis(void);
static void allocai(void);
static void arg(void);
static void getarg_c(void); static void getarg_uc(void);
@ -566,7 +568,9 @@ static size_t data_offset, data_length;
static instr_t instr_vector[] = {
#define entry(value) { NULL, #value, value }
entry(name),
entry(prolog), entry(ellipsis),
entry(prolog),
entry(frame), entry(tramp),
entry(ellipsis),
entry(allocai),
entry(arg),
entry(getarg_c), entry(getarg_uc),
@ -1320,7 +1324,9 @@ name(void) {
(void)identifier(ch);
jit_name(parser.string);
}
entry(prolog) entry(ellipsis)
entry(prolog)
entry_im(frame) entry_im(tramp)
entry(ellipsis)
void
allocai(void) {
symbol_t *symbol;

View file

@ -1444,6 +1444,44 @@ Or to only use a data buffer, if required:
@rem{...}
@end example
@section Shared stack frame layout
Certain jit generation patterns, for example the original GNU Smalltalk
jit generator, uses an approach of a fixed trampoline jit code, and
later generation of code that jumps around, assuming a fixed layout
stack frame.
To help on this pattern of code generation, @lightning{} provides
the @code{jit_frame} and the @code{jit_tramp} interfaces, to define
or to assume a stack frame. Both @code{jit_frame} or @code{jit_tramp}
must be the first call after @code{jit_prolog}.
@deftypefun void jit_frame (jit_int32_t @var{frame})
@var{frame} defines the size in bytes of the current function
stack frame. To calculate its value, a good formula is maximum number
of arguments to any called native function times eight, plus the
sum of the arguments to any call to @code{jit_allocai}. @lightning{}
automatically adjusts this value for any backend specific stack memory
it may need, or any alignment constraint.
To ensure trampoline code is correct, @lightning{} will save all
callee save registers in the prolog and reload in the epilog.
@end deftypefun
@deftypefun void jit_tramp (jit_int32_t @var{frame})
@var{frame} must be the same value of the dispatcher defined with the
@code{jit_frame} call.
The only difference of @code{jit_frame} and @code{jit_tramp} is that
@code{jit_tramp} omits generation of a prolog and epilog for the
current function.
Most trampoline based jit generation implements a single dispatch method
and later emit code that knows how to return back to the dispatch routine,
and the later emitted code is called with a non local goto. In such cases,
emitting a native prolog (and epilog) is just a waste of space.
@end deftypefun
It is a fatal error if more than @var{frame} bytes are required
either in the dispatcher defined with @code{jit_frame} or the
"trampolined" code, defined with @code{jit_tramp}.
@node Acknowledgements
@chapter Acknowledgements

View file

@ -907,6 +907,10 @@ extern void _jit_set_code(jit_state_t*, jit_pointer_t, jit_word_t);
extern jit_pointer_t _jit_get_data(jit_state_t*, jit_word_t*, jit_word_t*);
#define jit_set_data(u,v,w) _jit_set_data(_jit,u,v,w)
extern void _jit_set_data(jit_state_t*, jit_pointer_t, jit_word_t, jit_word_t);
#define jit_frame(u) _jit_frame(_jit,u)
extern void _jit_frame(jit_state_t*, jit_int32_t);
#define jit_tramp(u) _jit_tramp(_jit,u)
extern void _jit_tramp(jit_state_t*, jit_int32_t);
#define jit_emit() _jit_emit(_jit)
extern jit_pointer_t _jit_emit(jit_state_t*);

View file

@ -349,6 +349,13 @@ struct jit_function {
jit_int32_t *regoff;
jit_regset_t regset;
jit_int32_t stack;
/* Helper for common jit generation pattern, used in GNU Smalltalk
* and possibly others, where a static frame layout is required or
* assumed. */
jit_int32_t frame;
jit_uint32_t define_frame : 1;
jit_uint32_t assume_frame : 1;
};
/* data used only during jit generation */
@ -559,6 +566,9 @@ _jit_save(jit_state_t*, jit_int32_t);
extern void
_jit_load(jit_state_t*, jit_int32_t);
#define jit_trampoline(u,v) _jit_trampoline(_jit, u, v)
extern void _jit_trampoline(jit_state_t*, jit_int32_t, jit_bool_t);
#define jit_optimize() _jit_optimize(_jit)
extern void
_jit_optimize(jit_state_t*);

View file

@ -2145,6 +2145,13 @@ _calli_p(jit_state_t *_jit, jit_word_t i0)
static void
_prolog(jit_state_t *_jit, jit_node_t *node)
{
if (_jitc->function->define_frame || _jitc->function->assume_frame) {
jit_int32_t frame = -_jitc->function->frame;
assert(_jitc->function->self.aoff >= frame);
if (_jitc->function->assume_frame)
return;
_jitc->function->self.aoff = frame;
}
_jitc->function->stack = ((_jitc->function->self.alen -
/* align stack at 16 bytes */
_jitc->function->self.aoff) + 15) & -16;
@ -2188,6 +2195,8 @@ _prolog(jit_state_t *_jit, jit_node_t *node)
static void
_epilog(jit_state_t *_jit, jit_node_t *node)
{
if (_jitc->function->assume_frame)
return;
if (_jitc->function->stack)
MOV_XSP(SP_REGNO, FP_REGNO);
#define LOAD(L, R, O) \

View file

@ -2504,6 +2504,13 @@ _calli_p(jit_state_t *_jit, jit_word_t i0)
static void
_prolog(jit_state_t *_jit, jit_node_t *node)
{
if (_jitc->function->define_frame || _jitc->function->assume_frame) {
jit_int32_t frame = -_jitc->function->frame;
assert(_jitc->function->self.aoff >= frame);
if (_jitc->function->assume_frame)
return;
_jitc->function->self.aoff = frame;
}
_jitc->function->stack = ((_jitc->function->self.alen -
_jitc->function->self.aoff) + 7) & -8;
/* ldgp gp, 0(pv) */
@ -2544,6 +2551,8 @@ _prolog(jit_state_t *_jit, jit_node_t *node)
static void
_epilog(jit_state_t *_jit, jit_node_t *node)
{
if (_jitc->function->assume_frame)
return;
movr(_SP_REGNO, _FP_REGNO);
ldxi(_RA_REGNO, _SP_REGNO, 0);
ldxi(_FP_REGNO, _SP_REGNO, 8);

View file

@ -3694,6 +3694,16 @@ _calli_p(jit_state_t *_jit, jit_word_t i0)
static void
_prolog(jit_state_t *_jit, jit_node_t *node)
{
if (_jitc->function->define_frame || _jitc->function->assume_frame) {
jit_int32_t frame = -_jitc->function->frame;
assert(_jitc->function->self.aoff >= frame);
if (_jitc->function->assume_frame) {
if (jit_thumb_p() && !_jitc->thumb)
_jitc->thumb = _jit->pc.w;
return;
}
_jitc->function->self.aoff = frame;
}
_jitc->function->stack = ((_jitc->function->self.alen -
/* align stack at 8 bytes */
_jitc->function->self.aoff) + 7) & -8;
@ -3732,6 +3742,8 @@ _prolog(jit_state_t *_jit, jit_node_t *node)
static void
_epilog(jit_state_t *_jit, jit_node_t *node)
{
if (_jitc->function->assume_frame)
return;
addi(_SP_REGNO, _FP_REGNO, 16);
if (jit_cpu.abi)
VPOP_F64(_D8_REGNO, 8);

View file

@ -55,6 +55,8 @@ typedef union _jit_thumb_t {
static jit_int32_t _jit_get_reg_pair(jit_state_t*);
#define jit_unget_reg_pair(rn) _jit_unget_reg_pair(_jit,rn)
static void _jit_unget_reg_pair(jit_state_t*,jit_int32_t);
# define must_align_p(node) _must_align_p(_jit, node)
static jit_bool_t _must_align_p(jit_state_t*,jit_node_t*);
#define load_const(uniq,r0,i0) _load_const(_jit,uniq,r0,i0)
static void _load_const(jit_state_t*,jit_bool_t,jit_int32_t,jit_word_t);
#define flush_consts() _flush_consts(_jit)
@ -1042,9 +1044,13 @@ _emit_code(jit_state_t *_jit)
jit_regarg_set(node, value);
switch (node->code) {
case jit_code_note: case jit_code_name:
if (must_align_p(node->next))
nop(2);
node->u.w = _jit->pc.w;
break;
case jit_code_label:
if (must_align_p(node->next))
nop(2);
/* remember label is defined */
node->flag |= jit_flag_patch;
node->u.w = _jit->pc.w;
@ -1665,6 +1671,30 @@ _jit_unget_reg_pair(jit_state_t *_jit, jit_int32_t reg)
}
}
/* A prolog must be aligned at mod 4 bytes boundary.
* This condition was not being required to be tested by
* accident previously, but with the jit_frame and jit_tramp
* code it is required */
static jit_bool_t
_must_align_p(jit_state_t *_jit, jit_node_t *node)
{
if (jit_thumb_p() && (_jit->pc.w & 3)) {
for (; node; node = node->next) {
switch (node->code) {
case jit_code_note:
case jit_code_name:
case jit_code_label:
break;
case jit_code_prolog:
return (1);
default:
return (0);
}
}
}
return (0);
}
static void
_load_const(jit_state_t *_jit, jit_bool_t uniq, jit_int32_t r0, jit_word_t i0)
{

View file

@ -2621,6 +2621,13 @@ _prolog(jit_state_t *_jit, jit_node_t *node)
jit_int32_t regno;
jit_word_t offset;
if (_jitc->function->define_frame || _jitc->function->assume_frame) {
/* hppa stack grows up */
assert(_jitc->function->self.aoff <= _jitc->function->frame);
if (_jitc->function->assume_frame)
return;
_jitc->function->self.aoff = _jitc->function->frame;
}
_jitc->function->stack = ((_jitc->function->self.aoff -
_jitc->function->self.alen -
_jitc->function->self.size) + 63) & -64;
@ -2651,6 +2658,8 @@ _epilog(jit_state_t *_jit, jit_node_t *node)
jit_int32_t regno;
jit_word_t offset;
if (_jitc->function->assume_frame)
return;
/* Restore any modified callee save registers */
offset = alloca_offset - 140;
for (regno = 0; regno < jit_size(gr); regno++, offset += 4) {

View file

@ -3297,7 +3297,7 @@ _B4(jit_state_t *_jit, jit_word_t _p,
assert(!(p & ~0x1L));
assert(!(tp & ~0x7L));
TSTPRED(_p);
inst((d<<37)|(wh<<33)|(x6<<27)|(b<<13)|(p<<12)|(tp<<6)|_p, INST_B);
inst((d<<35)|(wh<<33)|(x6<<27)|(b<<13)|(p<<12)|(tp<<6)|_p, INST_B);
}
static void
@ -5051,7 +5051,7 @@ _bsubi_u(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_word_t i1,
static void
_jmpr(jit_state_t *_jit, jit_int32_t r0)
{
MOV_rn_br(r0, BR_6);
MOV_br_rn(BR_6, r0);
BR(BR_6);
}
@ -5117,6 +5117,13 @@ _prolog(jit_state_t *_jit, jit_node_t *node)
{
jit_int32_t reg, ruse, rout;
if (_jitc->function->define_frame || _jitc->function->assume_frame) {
jit_int32_t frame = -_jitc->function->frame;
assert(_jitc->function->self.aoff >= frame);
if (_jitc->function->assume_frame)
return;
_jitc->function->self.aoff = frame;
}
_jitc->function->stack = ((_jitc->function->self.alen -
_jitc->function->self.aoff) + 15) & -16;
@ -5130,11 +5137,15 @@ _prolog(jit_state_t *_jit, jit_node_t *node)
ruse = _jitc->rout - GR_32;
/* How many out argument registers required? */
if (!_jitc->function->define_frame) {
for (reg = _OUT0; reg <= _OUT7; reg++) {
if (!jit_regset_tstbit(&_jitc->function->regset, reg))
break;
}
rout = reg - _OUT0;
}
else
rout = 8;
/* Do not know if will call div/mod functions (sqrt* needs one) */
if (rout < 2)
@ -5181,6 +5192,8 @@ _prolog(jit_state_t *_jit, jit_node_t *node)
static void
_epilog(jit_state_t *_jit, jit_node_t *node)
{
if (_jitc->function->assume_frame)
return;
if (jit_regset_tstbit(&_jitc->function->regset, JIT_F0))
LDF_FILL(rn(JIT_F0), GR_4);
if (jit_regset_tstbit(&_jitc->function->regset, JIT_F1)) {

View file

@ -1256,7 +1256,7 @@ _emit_code(jit_state_t *_jit)
undo.prolog_offset = _jitc->prolog.offset;
restart_function:
_jitc->again = 0;
if (_jitc->jump) {
if (_jitc->jump && !_jitc->function->assume_frame) {
/* remember prolog to hide offset adjustment for a jump
* to the start of a function, what is expected to be
* a common practice as first jit instruction */

View file

@ -2862,6 +2862,13 @@ _prolog(jit_state_t *_jit, jit_node_t *node)
{
jit_int32_t index;
jit_int32_t offset;
if (_jitc->function->define_frame || _jitc->function->assume_frame) {
jit_int32_t frame = -_jitc->function->frame;
assert(_jitc->function->self.aoff >= frame);
if (_jitc->function->assume_frame)
return;
_jitc->function->self.aoff = frame;
}
#if NEW_ABI
_jitc->function->stack = ((_jitc->function->self.alen -
/* align stack at 16 bytes */
@ -2900,6 +2907,8 @@ _epilog(jit_state_t *_jit, jit_node_t *node)
{
jit_int32_t index;
jit_int32_t offset;
if (_jitc->function->assume_frame)
return;
/* callee save registers */
movr(_SP_REGNO, _BP_REGNO);
offset = stack_framesize - (sizeof(jit_word_t) << 1);

View file

@ -3072,6 +3072,13 @@ _prolog(jit_state_t *_jit, jit_node_t *node)
unsigned long regno;
jit_word_t offset;
if (_jitc->function->define_frame || _jitc->function->assume_frame) {
jit_int32_t frame = -_jitc->function->frame;
assert(_jitc->function->self.aoff >= frame);
if (_jitc->function->assume_frame)
return;
_jitc->function->self.aoff = frame;
}
_jitc->function->stack = ((_jitc->function->self.alen +
_jitc->function->self.size -
_jitc->function->self.aoff) + 15) & -16;
@ -3124,6 +3131,8 @@ _epilog(jit_state_t *_jit, jit_node_t *node)
unsigned long regno;
jit_word_t offset;
if (_jitc->function->assume_frame)
return;
#if __ppc__
LWZ(_SP_REGNO, _SP_REGNO, 0);
ldxi(_R0_REGNO, _SP_REGNO, 8);

View file

@ -1280,7 +1280,7 @@ _emit_code(jit_state_t *_jit)
restart_function:
_jitc->again = 0;
#if __powerpc__
if (_jitc->jump) {
if (_jitc->jump && !_jitc->function->assume_frame) {
/* remember prolog to hide offset adjustment for a jump
* to the start of a function, what is expected to be
* a common practice as first jit instruction */

View file

@ -3256,6 +3256,13 @@ static void
_prolog(jit_state_t *_jit, jit_node_t *i0)
{
jit_int32_t regno, offset;
if (_jitc->function->define_frame || _jitc->function->assume_frame) {
jit_int32_t frame = -_jitc->function->frame;
assert(_jitc->function->self.aoff >= frame);
if (_jitc->function->assume_frame)
return;
_jitc->function->self.aoff = frame;
}
_jitc->function->stack = ((_jitc->function->self.alen -
/* align stack at 8 bytes */
_jitc->function->self.aoff) + 7) & -8;
@ -3299,6 +3306,8 @@ static void
_epilog(jit_state_t *_jit, jit_node_t *i0)
{
jit_int32_t regno, offset;
if (_jitc->function->assume_frame)
return;
for (regno = 0; regno < jit_size(gprs) - 1; regno++) {
if (jit_regset_tstbit(&_jitc->function->regset, gprs[regno]))
break;

View file

@ -1620,6 +1620,13 @@ _calli_p(jit_state_t *_jit, jit_word_t i0)
static void
_prolog(jit_state_t *_jit, jit_node_t *node)
{
if (_jitc->function->define_frame || _jitc->function->assume_frame) {
jit_int32_t frame = -_jitc->function->frame;
assert(_jitc->function->self.aoff >= frame);
if (_jitc->function->assume_frame)
return;
_jitc->function->self.aoff = frame;
}
/* align at 16 bytes boundary */
_jitc->function->stack = ((stack_framesize +
_jitc->function->self.alen -
@ -1649,6 +1656,8 @@ _prolog(jit_state_t *_jit, jit_node_t *node)
static void
_epilog(jit_state_t *_jit, jit_node_t *node)
{
if (_jitc->function->assume_frame)
return;
/* (most) other backends do not save incoming arguments, so,
* only save locals here */
if (jit_regset_tstbit(&_jitc->function->regset, _L0))

View file

@ -3326,6 +3326,13 @@ _jmpi(jit_state_t *_jit, jit_word_t i0)
static void
_prolog(jit_state_t *_jit, jit_node_t *node)
{
if (_jitc->function->define_frame || _jitc->function->assume_frame) {
jit_int32_t frame = -_jitc->function->frame;
assert(_jitc->function->self.aoff >= frame);
if (_jitc->function->assume_frame)
return;
_jitc->function->self.aoff = frame;
}
#if __WORDSIZE == 64 && __CYGWIN__
_jitc->function->stack = (((/* first 32 bytes must be allocated */
(_jitc->function->self.alen > 32 ?
@ -3406,6 +3413,8 @@ _prolog(jit_state_t *_jit, jit_node_t *node)
static void
_epilog(jit_state_t *_jit, jit_node_t *node)
{
if (_jitc->function->assume_frame)
return;
/* callee save registers */
movr(_RSP_REGNO, _RBP_REGNO);
#if __WORDSIZE == 32

View file

@ -1920,6 +1920,45 @@ fail:
return (NULL);
}
void
_jit_frame(jit_state_t *_jit, jit_int32_t frame)
{
jit_trampoline(frame, 1);
}
void
_jit_tramp(jit_state_t *_jit, jit_int32_t frame)
{
jit_trampoline(frame, 0);
}
void
_jit_trampoline(jit_state_t *_jit, jit_int32_t frame, jit_bool_t prolog)
{
jit_int32_t regno;
/* Must be called after prolog, actually, just to simplify
* tests and know there is a current function and that
* _jitc->function->self.aoff is at the before any alloca value */
assert(_jitc->tail && _jitc->tail->code == jit_code_prolog);
/* + 24 for 3 possible spilled temporaries (that could be a double) */
frame += 24;
#if defined(__hppa__)
frame += _jitc->function->self.aoff;
#else
frame -= _jitc->function->self.aoff;
#endif
_jitc->function->frame = frame;
if (prolog)
_jitc->function->define_frame = 1;
else
_jitc->function->assume_frame = 1;
for (regno = 0; regno < _jitc->reglen; regno++)
if (jit_class(_rvs[regno].spec) & jit_class_sav)
jit_regset_setbit(&_jitc->function->regset, regno);
}
/* Compute initial reglive and regmask set values of a basic block.
* reglive is the set of known live registers
* regmask is the set of registers not referenced in the block