Alien-LibJIT

 view release on metacpan or  search on metacpan

libjit/ChangeLog  view on Meta::CPAN

            Kirill Kononenko  <Kirill.Kononenko@gmail.com>

	* tools/gen-apply.c (run_detect_struct_##n): Work around a bug in
	gcc-4.3 with optimization level 2 and Debian Lenny. Make
	'jit_nint stack[1]' volatile.

2009-01-01  Klaus Treichel  <ktreichel@web.de>

	* jit/jit-rules-x86-64.ins (JIT_OP_NFLOAT_TO_FLOAT32,
	JIT_OP_NFLOAT_TO_FLOAT64): Add rules for the case that the
	destination value is in the stack frame.
	(JIT_OP_BR_ILT, JIT_OP_BR_ILE, JIT_OP_BR_IGT, JIT_OP_BR_IGE):
	Handle the comparision with a constant 0 with a test opcode instead
	of a cmp.
	(JIT_OP_ISIGN, JIT_OP_LSIGN): Add handling of the integer sign
	opcodes.

2008-12-21  Aleksey Demakov  <ademakov@gmail.com>

	* jit/jit-dump.c (jit_dump_function): dump undefined labels as such
	rather than generating new labels for them.

libjit/ChangeLog  view on Meta::CPAN

	* include/jit/jit-arch-x86.h, include/jit/jit-arch-x86.h: Fix the
	 definition of _JIT_ARCH_GET_CURRENT_FRAME for MS cl. Use a
	temporary value for ebp/rbp because cl doesn't like arguments like
	f->x in the __asm statements.

	* jit/jit-rules-x86.ins: Move declaration of patch to the start of
	the block in JIT_OP_ULONG_TO_NFLOAT to be ANSI C compliant.

2008-05-21  Aleksey Demakov  <ademakov@gmail.com>

	* include/jit/jit-walk.h (jit_get_next_frame_address): use
	JIT_ARCH_GET_NEXT_FRAME if defined, use gcc syntax only if
	defined __GNUC__.

2008-05-12  Klaus Treichel  <ktreichel@web.de>

	* jit/jit-apply-x86-64.h: Include jit/jit-common.h instead of
	jit-internal.h to get the definition of the libjit types.

2008-05-08  Aleksey Demakov  <ademakov@gmail.com>

libjit/ChangeLog  view on Meta::CPAN


2008-04-19  Klaus Treichel  <ktreichel@web.de>

	* jit/jit-insn.c (jit_insn_sign): the dest value of the sign insn
	has to be int regardless of the argument type.

2008-04-13  Klaus Treichel  <ktreichel@web.de>

	* include/jit/Makefile.am:
	* include/jit/jit-arch-x86-64.h: new file with x86-64 architecture
	specific macros for stack frame inspection.

	* configure.in: check for x86-64 arch, add -fno-omit-frame-pointer
	flag.

	* include/jit/jit-walk.h: use _JIT_ARCH_GET_RETURN_ADDRESS and
	_JIT_ARCH_GET_CURRENT_RETURN if available.

	* jit/jit-gen-x86-64.h: Add additional macros for saving and
	restoring the fpu controlword and the mxcsr register. Add
	additional SSE conversion macros. Add SSE compare macros.
	Add macros for the SSE bit operations on packed values.
	Add macros for SSE sqrt and rounding. Add macros for fpu rounding.

libjit/ChangeLog  view on Meta::CPAN

	to cleanup_on_restart() which does this job more thoroughly.

	* jit/jit-reg-alloc.h, jit/jit-reg-alloc.c: remove _jit_regs_abort()
	function as the new cleanup-on-restart code makes it superflows.

	* jit/jit-reg-alloc.c (is_register_occupied): add new function;
	(clobbers_register, spill_clobbered_register, _jit_regs_gen): fix
	a problem that shows up with the new cleanup method.

	* tools/gen-rules-parser.y (gensel_output_clauses): the conditions
	for the local and frame patterns are changed. If the value is used
	before it is defined then both in_frame and in_register	flags are
	clear. This situation is perfectly valid if there is a backward
	branch form a point after the definition to a point before the use.
	So if the value is not a constant and it is not in a register assume
	that it is on the stack even if the in_frame flag is not set.

2007-02-10  Klaus Treichel  <ktreichel@web.de>

	* jit/jit-function.c: Use the on-demand compilation driver in
	jit_function_apply too. Return the functions' entry point if the
	function is allready compiled in jit_function_compile_entry.

2007-02-04  Aleksey Demakov  <ademakov@gmail.com>

	* include/jit/jit-common.h, include/jit/jit-context.h,

libjit/ChangeLog  view on Meta::CPAN

	* jit/jit-reg-alloc.c (_jit_regs_gen, set_regdesc_flags): fix bugs
	introduced 2006-12-30 with loading registers for ternary ops and
	handling input register thrash.

2007-01-26  Aleksey Demakov  <ademakov@gmail.com>

	* include/jit/jit-arch-x86.h (_JIT_ARCH_GET_CURRENT_FRAME): tweak
	gcc version of the macro.

	* jit/jit-apply-x86.c (_jit_create_redirector): redirector does not
	use stack frame so remove frame set up and restore instructions.

2007-01-23  Aleksey Demakov  <ademakov@gmail.com>

	* jit/jit-internal.h, jit/jit-function.c: remove the closure_entry
	field from jit_function_t. Find this value on the fly in
	jit_function_to_closure() and jit_function_to_vtable_pointer()
	to be equal either to entry_point or indirector fields.

	* jit/jit-rules-alpha.ins, jit/jit-rules-x86.ins: use
	jit_function_to_closure() instead of the closure_entry field.

libjit/ChangeLog  view on Meta::CPAN

	used (thanks Klaus for spotting).

2006-10-02  Klaus Treichel  <ktreichel@web.de>

	* jit/jit-intrinsic.c: Fix a copy bug in jit_ulong_mul (replace - by *).

2006-09-25  Aleksey Demakov  <ademakov@gmail.com>

	* include/jit/jit-arch-x86.h, include/jit/jit-arch-generic.h: add
	headers for architecture-specific definitions.
	(_JIT_ARCH_GET_CURRENT_FRAME): add macro to find the stack frame
	pointer.

	* include/jit/Makefile.am: create jit-arch.h as a symlink to one of
	the jit-arch-*.h files depending on the JIT_ARCH value.
	* configure.in: set JIT_ARCH according to the system architecture.

	* include/jit/jit-walk.h (jit_get_current_frame):
	* jit/jit-walk.c (jit_get_starting_frame):
	* tools/gen-apply.c (find_return_offset, detect_frame_offsets): use
	_JIT_ARCH_GET_CURRENT_FRAME macro if available. This resolves the
	problem	with gcc 4.1.* where __builtin_frame_address() function is
	broken (thanks Klaus for identifing the problem).

2006-09-15  Radek Polak <psonek2@seznam.cz>

        * include/jit/jit-insn.h, jit/jit-insn.c, jit/jit-debugger.c: new
        instruction jit_insn_mark_breakpoint_variable.

2006-09-14  Aleksey Demakov  <ademakov@gmail.com>

	* jit/jit-reg-alloc.h, jit/jit-reg-alloc.c: remove "old" register

libjit/ChangeLog  view on Meta::CPAN

2006-08-31  Klaus Treichel  <ktreichel@web.de>

	* configure.in: Replace the deprecated AM_PROG_LIBTOOL with the current
	AC_PROG_LIBTOOL.

	* jitdynamic/Makefile.am, jitplus/Makefile.am: Add -no-undefined to the
	LDFLAGS to enable building cygwin/mingw dlls.

2006-08-31  Aleksey Demakov  <ademakov@gmail.com>

	* tools/gen-rules-scanner.l, tools/gen-rules-parser.y: add "frame"
	keyword that is just like "local" but forces the value out from the
	register into the stack frame.

	* jit/jit-rules-x86.ins: rewrite JIT_OP_COPY_STORE_BYTE,
	JIT_OP_ADDRESS_OF, and JIT_OP_COPY_STORE_SHORT rules using the
	"frame" keyword.

	* jit/Makefile.am, jit/jit-rules-x86.c: remove all references to
	jit-rules-x86.sel and jit-rules-x86.slc.

	* jit/jit-rules-x86.c: remove mov_memindex_reg_byte() and
	widen_byte() functions.

2006-08-30  Aleksey Demakov  <ademakov@gmail.com>

	* jit/jit-interp.h, jit/jit-interp.c, jit/jit-opcode.c,

libjit/ChangeLog  view on Meta::CPAN


	* jit/jit-rules-x86.c (_jit_gen_exch_top): fix computation of stack
	register index.

	* jit/jit-reg-alloc.c (_jit_regs_assign): micro optimization by
	changing nesting order of for and if statements.

2006-05-19  Aleksey Demakov  <ademakov@gmail.com>

	* jit-reg-alloc.h, jit/jit-reg-alloc.c: determine if input values
	need to be saved and evicted from registers to stack frame at the
	_jit_regs_assign() time. Uniformly save input values that need to
	in _jit_regs_gen(), do not save them in _jit_regs_commit(). This
	simplifies handling of stack registers. Remove initial_stack_top,
	exchanges, num_exchages fields from the _jit_regs_t struct. Add
	save and kill bit fields to the _jit_regdesc_t struct. Refactor
	and clean up code.

2006-05-10  Aleksey Demakov  <ademakov@gmail.com>

	* jit/jit-reg-alloc.c (use_cheapest_register): check if the other

libjit/ChangeLog  view on Meta::CPAN


2006-04-03  Aleksey Demakov  <ademakov@gmail.com>

	* tools/gen-rules-scanner.l:
	* tools/gen-rules-parser.y: add `reversible', `x87arith',
	  and `copy' keywords. Fix bugs.

2006-03-23  Klaus Treichel  <ktreichel@web.de>

	* jit/jitc-except.c: Walk the stack to build the stack trace in
	jit_exception_get_stack_trace when the frame is not broken.

2006-03-23  Aleksey Demakov  <ademakov@gmail.com>

	* tools/Makefile.am: 
	* tools/gen-rules-parser.y, tools/gen-rules-scanner.l: add
	"gen-rules" tool that is similar to "gen-sel" but uses new
	register allocator.

2006-03-12  Klaus Treichel  <ktreichel@web.de>

libjit/ChangeLog  view on Meta::CPAN

	64-bit opcodes in the instruction selectors.

2004-06-12  Rhys Weatherley  <rweather@southern-storm.com.au>

	* jit/jit-insn.c, jit/jit-rules-x86.c, jit/jit-rules-x86.sel:
	implement or stub missing x86 instruction selection rules.

	* include/jit/jit-insn.h, include/jit/jit-opcode.h,
	include/jit/jit-plus.h, jit/jit-function.c, jit/jit-insn.c,
	jit/jit-interp.c, jit/jit-opcode.c, jit/jit-rules-interp.c,
	jitplus/jit-plus-function.cpp: add the "outgoing_frame_posn"
	instruction, to support tail calls.

2004-06-11  Rhys Weatherley  <rweather@southern-storm.com.au>

	* doc/libjit.texi, jit/jit-insn.c, jit/jit-internal.h,
	jit/jit-reg-alloc.c, jit/jit-rules-arm.c, jit/jit-rules-arm.sel,
	jit/jit-rules-interp.c, jit/jit-rules-x86.c, jit/jit-rules-x86.sel,
	jit/jit-rules.h, jit/jit-value.c, tutorial/Makefile.am,
	tutorial/t2.c, tutorial/t5.c: implement tail calls from a
	function to itself.

libjit/ChangeLog  view on Meta::CPAN

	* include/jit/jit-insn.h, include/jit/jit-opcode.h,
	include/jit/jit-plus.h, jit/jit-insn.c, jit/jit-internal.h,
	jit/jit-interp.c, jit/jit-opcode.c, jit/jit-rules-arm.c,
	jit/jit-rules-arm.sel, jitplus/jit-plus-function.cpp:
	add support for outgoing parameter areas, which should reduce
	the overhead of function calls that involve stacked arguments
	on non-x86 platforms; use parameter areas in the ARM back end.

	* include/jit/jit-plus.h, include/jit/jit-value.h, jit/jit-insn.c,
	jit/jit-internal.h, jit/jit-reg-alloc.c, jit/jit-rules-x86.c,
	jit/jit-value.c: don't over-allocate x86 stack frames if
	EBX, ESI, and EDI don't need to be saved; don't perform global
	register allocation on stacked parameters because it confuses
	the register spill logic.

	* jit/jit-reg-alloc.c (_jit_regs_load_value): avoid unnecessary
	spills if a temporary value won't be used again in the current block.

2004-06-09  Rhys Weatherley  <rweather@southern-storm.com.au>

	* jit/jit-rules-arm.c (flush_constants): update the instruction

libjit/ChangeLog  view on Meta::CPAN

	* dpas/dpas-parser.y, dpas/dpas-scope.h, dpas/dpas-semantics.h:
	introduce effective address based l-values into dpas.

2004-04-27  Rhys Weatherley  <rweather@southern-storm.com.au>

	* jit/jit-dump.c, jit/jit-reg-alloc.c: fix a register stack bug
	in "_jit_regs_set_value"; add some more debug code.

	* include/jit/jit-opcode.h, jit/jit-insn.c, jit/jit-internal.h,
	jit/jit-interp.cpp, jit/jit-opcode.c: wrap function calls
	with code to set up and remove exception frame information.

	* jit/jit-function.c, jit/jit-insn.c, jit/jit-internal.h:
	intuit "nothrow" and "noreturn" flags for compiled functions.

	* include/jit/jit-insn.h, include/jit/jit-plus.h, jit/jit-insn.c,
	jitplus/jit-plus-function.cpp: add "jit_insn_throw",
	"jit_insn_rethrow", and "jit_insn_get_call_stack" to assist
	with throwing exceptions.

	* include/jit/jit-insn.h, jit/jit-block.c, jit/jit-insn.c,

libjit/README  view on Meta::CPAN


Compiler notes
--------------

It is highly recommended that you build libjit with gcc and not
some other C compiler, even if you plan to use some other C
compiler to access the library.  We make use of a number of gcc
builtins to assist with stack walking, dynamic function calls,
and closures.

It is also recommended that you don't use the "-fomit-frame-pointer"
option when compiling programs that use libjit.  Otherwise stack walking
may not work correctly, leading to problems when throwing exceptions.
The configure script for libjit will detect the presence of this
option in CFLAGS and remove it when building libjit itself.

Contacting the authors
----------------------

The primary author is Rhys Weatherley at Southern Storm Software, Pty Ltd.
He can be reached via e-mail at "rweather@southern-storm.com.au".

libjit/attic/jit-apply-alpha.c  view on Meta::CPAN


#include "jit-gen-alpha.h"

void _jit_create_closure(unsigned char *buf, void *func, void *closure, void *_type) {
	alpha_inst inst = (alpha_inst) buf;

	/* Compute and load the global pointer (2 instructions) */
	alpha_ldah(inst,ALPHA_GP,ALPHA_PV,0);
	alpha_lda( inst,ALPHA_GP,ALPHA_GP,0);

	/* Allocate space for a new stack frame. (1 instruction) */
	alpha_lda(inst,ALPHA_SP,ALPHA_SP,-(13*8));

	/* Save the return address. (1 instruction) */
	alpha_stq(inst,ALPHA_RA,ALPHA_SP,0*8);

	/* Save integer register arguments as local variables (6 instructions) */
	alpha_stq(inst,ALPHA_A0,ALPHA_SP,1*8);
	alpha_stq(inst,ALPHA_A1,ALPHA_SP,2*8);
	alpha_stq(inst,ALPHA_A2,ALPHA_SP,3*8);
	alpha_stq(inst,ALPHA_A3,ALPHA_SP,4*8);

libjit/attic/jit-apply-alpha.c  view on Meta::CPAN

	alpha_ldt(inst,ALPHA_FA4,ALPHA_SP,11*8);
	alpha_ldt(inst,ALPHA_FA5,ALPHA_SP,12*8);

	/* restore the stack pointer (1 instruction) */
	alpha_lda(inst,ALPHA_SP,ALPHA_SP,(13*8));
}

void *_jit_create_redirector(unsigned char *buf, void *func, void *user_data, int abi) {
	alpha_inst inst = (alpha_inst) buf;

	/* Allocate space for a new stack frame. (1 instruction) */
	alpha_lda(inst,ALPHA_SP,ALPHA_SP,-(16*8));

	/* Save the return address. (1 instruction) */
	alpha_stq(inst,ALPHA_RA,ALPHA_SP,0*8);

	/* Save the frame pointer. (1 instruction) */
	alpha_stq(inst,ALPHA_FP,ALPHA_SP,1*8);

	/* Save the integer save registers (6 instructions) */
	alpha_stq(inst,ALPHA_S0,ALPHA_SP,2*8);
	alpha_stq(inst,ALPHA_S1,ALPHA_SP,3*8);
	alpha_stq(inst,ALPHA_S2,ALPHA_SP,4*8);
	alpha_stq(inst,ALPHA_S3,ALPHA_SP,5*8);
	alpha_stq(inst,ALPHA_S4,ALPHA_SP,6*8);
	alpha_stq(inst,ALPHA_S5,ALPHA_SP,7*8);

	/* Save the floating point save registers (8 instructions) */
	alpha_stt(inst,ALPHA_FS0,ALPHA_SP, 8*8);
	alpha_stt(inst,ALPHA_FS1,ALPHA_SP, 9*8);
	alpha_stt(inst,ALPHA_FS2,ALPHA_SP,10*8);
	alpha_stt(inst,ALPHA_FS3,ALPHA_SP,11*8);
	alpha_stt(inst,ALPHA_FS4,ALPHA_SP,12*8);
	alpha_stt(inst,ALPHA_FS5,ALPHA_SP,13*8);
	alpha_stt(inst,ALPHA_FS6,ALPHA_SP,14*8);
	alpha_stt(inst,ALPHA_FS7,ALPHA_SP,15*8);

	/* Set the frame pointer (1 instruction) */
	alpha_mov(inst,ALPHA_SP,ALPHA_FP);

	/* Compute and load the global pointer (2 instructions) */
	alpha_ldah(inst,ALPHA_GP,ALPHA_PV,0);
	alpha_lda( inst,ALPHA_GP,ALPHA_GP,0);

	/* Force any pending hardware exceptions to be raised. (1 instruction) */
	alpha_trapb(inst);

	/* Call the redirector handling function (6 instruction) */
	alpha_call(inst, func);

	/* Restore the return address. (1 instruction) */
	alpha_ldq(inst,ALPHA_RA,ALPHA_SP,0*8);

	/* Restore the frame pointer. (1 instruction) */
	alpha_ldq(inst,ALPHA_FP,ALPHA_SP,1*8);

	/* Restore the integer save registers (6 instructions) */
	alpha_ldq(inst,ALPHA_S0,ALPHA_SP,2*8);
	alpha_ldq(inst,ALPHA_S1,ALPHA_SP,3*8);
	alpha_ldq(inst,ALPHA_S2,ALPHA_SP,4*8);
	alpha_ldq(inst,ALPHA_S3,ALPHA_SP,5*8);
	alpha_ldq(inst,ALPHA_S4,ALPHA_SP,6*8);
	alpha_ldq(inst,ALPHA_S5,ALPHA_SP,7*8);

libjit/attic/jit-gen-alpha.h  view on Meta::CPAN

	ALPHA_R8 = 8,	ALPHA_T7 = ALPHA_R8,

	ALPHA_R9 = 9,	ALPHA_S0 = ALPHA_R9,	/* Saved registers */
	ALPHA_R10 = 10,	ALPHA_S1 = ALPHA_R10,
	ALPHA_R11 = 11,	ALPHA_S2 = ALPHA_R11,
	ALPHA_R12 = 12,	ALPHA_S3 = ALPHA_R12,
	ALPHA_R13 = 13,	ALPHA_S4 = ALPHA_R13,
	ALPHA_R14 = 14,	ALPHA_S5 = ALPHA_R14,

	ALPHA_R15 = 15,	ALPHA_S6 = ALPHA_R15,   /* ALPHA_R15 can hold either a saved value */
			ALPHA_FP = ALPHA_R15,   /* or the frame pointer                    */

	ALPHA_R16 = 16, ALPHA_A0 = ALPHA_R16,	/* First 6 arguments */
	ALPHA_R17 = 17,	ALPHA_A1 = ALPHA_R17,
	ALPHA_R18 = 18,	ALPHA_A2 = ALPHA_R18,
	ALPHA_R19 = 19,	ALPHA_A3 = ALPHA_R19,
	ALPHA_R20 = 20,	ALPHA_A4 = ALPHA_R20,
	ALPHA_R21 = 21,	ALPHA_A5 = ALPHA_R21,

	ALPHA_R22 = 22,	ALPHA_T8  = ALPHA_R22,	/* More temp registers */
	ALPHA_R23 = 23,	ALPHA_T9  = ALPHA_R23,

libjit/attic/jit-rules-alpha.c  view on Meta::CPAN

 * most compact prolog possible. 
 */
void *_jit_gen_prolog(jit_gencode_t gen, jit_function_t func, void *buf) {
	unsigned int prolog[JIT_PROLOG_SIZE];
	alpha_inst inst = prolog;

	/* Compute and load the global pointer (2 instruction) */
        alpha_ldah(inst,ALPHA_GP,ALPHA_PV,0);
        alpha_lda( inst,ALPHA_GP,ALPHA_GP,0);

	/* Allocate space for a new stack frame. (1 instruction) */
	alpha_lda(inst,ALPHA_SP,ALPHA_SP,-(2*8));

	/* Save the return address. (1 instruction) */
	alpha_stq(inst,ALPHA_RA,ALPHA_SP,0*8);

	/* Save the frame pointer. (1 instruction) */
	alpha_stq(inst,ALPHA_FP,ALPHA_SP,1*8);

	/* Set the frame pointer (1 instruction) */
	alpha_mov(inst,ALPHA_SP,ALPHA_FP);

	/* Force any pending hardware exceptions to be raised. (1 instruction) */
	alpha_trapb(inst);

	/* Copy the prolog into place and return the entry position */
	jit_memcpy(buf, prolog, JIT_PROLOG_SIZE);
	return (void *) buf;
}

libjit/attic/jit-rules-alpha.c  view on Meta::CPAN


		fixup    = next;
	}

	/* Set the stack pointer (1 instruction) */
	alpha_mov(inst,ALPHA_FP,ALPHA_SP);

	/* Restore the return address. (1 instruction) */
	alpha_ldq(inst,ALPHA_RA,ALPHA_SP,0*8);

	/* Restore the frame pointer. (1 instruction) */
	alpha_ldq(inst,ALPHA_FP,ALPHA_SP,1*8);

	/* Restore the stack pointer (1 instruction) */
	alpha_lda(inst,ALPHA_SP,ALPHA_SP,16*8);

	/* Force any pending hardware exceptions to be raised. (1 instruction) */
	alpha_trapb(inst);

	/* Return from the current function (1 instruction) */
	alpha_ret(inst,ALPHA_RA,1);

libjit/attic/jit-rules-alpha.c  view on Meta::CPAN


	return_type = jit_type_normalize(jit_type_get_return(signature));
	ptr_return  = jit_type_return_via_pointer(return_type);

	/* Bail out now if we don't need to worry about return values */
	if (!return_value || ptr_return) {
		return 0;
	}

	/*
	 * Structure values must be flushed into the frame, and
	 * everything else ends up in a register
	 */
	if (jit_type_is_struct(return_type) || jit_type_is_union(return_type)) {
		if (!jit_insn_flush_struct(func, return_value)) {
			return 0;
		}
	} else if (return_type->kind == JIT_TYPE_FLOAT32 || return_type->kind == JIT_TYPE_FLOAT64 || return_type->kind == JIT_TYPE_NFLOAT) {
		if (!jit_insn_return_reg(func, return_value, 32 /* fv0 */)) {
			return 0;
		}

libjit/attic/jit-rules-alpha.c  view on Meta::CPAN


void _jit_gen_spill_top(jit_gencode_t gen, int reg, jit_value_t value, int pop) {
	/* not used by alpha */;
}

void _jit_gen_spill_global(jit_gencode_t gen, int reg, jit_value_t value) {
	/* not used by alpha */;
}

/*
 * Generate instructions to spill a pseudo register to the local variable frame. If 
 * other_reg is not -1, then it indicates the second register in a 64-bit register pair.
 *
 * This function will typically call _jit_gen_fix_value to fix the value's frame 
 * position, and will then generate the appropriate spill instructions. 
 */
void _jit_gen_spill_reg(jit_gencode_t gen, int reg, int other_reg, jit_value_t value) {
	int offset;

	/* Make sure that we have sufficient space */
	jit_cache_setup_output(32);

	/* If the value is associated with a global register, then copy to that */
	if (value->has_global_register) {
		alpha_mov(inst,_jit_reg_info[reg].cpu_reg,_jit_reg_info[value->global_reg].cpu_reg);
		jit_cache_end_output();
		return;
	}

	/* Fix the value in place within the local variable frame */
	_jit_gen_fix_value(value);

	/* Output an appropriate instruction to spill the value */
	offset = (int)(value->frame_offset);

	if (reg < 32) {		/* if integer register */
		alpha_stq(inst,reg,ALPHA_FP,offset);
		if (other_reg != -1) {
			offset += sizeof(void *);
			alpha_stq(inst,other_reg,ALPHA_FP,offset);
		}
	} else /* floating point register */ {
		/* TODO requires floating point support */
	}

libjit/attic/jit-rules-alpha.c  view on Meta::CPAN


/*
 * Called to notify the back end that the end of a basic block has been reached.
 */
void _jit_gen_end_block(jit_gencode_t gen, jit_block_t block) {
	/* Nothing to do here */;
}

/*
 * Generate instructions to load a value into a register. The value will either be a 
 * constant or a slot in the frame. You should fix frame slots with 
 * _jit_gen_fix_value.
 */
void _jit_gen_load_value(jit_gencode_t gen, int reg, int other_reg, jit_value_t value) {
	short int offset;

	/* Make sure that we have sufficient space */
	jit_cache_setup_output(32);

	if (value->is_constant) {

libjit/attic/jit-rules-alpha.c  view on Meta::CPAN

				break;

		}
	} else if (value->in_register || value->in_global_register) {

		/* mov from value->reg to _jit_reg_info[reg].cpu_reg */
		alpha_mov(inst,value->reg,_jit_reg_info[reg].cpu_reg);

	} else {

		/* Fix the position of the value in the stack frame */
		_jit_gen_fix_value(value);
		offset = (int)(value->frame_offset);

		/* Load the value into the specified register */
		switch (jit_type_normalize(value->type)->kind) {

			case JIT_TYPE_SBYTE:
/* TODO add alpha_ldb		alpha_ldb(inst,_jit_reg_info[reg].cpu_reg,ALPHA_SP,offset);
 */				break;
			case JIT_TYPE_UBYTE:
				alpha_ldbu(inst,_jit_reg_info[reg].cpu_reg,ALPHA_SP,offset);
				break;

libjit/attic/jit-rules-alpha.c  view on Meta::CPAN

		#undef JIT_INCLUDE_RULES

		default:
			fprintf(stderr, "TODO(%x) at %s, %d\n", (int)(insn->opcode), __FILE__, (int)__LINE__);
			break;
	}
}

void _jit_gen_fix_value(jit_value_t value) {

	if (!(value->has_frame_offset) && !(value->is_constant)) {
		jit_nint size = (jit_nint)(ROUND_STACK(jit_type_get_size(value->type)));
		value->block->func->builder->frame_size += size;
		value->frame_offset = -(value->block->func->builder->frame_size);
		value->has_frame_offset = 1;
	}
}

/*
 * Output a branch instruction.
 */
void alpha_output_branch(jit_function_t func, alpha_inst inst, int opcode, jit_insn_t insn, int reg) {
	jit_block_t block;

	if (!(block = jit_block_from_label(func, (jit_label_t)(insn->dest))))

libjit/configure.ac  view on Meta::CPAN

AC_MSG_RESULT($JITNATIVEFLOAT)

dnl Check to see if we are using gcc or not.
if test x$GCC = xyes ; then
	CFLAGS="$CFLAGS -Wall"
fi
if test x$GXX = xyes ; then
	CXXFLAGS="$CXXFLAGS -Wall"
fi

dnl If CFLAGS contains "-fomit-frame-pointer", then remove it.
dnl We need to have frame pointers to perform stack walking.
case "x$CFLAGS" in
	*-fomit-frame-pointer*)
		CFLAGS=`echo "$CFLAGS" | sed 's/-fomit-frame-pointer//'` ;;
	*)	;;
esac
case "x$CXXFLAGS" in
	*-fomit-frame-pointer*)
		CXXFLAGS=`echo "$CXXFLAGS" | sed 's/-fomit-frame-pointer//'` ;;
	*)	;;
esac

dnl Add "-fno-omit-frame-pointer" to the CFLAGS because current gcc versions
dnl have no frame pointers by default on some archs.
if test x$GCC = xyes ; then
	CFLAGS="$CFLAGS -fno-omit-frame-pointer"
	CXXFLAGS="$CXXFLAGS -fno-omit-frame-pointer"
fi

dnl Find the option to use to turn on C++ exception handling.
AC_CACHE_CHECK(for C++ exception handling option, ac_cv_prog_cxx_exceptions,
[echo 'int main(int argc, char **argv){try { throw 1; } catch(int i) { return i; } return 0;}' > conftest.c
if test -z "`${CXX-c++} -o conftest conftest.c 2>&1`"; then
  ac_cv_prog_cxx_exceptions='none needed'
else
  if test -z "`${CXX-c++} -fexceptions -o conftest conftest.c 2>&1`"; then
    ac_cv_prog_cxx_exceptions=-fexceptions

libjit/doc/libjit.texi  view on Meta::CPAN

@end example

There is no need for the @code{jit_insn_return}, because the call
will never return to that point in the code.  Behind the scenes,
@code{libjit} will convert the call into a jump back to the head
of the function.

Tail calls can only be used in certain circumstances.  The source
and destination of the call must have the same function signatures.
None of the parameters should point to local variables in the current
stack frame.  And tail calls cannot be used from any source function
that uses @code{try} or @code{alloca} statements.

Because it can be difficult for @code{libjit} to determine when these
conditions have been met, it relies upon the caller to supply the
@code{JIT_CALL_TAIL} flag when it is appropriate to use a tail call.

@c -----------------------------------------------------------------------

@node Dynamic Pascal, Initialization, Tutorial 5, Tutorials
@section Dynamic Pascal - A full JIT example

libjit/include/jit/jit-arch-arm.h  view on Meta::CPAN

 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with the libjit library.  If not, see
 * <http://www.gnu.org/licenses/>.
 */

#ifndef	_JIT_ARCH_ARM_H
#define	_JIT_ARCH_ARM_H

/*
 * If defined _JIT_ARCH_GET_CURRENT_FRAME() macro assigns the current frame
 * pointer to the supplied argument that has to be a void pointer.
 */
#if defined(__GNUC__)
#define _JIT_ARCH_GET_CURRENT_FRAME(f)		\
	do {					\
		register void *__f asm("fp");	\
		f = __f;			\
	} while(0)
#else
#undef _JIT_ARCH_GET_CURRENT_FRAME

libjit/include/jit/jit-arch-generic.h  view on Meta::CPAN

 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with the libjit library.  If not, see
 * <http://www.gnu.org/licenses/>.
 */

#ifndef	_JIT_ARCH_GENERIC_H
#define	_JIT_ARCH_GENERIC_H

/*
 * If defined _JIT_ARCH_GET_CURRENT_FRAME() macro assigns the current frame
 * pointer to the supplied argument that has to be a void pointer.
 */
#undef _JIT_ARCH_GET_CURRENT_FRAME

/*
 * If defined _JIT_ARCH_GET_NEXT_FRAME() assigns the frame address following
 * the frame supplied as second arg to the value supplied as first argument.
 */
#undef _JIT_ARCH_GET_NEXT_FRAME

/*
 * If defined _JIT_ARCH_GET_RETURN_ADDRESS() assigns the return address of
 * the frame supplied as second arg to the value supplied as first argument.
 */
#undef _JIT_ARCH_GET_RETURN_ADDRESS

/*
 * If defined _JIT_ARCH_GET_CURRENT_RETURN() assigns the return address of
 * the current to the supplied argument.
 */
#define _JIT_ARCH_GET_CURRENT_RETURN

#endif /* _JIT_ARCH_GENERIC_H */

libjit/include/jit/jit-arch-x86-64.h  view on Meta::CPAN

 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with the libjit library.  If not, see
 * <http://www.gnu.org/licenses/>.
 */

#ifndef	_JIT_ARCH_X86_64_H
#define	_JIT_ARCH_X86_64_H

/*
 * The frame header structure for X86_64
 */
typedef struct _jit_arch_frame _jit_arch_frame_t;
struct _jit_arch_frame
{
	_jit_arch_frame_t *next_frame;
	void *return_address;
};

/*
 * If defined _JIT_ARCH_GET_CURRENT_FRAME() macro assigns the current frame
 * pointer to the supplied argument that has to be a void pointer.
 */
#if defined(__GNUC__)
#define _JIT_ARCH_GET_CURRENT_FRAME(f)		\
	do {					\
		register void *__f asm("rbp");	\
		f = __f;			\
	} while(0)
#elif defined(_MSC_VER) && defined(_M_IX86)
#define	_JIT_ARCH_GET_CURRENT_FRAME(f)		\

libjit/include/jit/jit-arch-x86-64.h  view on Meta::CPAN

		{				\
			__asm mov qword ptr __ptr, rbp	\
		}				\
		(f) = __ptr;			\
	} while(0)
#else
#undef _JIT_ARCH_GET_CURRENT_FRAME
#endif

/*
 * If defined _JIT_ARCH_GET_NEXT_FRAME() assigns the frame address following
 * the frame supplied as second arg to the value supplied as first argument.
 */
#define _JIT_ARCH_GET_NEXT_FRAME(n, f)							\
	do {										\
		(n) = (void *)((f) ? ((_jit_arch_frame_t *)(f))->next_frame : 0);	\
	} while(0)

/*
 * If defined _JIT_ARCH_GET_RETURN_ADDRESS() assigns the return address of
 * the frame supplied as second arg to the value supplied as first argument.
 */
#define _JIT_ARCH_GET_RETURN_ADDRESS(r, f)						\
	do {										\
		(r) = (void *)((f) ? ((_jit_arch_frame_t *)(f))->return_address : 0);	\
	} while(0)

/*
 * If defined _JIT_ARCH_GET_CURRENT_RETURN() assigns the return address of
 * the current to the supplied argument.
 */
#define _JIT_ARCH_GET_CURRENT_RETURN(r)				\
	do {							\
		void *__frame;					\
		_JIT_ARCH_GET_CURRENT_FRAME(__frame);		\
		_JIT_ARCH_GET_RETURN_ADDRESS((r), __frame);	\
	} while(0)

#endif /* _JIT_ARCH_X86_64_H */

libjit/include/jit/jit-arch-x86.h  view on Meta::CPAN

 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with the libjit library.  If not, see
 * <http://www.gnu.org/licenses/>.
 */

#ifndef	_JIT_ARCH_X86_H
#define	_JIT_ARCH_X86_H

/*
 * If defined _JIT_ARCH_GET_CURRENT_FRAME() macro assigns the current frame
 * pointer to the supplied argument that has to be a void pointer.
 */
#if defined(__GNUC__)
#define _JIT_ARCH_GET_CURRENT_FRAME(f)		\
	do {					\
		register void *__f asm("ebp");	\
		f = __f;			\
	} while(0)
#elif defined(_MSC_VER) && defined(_M_IX86)
#define	_JIT_ARCH_GET_CURRENT_FRAME(f)		\

libjit/include/jit/jit-insn.h  view on Meta::CPAN

jit_value_t jit_insn_call_native
	(jit_function_t func, const char *name,
	 void *native_func, jit_type_t signature,
	 jit_value_t *args, unsigned int num_args, int flags) JIT_NOTHROW;
jit_value_t jit_insn_call_intrinsic
	(jit_function_t func, const char *name, void *intrinsic_func,
	 const jit_intrinsic_descr_t *descriptor,
	 jit_value_t arg1, jit_value_t arg2) JIT_NOTHROW;
int jit_insn_incoming_reg
	(jit_function_t func, jit_value_t value, int reg) JIT_NOTHROW;
int jit_insn_incoming_frame_posn
	(jit_function_t func, jit_value_t value, jit_nint frame_offset) JIT_NOTHROW;
int jit_insn_outgoing_reg
	(jit_function_t func, jit_value_t value, int reg) JIT_NOTHROW;
int jit_insn_outgoing_frame_posn
	(jit_function_t func, jit_value_t value, jit_nint frame_offset) JIT_NOTHROW;
int jit_insn_return_reg
	(jit_function_t func, jit_value_t value, int reg) JIT_NOTHROW;
int jit_insn_setup_for_nested
	(jit_function_t func, int nested_level, int reg) JIT_NOTHROW;
int jit_insn_flush_struct(jit_function_t func, jit_value_t value) JIT_NOTHROW;
jit_value_t jit_insn_import
	(jit_function_t func, jit_value_t value) JIT_NOTHROW;
int jit_insn_push(jit_function_t func, jit_value_t value) JIT_NOTHROW;
int jit_insn_push_ptr
	(jit_function_t func, jit_value_t value, jit_type_t type) JIT_NOTHROW;

libjit/include/jit/jit-plus.h  view on Meta::CPAN

		(const jit_value& value, jit_type_t signature,
	 	 jit_value_t *args, unsigned int num_args, int flags=0);
	jit_value insn_call_native
		(const char *name, void *native_func, jit_type_t signature,
	     jit_value_t *args, unsigned int num_args, int flags=0);
	jit_value insn_call_intrinsic
		(const char *name, void *intrinsic_func,
	 	 const jit_intrinsic_descr_t& descriptor,
		 const jit_value& arg1, const jit_value& arg2);
	void insn_incoming_reg(const jit_value& value, int reg);
	void insn_incoming_frame_posn(const jit_value& value, jit_nint posn);
	void insn_outgoing_reg(const jit_value& value, int reg);
	void insn_outgoing_frame_posn(const jit_value& value, jit_nint posn);
	void insn_return_reg(const jit_value& value, int reg);
	void insn_setup_for_nested(int nested_level, int reg);
	void insn_flush_struct(const jit_value& value);
	jit_value insn_import(jit_value value);
	void insn_push(const jit_value& value);
	void insn_push_ptr(const jit_value& value, jit_type_t type);
	void insn_set_param(const jit_value& value, jit_nint offset);
	void insn_set_param_ptr
		(const jit_value& value, jit_type_t type, jit_nint offset);
	void insn_push_return_area_ptr();

libjit/include/jit/jit-unwind.h  view on Meta::CPAN


#include <jit/jit-common.h>
#include <jit/jit-arch.h>

#ifdef	__cplusplus
extern	"C" {
#endif

typedef struct
{
	void *frame;
	void *cache;
	jit_context_t context;
#ifdef _JIT_ARCH_UNWIND_DATA
	_JIT_ARCH_UNWIND_DATA
#endif
} jit_unwind_context_t;

int jit_unwind_init(jit_unwind_context_t *unwind, jit_context_t context);
void jit_unwind_free(jit_unwind_context_t *unwind);

libjit/include/jit/jit-walk.h  view on Meta::CPAN

/*
 * jit-walk.h - Functions for walking stack frames.
 *
 * Copyright (C) 2004  Southern Storm Software, Pty Ltd.
 *
 * The libjit library is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation, either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * The libjit library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of

libjit/include/jit/jit-walk.h  view on Meta::CPAN

#ifndef	_JIT_WALK_H
#define	_JIT_WALK_H

#include <jit/jit-arch.h>

#ifdef	__cplusplus
extern	"C" {
#endif

/*
 * Get the frame address for a frame which is "n" levels up the stack.
 * A level value of zero indicates the current frame.
 */
void *_jit_get_frame_address(void *start, unsigned int n);
#if defined(__GNUC__)
# define jit_get_frame_address(n)	\
	(_jit_get_frame_address(jit_get_current_frame(), (n)))
#else
# define jit_get_frame_address(n)	(_jit_get_frame_address(0, (n)))
#endif

/*
 * Get the frame address for the current frame.  May be more efficient
 * than using "jit_get_frame_address(0)".
 *
 * Note: some gcc vestions have broken __builtin_frame_address() so use
 * _JIT_ARCH_GET_CURRENT_FRAME() if available. 
 */
#if defined(__GNUC__)
# define JIT_FAST_GET_CURRENT_FRAME	1
# if defined(_JIT_ARCH_GET_CURRENT_FRAME)
#  define jit_get_current_frame()			\
	({						\
		void *address;				\
		_JIT_ARCH_GET_CURRENT_FRAME(address);	\
		address;				\
	})
# else
#  define jit_get_current_frame()	(__builtin_frame_address(0))
# endif
#else
# define JIT_FAST_GET_CURRENT_FRAME	0
# define jit_get_current_frame()	(jit_get_frame_address(0))
#endif

/*
 * Get the next frame up the stack from a specified frame.
 * Returns NULL if it isn't possible to retrieve the next frame.
 */
void *_jit_get_next_frame_address(void *frame);
#if defined(__GNUC__) && defined(_JIT_ARCH_GET_NEXT_FRAME)
# define jit_get_next_frame_address(frame)			\
	({							\
		void *address;					\
		_JIT_ARCH_GET_NEXT_FRAME(address, (frame));	\
		address;					\
	})
#else
# define jit_get_next_frame_address(frame)	\
	(_jit_get_next_frame_address(frame))
#endif

/*
 * Get the return address for a specific frame.
 */
void *_jit_get_return_address(void *frame, void *frame0, void *return0);
#if defined(__GNUC__)
# if defined(_JIT_ARCH_GET_RETURN_ADDRESS)
#  define jit_get_return_address(frame)				\
	({							\
		void *address;					\
		_JIT_ARCH_GET_RETURN_ADDRESS(address, (frame));	\
		address;					\
	})
# else
#  define jit_get_return_address(frame)			\
	(_jit_get_return_address			\
		((frame),				\
		 __builtin_frame_address(0),		\
		 __builtin_return_address(0)))
# endif
#else
# define jit_get_return_address(frame)	\
	(_jit_get_return_address((frame), 0, 0))
#endif

/*
 * Get the return address for the current frame.  May be more efficient
 * than using "jit_get_return_address(0)".
 */
#if defined(__GNUC__)
# if defined(_JIT_ARCH_GET_CURRENT_RETURN)
#  define jit_get_current_return()			\
	({						\
		void *address;				\
		_JIT_ARCH_GET_CURRENT_RETURN(address);	\
		address;				\
	})
# else
#  define jit_get_current_return()	(__builtin_return_address(0))
# endif
#else
# define jit_get_current_return()	\
	(jit_get_return_address(jit_get_current_frame()))
#endif

/*
 * Declare a stack crawl mark variable.  The address of this variable
 * can be passed to "jit_frame_contains_crawl_mark" to determine
 * if a frame contains the mark.
 */
typedef struct { void * volatile mark; } jit_crawl_mark_t;
#define	jit_declare_crawl_mark(name)	jit_crawl_mark_t name = {0}

/*
 * Determine if the stack frame just above "frame" contains a
 * particular crawl mark.
 */
int jit_frame_contains_crawl_mark(void *frame, jit_crawl_mark_t *mark);

#ifdef	__cplusplus
};
#endif

#endif /* _JIT_WALK_H */

libjit/jit/jit-apply-arm.c  view on Meta::CPAN

#include "jit-gen-arm.h"

void _jit_create_closure(unsigned char *buf, void *func,
                         void *closure, void *_type)
{
	arm_inst_buf inst;

	/* Initialize the instruction buffer */
	arm_inst_buf_init(inst, buf, buf + jit_closure_size);

	/* Set up the local stack frame */
	arm_setup_frame(inst, 0);
	arm_alu_reg_imm8(inst, ARM_SUB, ARM_SP, ARM_SP, 24);

	/* Create the apply argument block on the stack */
	arm_store_membase(inst, ARM_R0, ARM_FP, -28);
	arm_store_membase(inst, ARM_R1, ARM_FP, -24);
	arm_store_membase(inst, ARM_R2, ARM_FP, -20);
	arm_store_membase(inst, ARM_R3, ARM_FP, -16);
	arm_alu_reg_imm(inst, ARM_ADD, ARM_R3, ARM_FP, 4);
	arm_store_membase(inst, ARM_R3, ARM_FP, -36);
	arm_store_membase(inst, ARM_R0, ARM_FP, -32);

	/* Set up the arguments for calling "func" */
	arm_mov_reg_imm(inst, ARM_R0, (int)(jit_nint)closure);
	arm_mov_reg_reg(inst, ARM_R1, ARM_SP);

	/* Call the closure handling function */
	arm_call(inst, func);

	/* Pop the current stack frame and return */
	arm_pop_frame(inst, 0);
}

void *_jit_create_redirector(unsigned char *buf, void *func,
							 void *user_data, int abi)
{
	arm_inst_buf inst;

	/* Align "buf" on an appropriate boundary */
	if((((jit_nint)buf) % jit_closure_align) != 0)
	{
		buf += jit_closure_align - (((jit_nint)buf) % jit_closure_align);
	}

	/* Initialize the instruction buffer */
	arm_inst_buf_init(inst, buf, buf + jit_redirector_size);

	/* Set up the local stack frame, and save R0-R3 */
	arm_setup_frame(inst, 0x000F);

	/* Set up the arguments for calling "func" */
	arm_mov_reg_imm(inst, ARM_R0, (int)(jit_nint)user_data);

	/* Call the redirector handling function */
	arm_call(inst, func);

	/* Shift the result into R12, because we are about to restore R0 */
	arm_mov_reg_reg(inst, ARM_R12, ARM_R0);

	/* Pop the current stack frame, but don't change PC yet */
	arm_pop_frame_tail(inst, 0x000F);

	/* Jump to the function that the redirector indicated */
	arm_mov_reg_reg(inst, ARM_PC, ARM_R12);

	/* Flush the cache lines that we just wrote */
	_jit_flush_exec(buf, ((unsigned char *)(inst.current)) - buf);

	/* Return the aligned start of the buffer as the entry point */
	return (void *)buf;
}

libjit/jit/jit-apply-x86-64.c  view on Meta::CPAN

#define X86_64_ARG_IS_SSE(arg)	(((arg) & 0x10) != 0)
#define X86_64_ARG_IS_X87(arg)	(((arg) & 0x20) != 0)


void _jit_create_closure(unsigned char *buf, void *func,
                         void *closure, void *_type)
{
	jit_nint offset;
	jit_type_t signature = (jit_type_t)_type;

	/* Set up the local stack frame */
	x86_64_push_reg_size(buf, X86_64_RBP, 8);
	x86_64_mov_reg_reg_size(buf, X86_64_RBP, X86_64_RSP, 8);

	/* Create the apply argument block on the stack */
	x86_64_sub_reg_imm_size(buf, X86_64_RSP, 192, 8);

	/* fill the apply buffer */
	x86_64_mov_membase_reg_size(buf, X86_64_RSP, 0x08, X86_64_RDI, 8);
	x86_64_mov_membase_reg_size(buf, X86_64_RSP, 0x10, X86_64_RSI, 8);
	x86_64_mov_membase_reg_size(buf, X86_64_RSP, 0x18, X86_64_RDX, 8);

libjit/jit/jit-apply-x86-64.c  view on Meta::CPAN

		/* We use R11 here because it's the only temporary caller saved */
		/* register not used for argument passing. */
		x86_64_mov_reg_imm_size(buf, X86_64_R11, (jit_nint)func, 8);
		x86_64_call_reg(buf, X86_64_R11);
	}
	else
	{
		x86_64_call_imm(buf, (jit_int)offset);
	}

	/* Pop the current stack frame */
	x86_64_mov_reg_reg_size(buf, X86_64_RSP, X86_64_RBP, 8);
	x86_64_pop_reg_size(buf, X86_64_RBP, 8);

	/* Return from the closure */
	x86_64_ret(buf);
}

void *_jit_create_redirector(unsigned char *buf, void *func,
							 void *user_data, int abi)
{

libjit/jit/jit-apply-x86-64.c  view on Meta::CPAN

				/* Set the first register to the register used */
				param->un.reg_info[0].reg = passing->word_regs[passing->word_index];
				param->un.reg_info[0].value = param->value;
				++(passing->word_index);
			}
			else
			{
				/* Set the arg class to stack */
				param->arg_class = JIT_ARG_CLASS_STACK;

				/* Allocate the slot in the arg passing frame */
				_jit_alloc_param_slot(passing, param, param_type);
			}			
		}
		else if(arg_class == X86_64_ARG_SSE)
		{
			if(passing->float_index < passing->max_float_regs)
			{
				/* Set the arg class to the number of registers used */
				param->arg_class = 1;

				/* Set the first register to the register used */
				param->un.reg_info[0].reg =	passing->float_regs[passing->float_index];
				param->un.reg_info[0].value = param->value;
				++(passing->float_index);
			}
			else
			{
				/* Set the arg class to stack */
				param->arg_class = JIT_ARG_CLASS_STACK;

				/* Allocate the slot in the arg passing frame */
				_jit_alloc_param_slot(passing, param, param_type);
			}
		}
		else
		{
			/* Set the arg class to stack */
			param->arg_class = JIT_ARG_CLASS_STACK;

			/* Allocate the slot in the arg passing frame */
			_jit_alloc_param_slot(passing, param, param_type);
		}
	}
	else if(size <= 16)
	{
		int arg_class1;
		int arg_class2;

		arg_class1 = _jit_classify_structpart(param_type, 0, 0, 7);
		arg_class2 = _jit_classify_structpart(param_type, 0, 8, size - 1);

libjit/jit/jit-apply-x86-64.c  view on Meta::CPAN

				/* Set the first register to the register used */
				param->un.reg_info[0].reg =	passing->float_regs[passing->float_index];
				param->un.reg_info[0].value = param->value;
				++(passing->float_index);
			}
			else
			{
				/* Set the arg class to stack */
				param->arg_class = JIT_ARG_CLASS_STACK;

				/* Allocate the slot in the arg passing frame */
				_jit_alloc_param_slot(passing, param, param_type);
			}
		}
		else if(arg_class1 == X86_64_ARG_MEMORY ||
				arg_class2 == X86_64_ARG_MEMORY)
		{
			/* Set the arg class to stack */
			param->arg_class = JIT_ARG_CLASS_STACK;

			/* Allocate the slot in the arg passing frame */
			_jit_alloc_param_slot(passing, param, param_type);
		}
		else if(arg_class1 == X86_64_ARG_INTEGER &&
				arg_class2 == X86_64_ARG_INTEGER)
		{
			/* We need two general purpose registers in this case */
			if((passing->word_index + 1) < passing->max_word_regs)
			{
				/* Set the arg class to the number of registers used */
				param->arg_class = 2;

libjit/jit/jit-apply-x86-64.c  view on Meta::CPAN

				param->un.reg_info[0].reg = passing->word_regs[passing->word_index];
				++(passing->word_index);
				param->un.reg_info[1].reg = passing->word_regs[passing->word_index];
				++(passing->word_index);
			}
			else
			{
				/* Set the arg class to stack */
				param->arg_class = JIT_ARG_CLASS_STACK;

				/* Allocate the slot in the arg passing frame */
				_jit_alloc_param_slot(passing, param, param_type);
			}			
		}
		else
		{
			/* We need one xmm and one general purpose register */
			if((passing->word_index < passing->max_word_regs) &&
			   (passing->float_index < passing->max_float_regs))
			{
				/* Set the arg class to the number of registers used */

libjit/jit/jit-apply-x86-64.c  view on Meta::CPAN

					++(passing->float_index);
					param->un.reg_info[1].reg = passing->word_regs[passing->word_index];
					++(passing->word_index);
				}
			}
			else
			{
				/* Set the arg class to stack */
				param->arg_class = JIT_ARG_CLASS_STACK;

				/* Allocate the slot in the arg passing frame */
				_jit_alloc_param_slot(passing, param, param_type);
			}
		}
	}
	else
	{
		/* Set the arg class to stack */
		param->arg_class = JIT_ARG_CLASS_STACK;

		/* Allocate the slot in the arg passing frame */
		_jit_alloc_param_slot(passing, param, param_type);
	}
	return 1;
}

int
_jit_classify_param(jit_param_passing_t *passing,
					_jit_param_t *param, jit_type_t param_type)
{
	if(is_struct_or_union(param_type))

libjit/jit/jit-apply-x86-64.c  view on Meta::CPAN

					/* Set the first register to the register used */
					param->un.reg_info[0].reg = passing->word_regs[passing->word_index];
					param->un.reg_info[0].value = param->value;
					++(passing->word_index);
				}
				else
				{
					/* Set the arg class to stack */
					param->arg_class = JIT_ARG_CLASS_STACK;

					/* Allocate the slot in the arg passing frame */
					_jit_alloc_param_slot(passing, param, param_type);
				}
			}
			break;

			case X86_64_ARG_SSE:
			{
				if(passing->float_index < passing->max_float_regs)
				{
					/* Set the arg class to the number of registers used */

libjit/jit/jit-apply-x86-64.c  view on Meta::CPAN

					/* Set the first register to the register used */
					param->un.reg_info[0].reg =	passing->float_regs[passing->float_index];
					param->un.reg_info[0].value = param->value;
					++(passing->float_index);
				}
				else
				{
					/* Set the arg class to stack */
					param->arg_class = JIT_ARG_CLASS_STACK;

					/* Allocate the slot in the arg passing frame */
					_jit_alloc_param_slot(passing, param, param_type);
				}
			}
			break;

			case X86_64_ARG_MEMORY:
			{
				/* Set the arg class to stack */
				param->arg_class = JIT_ARG_CLASS_STACK;

				/* Allocate the slot in the arg passing frame */
				_jit_alloc_param_slot(passing, param, param_type);
			}
			break;
		}
	}
	return 1;
}

void
_jit_builtin_apply_add_struct(jit_apply_builder *builder,

libjit/jit/jit-apply-x86.c  view on Meta::CPAN

                         void *closure, void *_type)
{
	jit_type_t signature = (jit_type_t)_type;
	jit_type_t type;
#if JIT_APPLY_X86_FASTCALL == 1
	jit_abi_t abi = jit_type_get_abi(signature);
#endif
	unsigned int num_bytes = 0;
	int struct_return_offset = 0;

	/* Set up the local stack frame */
	x86_push_reg(buf, X86_EBP);
	x86_mov_reg_reg(buf, X86_EBP, X86_ESP, 4);

	/* Create the apply argument block on the stack */
#if JIT_APPLY_X86_FASTCALL == 1
	if(abi == jit_abi_fastcall)
	{
		x86_push_reg(buf, X86_EDX);
		x86_push_reg(buf, X86_ECX);
	}

libjit/jit/jit-apply-x86.c  view on Meta::CPAN

		}
	}

	/* If we are returning a structure via a pointer, then load
	   the address of the structure into the EAX register */
	if(struct_return_offset != 0)
	{
		x86_mov_reg_membase(buf, X86_EAX, X86_EBP, struct_return_offset, 4);
	}

	/* Pop the current stack frame */
	x86_mov_reg_reg(buf, X86_ESP, X86_EBP, 4);
	x86_pop_reg(buf, X86_EBP);

	/* Return from the closure */
	if(num_bytes > 0)
	{
		x86_ret_imm(buf, num_bytes);
	}
	else
	{

libjit/jit/jit-compile.c  view on Meta::CPAN

			/* Assign a register to an incoming value */
			_jit_regs_set_incoming(gen,
					       (int)jit_value_get_nint_constant(insn->value2),
					       insn->value1);
			/* Generate code for the instruction with the back end */
			_jit_gen_insn(gen, func, block, insn);
			break;
#endif

		case JIT_OP_INCOMING_FRAME_POSN:
			/* Set the frame position for an incoming value */
			insn->value1->frame_offset = jit_value_get_nint_constant(insn->value2);
			insn->value1->in_register = 0;
			insn->value1->has_frame_offset = 1;
			if(insn->value1->has_global_register)
			{
				insn->value1->in_global_register = 1;
				_jit_gen_load_global(gen, insn->value1->global_reg, insn->value1);
			}
			else
			{
				insn->value1->in_frame = 1;
			}
			break;

#ifndef JIT_BACKEND_INTERP
		case JIT_OP_OUTGOING_REG:
			/* Copy a value into an outgoing register */
			_jit_regs_set_outgoing(gen,
					       (int)jit_value_get_nint_constant(insn->value2),
					       insn->value1);
			break;
#endif

		case JIT_OP_OUTGOING_FRAME_POSN:
			/* Set the frame position for an outgoing value */
			insn->value1->frame_offset = jit_value_get_nint_constant(insn->value2);
			insn->value1->in_register = 0;
			insn->value1->in_global_register = 0;
			insn->value1->in_frame = 0;
			insn->value1->has_frame_offset = 1;
			insn->value1->has_global_register = 0;
			break;

#ifndef JIT_BACKEND_INTERP
		case JIT_OP_RETURN_REG:
			/* Assign a register to a return value */
			_jit_regs_set_incoming(gen,
					       (int)jit_value_get_nint_constant(insn->value2),
					       insn->value1);
			/* Generate code for the instruction with the back end */

libjit/jit/jit-compile.c  view on Meta::CPAN


/*
 * Reset value on codegen restart.
 */
static void
reset_value(jit_value_t value)
{
	value->reg = -1;
	value->in_register = 0;
	value->in_global_register = 0;
	value->in_frame = 0;
}

/*
 * Clean up the compilation state on codegen restart.
 */
static void
cleanup_on_restart(jit_gencode_t gen, jit_function_t func)
{
	jit_block_t block;
	jit_insn_iter_t iter;

libjit/jit/jit-compile.c  view on Meta::CPAN

				reset_value(insn->value2);
			}
		}
	}

	/* Reset values referred to by builder */
	if(func->builder->setjmp_value)
	{
		reset_value(func->builder->setjmp_value);
	}
	if(func->builder->parent_frame)
	{
		reset_value(func->builder->parent_frame);
	}

	/* Reset the "touched" registers mask. The first time compilation
	   might have followed wrong code paths and thus allocated wrong
	   registers. */
	if(func->builder->has_tail_call)
	{
		/* For functions with tail calls _jit_regs_alloc_global()
		   does not allocate any global registers. The "permanent"
		   mask has all global registers set to prevent their use. */

libjit/jit/jit-compile.c  view on Meta::CPAN


#ifndef JIT_BACKEND_INTERP
		/* Clear the local register assignments */
		_jit_regs_init_for_block(gen);
#endif

		/* Generate the block's code */
		compile_block(gen, func, block);

#ifndef JIT_BACKEND_INTERP
		/* Spill all live register values back to their frame positions */
		_jit_regs_spill_all(gen);
#endif

		/* Notify the back end that the block is finished */
		_jit_gen_end_block(gen, block);
	}

	/* Output the function epilog.  All return paths will jump to here */
	_jit_gen_epilog(gen, func);

libjit/jit/jit-dump.c  view on Meta::CPAN

			{
				name = "<unknown-constant>";
			}
			break;
		}
		fputs(name, stream);
		return;
	}
	else if(value->is_local && value->block->func != func)
	{
		/* Accessing a local variable in an outer function frame */
		int scope = 0;
		while(func && func->builder && func != value->block->func)
		{
			++scope;
			func = func->nested_parent;
		}
		fprintf(stream, "{%d}", scope);
		if(!func || !(func->builder))
		{
			return;

libjit/jit/jit-dump.c  view on Meta::CPAN

	num_params = jit_type_num_params(signature);
	if(func->builder)
	{
		value = jit_value_get_struct_pointer(func);
		if(value || func->nested_parent)
		{
			/* We have extra hidden parameters */
			putc('[', stream);
			if(func->nested_parent)
			{
				fputs("parent_frame", stream);
				if(value)
				{
					fputs(", ", stream);
				}
			}
			if(value)
			{
				jit_dump_value(stream, func, value, 0);
				fputs(" : struct_ptr", stream);
			}

libjit/jit/jit-dump.c  view on Meta::CPAN

	{
		void *start = func->entry_point;
		void *info = _jit_memory_find_function_info(func->context, start);
		void *end = _jit_memory_get_function_end(func->context, info);
#if defined(JIT_BACKEND_INTERP)
		/* Dump the interpreter's bytecode representation */
		jit_function_interp_t interp;
		interp = (jit_function_interp_t)(func->entry_point);
		fprintf(stream, "\t%08lX: prolog(0x%lX, %d, %d, %d)\n",
				(long)(jit_nint)interp, (long)(jit_nint)func,
				(int)(interp->args_size), (int)(interp->frame_size),
				(int)(interp->working_area));
		dump_interp_code(stream, (void **)(interp + 1), (void **)end);
#else
		dump_object_code(stream, start, end);
#endif
	}

	/* Output the function footer */
	fprintf(stream, "end\n\n");
	fflush(stream);

libjit/jit/jit-elf-defs.h  view on Meta::CPAN

#define	PT_NULL		0		/* Program header table entry unused */
#define PT_LOAD		1		/* Loadable program segment */
#define PT_DYNAMIC	2		/* Dynamic linking information */
#define PT_INTERP	3		/* Program interpreter */
#define PT_NOTE		4		/* Auxiliary information */
#define PT_SHLIB	5		/* Reserved */
#define PT_PHDR		6		/* Entry for header table itself */
#define PT_TLS		7		/* Thread-local storage segment */
#define	PT_NUM		8		/* Number of defined types */
#define PT_LOOS		0x60000000	/* Start of OS-specific */
#define PT_GNU_EH_FRAME 0x6474e550	/* GCC .eh_frame_hdr segment */
#define PT_HIOS		0x6fffffff	/* End of OS-specific */
#define PT_LOPROC	0x70000000	/* Start of processor-specific */
#define PT_HIPROC	0x7fffffff	/* End of processor-specific */

/* Legal values for p_flags (segment flags).  */

#define PF_X		(1 << 0)	/* Segment is executable */
#define PF_W		(1 << 1)	/* Segment is writable */
#define PF_R		(1 << 2)	/* Segment is readable */
#define PF_MASKOS	0x0ff00000	/* OS-specific */

libjit/jit/jit-gen-arm.h  view on Meta::CPAN

 * Pop a register from the system stack.
 */
#define	arm_pop_reg(inst,reg)	\
			do { \
				arm_inst_add((inst), arm_prefix(0x04900004) | \
							(((unsigned int)ARM_SP) << 16) | \
							(((unsigned int)(reg)) << 12)); \
			} while (0)

/*
 * Pop the top of the system stack and put it at a given offset from the position specified by basereg (that is, usually, the frame pointer). NB: This macro thrashes the content of ARM_WORK
 */
#define arm_pop_membase(inst,basereg,offset)	\
			do {	\
				arm_pop_reg((inst), ARM_WORK);	\
				arm_store_membase((inst),ARM_WORK,basereg,offset);	\
			} while (0)
			
/*
 * Set up a local variable frame, and save the registers in "regset".
 */
#define	arm_setup_frame(inst,regset)	\
			do { \
				arm_mov_reg_reg((inst), ARM_WORK, ARM_SP); \
				arm_inst_add((inst), arm_prefix(0x0920D800) | \
							(((unsigned int)ARM_SP) << 16) | \
							(((unsigned int)(regset)))); \
				arm_alu_reg_imm8((inst), ARM_SUB, ARM_FP, ARM_WORK, 4); \
			} while (0)

/*
 * Pop a local variable frame, restore the registers in "regset",
 * and return to the caller.
 */
#define	arm_pop_frame(inst,regset)	\
			do { \
				arm_inst_add((inst), arm_prefix(0x0910A800) | \
							(((unsigned int)ARM_FP) << 16) | \
							(((unsigned int)(regset)))); \
			} while (0)

/*
 * Pop a local variable frame, in preparation for a tail call.
 * This restores "lr" to its original value, but does not set "pc".
 */
#define	arm_pop_frame_tail(inst,regset)	\
			do { \
				arm_inst_add((inst), arm_prefix(0x09106800) | \
							(((unsigned int)ARM_FP) << 16) | \
							(((unsigned int)(regset)))); \
			} while (0)

/*
 * Load a word value from a pointer and then advance the pointer.
 */
#define	arm_load_advance(inst,dreg,sreg)	\

libjit/jit/jit-gen-x86.h  view on Meta::CPAN

// Frame structure:
//
//      +--------------------------------+
//      | in_arg[0]       = var[0]	     |
//      | in_arg[1]	      = var[1]	     |
//      |	      . . .			         |
//      | in_arg[n_arg-1] = var[n_arg-1] |
//      +--------------------------------+
//      |       return IP                |
//      +--------------------------------+
//      |       saved EBP                | <-- frame pointer (EBP)
//      +--------------------------------+
//      |            ...                 |  n_extra
//      +--------------------------------+
//      |	    var[n_arg]	             |
//      |	    var[n_arg+1]             |  local variables area
//      |          . . .                 |
//      |	    var[n_var-1]             | 
//      +--------------------------------+
//      |			                     |
//      |			                     |  

libjit/jit/jit-gen-x86.h  view on Meta::CPAN

#define x86_cmov_membase(inst,cond,is_signed,reg,basereg,disp)	\
	do {	\
		*(inst)++ = (unsigned char) 0x0f;	\
		if ((is_signed))	\
			*(inst)++ = x86_cc_signed_map [(cond)] - 0x30;	\
		else	\
			*(inst)++ = x86_cc_unsigned_map [(cond)] - 0x30;	\
		x86_membase_emit ((inst), (reg), (basereg), (disp));	\
	} while (0)

#define x86_enter(inst,framesize)	\
	do {	\
		*(inst)++ = (unsigned char)0xc8;	\
		x86_imm_emit16 ((inst), (framesize));	\
		*(inst)++ = 0;	\
	} while (0)
	
#define x86_leave(inst) do { *(inst)++ = (unsigned char)0xc9; } while (0)
#define x86_sahf(inst)  do { *(inst)++ = (unsigned char)0x9e; } while (0)

#define x86_fsin(inst) do { *(inst)++ = (unsigned char)0xd9; *(inst)++ = (unsigned char)0xfe; } while (0)
#define x86_fcos(inst) do { *(inst)++ = (unsigned char)0xd9; *(inst)++ = (unsigned char)0xff; } while (0)
#define x86_fabs(inst) do { *(inst)++ = (unsigned char)0xd9; *(inst)++ = (unsigned char)0xe1; } while (0)
#define x86_ftst(inst) do { *(inst)++ = (unsigned char)0xd9; *(inst)++ = (unsigned char)0xe4; } while (0)

libjit/jit/jit-gen-x86.h  view on Meta::CPAN

			*(inst)++ = 0x00; *(inst)++ = 0x00;	\
			break;	\
		case 7: *(inst)++ = 0x8d; *(inst)++ = 0xa4;	\
			*(inst)++ = 0x24; *(inst)++ = 0x00;	\
			*(inst)++ = 0x00; *(inst)++ = 0x00;	\
			*(inst)++ = 0x00; break;	\
		default: jit_assert (0);	\
		}	\
	} while (0)

#define x86_prolog(inst,frame_size,reg_mask)	\
	do {	\
		unsigned i, m = 1;	\
		x86_enter ((inst), (frame_size));	\
		for (i = 0; i < X86_NREG; ++i, m <<= 1) {	\
			if ((reg_mask) & m)	\
				x86_push_reg ((inst), i);	\
		}	\
	} while (0)

#define x86_epilog(inst,reg_mask)	\
	do {	\
		unsigned i, m = 1 << X86_EDI;	\
		for (i = X86_EDI; m != 0; i--, m=m>>1) {	\

libjit/jit/jit-insn.c  view on Meta::CPAN

 * elimination pass.
 *
 * Repetitive use of this procedure for a chain of "add_relative" instructions
 * converts it into a series of indpenedent instructions each using the very
 * first address in the chain as its base. Therefore regardless of the initial
 * chain length it is always enough to make single "find_base_insn()" call to
 * get the base address of the entire chain (think induction).
 *
 * Note that in this situation the second "find_base_insn()" call will return
 * the instruction "i" that obtains the base address as the address of a local
 * frame variable. This instruction is a candidate for being moved down to
 * where the "load_relative" or "store_relative" occurs. This might make it
 * easier for the code generator to handle field accesses whitin local
 * variables.
 *
 * The "plast" argument indicates if the found instruction is already the last
 * one, so there is no need to move it down.
 */
static jit_insn_t
find_base_insn(
	jit_function_t func,

libjit/jit/jit-insn.c  view on Meta::CPAN

	for(param = 0; param < num_args; ++param)
	{
		new_args[param] = jit_insn_convert
			(func, args[param],
			 jit_type_get_param(signature, param), 0);
	}
	return 1;
}

/*
 * Set up the exception frame information before a function call out.
 */
static int setup_eh_frame_for_call(jit_function_t func, int flags)
{
#if !defined(JIT_BACKEND_INTERP)
	jit_type_t type;
	jit_value_t args[2];
	jit_insn_t insn;

	/* If "tail" is set, then we need to pop the "setjmp" context */
	if((flags & JIT_CALL_TAIL) != 0 && func->has_try)
	{
		type = jit_type_create_signature

libjit/jit/jit-insn.c  view on Meta::CPAN

	if((flags & (JIT_CALL_NOTHROW | JIT_CALL_TAIL)) != 0)
	{
		return 1;
	}

	/* This function may throw an exception */
	func->builder->may_throw = 1;

#if JIT_APPLY_BROKEN_FRAME_BUILTINS != 0
	{
		jit_value_t eh_frame_info;
		jit_type_t params[2];

		/* Get the value that holds the exception frame information */
		if((eh_frame_info = func->builder->eh_frame_info) == 0)
		{
			type = jit_type_create_struct(0, 0, 0);
			if(!type)
			{
				return 0;
			}
			jit_type_set_size_and_alignment
				(type, sizeof(struct jit_backtrace), sizeof(void *));
			eh_frame_info = jit_value_create(func, type);
			jit_type_free(type);
			if(!eh_frame_info)
			{
				return 0;
			}
			func->builder->eh_frame_info = eh_frame_info;
		}

		/* Output an instruction to load the "pc" into a value */
		args[1] = jit_value_create(func, jit_type_void_ptr);
		if(!(args[1]))
		{
			return 0;
		}
		insn = _jit_block_add_insn(func->builder->current_block);
		if(!insn)
		{
			return 0;
		}
		jit_value_ref(func, args[1]);
		insn->opcode = JIT_OP_LOAD_PC;
		insn->dest = args[1];

		/* Load the address of "eh_frame_info" into another value */
		args[0] = jit_insn_address_of(func, eh_frame_info);
		if(!(args[0]))
		{
			return 0;
		}

		/* Create a signature for the prototype "void (void *, void *)" */
		params[0] = jit_type_void_ptr;
		params[1] = jit_type_void_ptr;
		type = jit_type_create_signature
			(jit_abi_cdecl, jit_type_void, params, 2, 1);

libjit/jit/jit-insn.c  view on Meta::CPAN

			(func, jit_insn_address_of(func, func->builder->setjmp_value),
			 jit_jmp_catch_pc_offset, args[0]))
		{
			return 0;
		}
	}

	/* We are now ready to make the actual function call */
	return 1;
#else /* JIT_BACKEND_INTERP */
	/* The interpreter handles exception frames for us */
	if((flags & (JIT_CALL_NOTHROW | JIT_CALL_TAIL)) == 0)
	{
		func->builder->may_throw = 1;
	}
	return 1;
#endif
}

/*
 * Restore the exception handling frame after a function call.
 */
static int restore_eh_frame_after_call(jit_function_t func, int flags)
{
#if !defined(JIT_BACKEND_INTERP)
	jit_value_t value;

	/* If the "nothrow", "noreturn", or "tail" flags are set, then we
	   don't need to worry about this */
	if((flags & (JIT_CALL_NOTHROW | JIT_CALL_NORETURN | JIT_CALL_TAIL)) != 0)
	{
		return 1;
	}

libjit/jit/jit-insn.c  view on Meta::CPAN

			(func, jit_insn_address_of(func, func->builder->setjmp_value),
			 jit_jmp_catch_pc_offset, value))
		{
			return 0;
		}
	}

	/* Everything is back to where it should be */
	return 1;
#else /* JIT_BACKEND_INTERP */
	/* The interpreter handles exception frames for us */
	return 1;
#endif
}

/*
 * Determine if two signatures are identical for the purpose of tail calls.
 */
static int signature_identical(jit_type_t type1, jit_type_t type2)
{
	unsigned int param;

libjit/jit/jit-insn.c  view on Meta::CPAN

		if(!_jit_create_call_return_insns(func,
						  signature,
						  args, num_args,
						  return_value,
						  is_nested))
		{
			return 0;
		}
	}

	/* Restore exception frame information after the call */
	if(!restore_eh_frame_after_call(func, flags))
	{
		return 0;
	}

	/* Return the value containing the result to the caller */
	return return_value;
}

/*@
 * @deftypefun jit_value_t jit_insn_call (jit_function_t @var{func}, const char *@var{name}, jit_function_t @var{jit_func}, jit_type_t @var{signature}, jit_value_t *@var{args}, unsigned int @var{num_args}, int @var{flags})

libjit/jit/jit-insn.c  view on Meta::CPAN

	/* Intuit additional flags from "jit_func" if it was already compiled */
	if(func->no_throw)
	{
		flags |= JIT_CALL_NOTHROW;
	}
	if(func->no_return)
	{
		flags |= JIT_CALL_NORETURN;
	}

	/* Set up exception frame information for the call */
	if(!setup_eh_frame_for_call(func, flags))
	{
		return 0;
	}

	/* Create the instructions to push the parameters onto the stack */
	if(!create_call_setup_insns
			(func, jit_func, signature, new_args, num_args,
			 is_nested, nesting_level, &return_value, flags))
	{
		return 0;

libjit/jit/jit-insn.c  view on Meta::CPAN

		if(!convert_call_parameters(func, signature, args, num_args, new_args))
		{
			return 0;
		}
	}
	else
	{
		new_args = args;
	}

	/* Set up exception frame information for the call */
	if(!setup_eh_frame_for_call(func, flags))
	{
		return 0;
	}

	/* Create the instructions to push the parameters onto the stack */
	if(!create_call_setup_insns
		(func, 0, signature, new_args, num_args, 0, 0, &return_value, flags))
	{
		return 0;
	}

libjit/jit/jit-insn.c  view on Meta::CPAN

		if(!convert_call_parameters(func, signature, args, num_args, new_args))
		{
			return 0;
		}
	}
	else
	{
		new_args = args;
	}

	/* Set up exception frame information for the call */
	if(!setup_eh_frame_for_call(func, flags))
	{
		return 0;
	}

	/* Create the instructions to push the parameters onto the stack */
	if(!create_call_setup_insns
		(func, 0, signature, new_args, num_args, 0, 0, &return_value, flags))
	{
		return 0;
	}

libjit/jit/jit-insn.c  view on Meta::CPAN

		if(!convert_call_parameters(func, signature, args, num_args, new_args))
		{
			return 0;
		}
	}
	else
	{
		new_args = args;
	}

	/* Set up exception frame information for the call */
	if(!setup_eh_frame_for_call(func, flags))
	{
		return 0;
	}

	/* Create the instructions to push the parameters onto the stack */
	if(!create_call_setup_insns
		(func, 0, signature, new_args, num_args, 0, 0, &return_value, flags))
	{
		return 0;
	}

libjit/jit/jit-insn.c  view on Meta::CPAN

	/* Return the temporary that contains the result value */
	return return_value;
}

/*@
 * @deftypefun int jit_insn_incoming_reg (jit_function_t @var{func}, jit_value_t @var{value}, int @var{reg})
 * Output an instruction that notes that the contents of @var{value}
 * can be found in the register @var{reg} at this point in the code.
 *
 * You normally wouldn't call this yourself - it is used internally
 * by the CPU back ends to set up the function's entry frame and the
 * values of registers on return from a subroutine call.
 * @end deftypefun
@*/
int jit_insn_incoming_reg(jit_function_t func, jit_value_t value, int reg)
{
	if(value && value->is_parameter)
	{
		value->is_reg_parameter = 1;
	}
	return create_note(func, JIT_OP_INCOMING_REG, value,
					   jit_value_create_nint_constant
					   		(func, jit_type_int, (jit_nint)reg));
}

/*@
 * @deftypefun int jit_insn_incoming_frame_posn (jit_function_t @var{func}, jit_value_t @var{value}, jit_nint @var{frame_offset})
 * Output an instruction that notes that the contents of @var{value}
 * can be found in the stack frame at @var{frame_offset} at this point
 * in the code.
 *
 * You normally wouldn't call this yourself - it is used internally
 * by the CPU back ends to set up the function's entry frame.
 * @end deftypefun
@*/
int jit_insn_incoming_frame_posn
		(jit_function_t func, jit_value_t value, jit_nint frame_offset)
{
	return create_note(func, JIT_OP_INCOMING_FRAME_POSN, value,
					   jit_value_create_nint_constant
					   		(func, jit_type_int, frame_offset));
}

/*@
 * @deftypefun int jit_insn_outgoing_reg (jit_function_t @var{func}, jit_value_t @var{value}, int @var{reg})
 * Output an instruction that copies the contents of @var{value}
 * into the register @var{reg} at this point in the code.  This is
 * typically used just before making an outgoing subroutine call.
 *
 * You normally wouldn't call this yourself - it is used internally
 * by the CPU back ends to set up the registers for a subroutine call.
 * @end deftypefun
@*/
int jit_insn_outgoing_reg(jit_function_t func, jit_value_t value, int reg)
{
	return create_note(func, JIT_OP_OUTGOING_REG, value,
					   jit_value_create_nint_constant
					   		(func, jit_type_int, (jit_nint)reg));
}

/*@
 * @deftypefun int jit_insn_outgoing_frame_posn (jit_function_t @var{func}, jit_value_t @var{value}, jit_nint @var{frame_offset})
 * Output an instruction that notes that the contents of @var{value}
 * should be stored in the stack frame at @var{frame_offset} at this point
 * in the code.
 *
 * You normally wouldn't call this yourself - it is used internally
 * by the CPU back ends to set up an outgoing frame for tail calls.
 * @end deftypefun
@*/
int jit_insn_outgoing_frame_posn
		(jit_function_t func, jit_value_t value, jit_nint frame_offset)
{
	return create_note(func, JIT_OP_OUTGOING_FRAME_POSN, value,
					   jit_value_create_nint_constant
					   		(func, jit_type_int, frame_offset));
}

/*@
 * @deftypefun int jit_insn_return_reg (jit_function_t @var{func}, jit_value_t @var{value}, int @var{reg})
 * Output an instruction that notes that the contents of @var{value}
 * can be found in the register @var{reg} at this point in the code.
 * This is similar to @code{jit_insn_incoming_reg}, except that it
 * refers to return values, not parameter values.
 *
 * You normally wouldn't call this yourself - it is used internally

libjit/jit/jit-insn.c  view on Meta::CPAN

					   jit_value_create_nint_constant
					   		(func, jit_type_int, (jit_nint)reg));
}

/*@
 * @deftypefun int jit_insn_setup_for_nested (jit_function_t @var{func}, int @var{nested_level}, int @var{reg})
 * Output an instruction to set up for a nested function call.
 * The @var{nested_level} value will be -1 to call a child, zero to call a
 * sibling of @var{func}, 1 to call a sibling of the parent, 2 to call
 * a sibling of the grandparent, etc.  If @var{reg} is not -1, then
 * it indicates the register to receive the parent frame information.
 * If @var{reg} is -1, then the frame information will be pushed on the stack.
 *
 * You normally wouldn't call this yourself - it is used internally by the
 * CPU back ends to set up the parameters for a nested subroutine call.
 * @end deftypefun
@*/
int jit_insn_setup_for_nested(jit_function_t func, int nested_level, int reg)
{
	if(nested_level < 0)
	{
		return create_unary_note

libjit/jit/jit-insn.c  view on Meta::CPAN

			 jit_value_create_nint_constant
				 (func, jit_type_int, (jit_nint)nested_level),
			 jit_value_create_nint_constant
				 (func, jit_type_int, (jit_nint)reg));
	}
}

/*@
 * @deftypefun int jit_insn_flush_struct (jit_function_t @var{func}, jit_value_t @var{value})
 * Flush a small structure return value out of registers and back
 * into the local variable frame.  You normally wouldn't call this
 * yourself - it is used internally by the CPU back ends to handle
 * structure returns from functions.
 * @end deftypefun
@*/
int jit_insn_flush_struct(jit_function_t func, jit_value_t value)
{
	if(value)
	{
		jit_value_set_addressable(value);
	}

libjit/jit/jit-insn.c  view on Meta::CPAN

		}
		/* Not reached */
	}
}

/*@
 * @deftypefun int jit_insn_set_param (jit_function_t @var{func}, jit_value_t @var{value}, jit_nint @var{offset})
 * Set the parameter slot at @var{offset} in the outgoing parameter area
 * to @var{value}.  This may be used instead of @code{jit_insn_push}
 * if it is more efficient to store directly to the stack than to push.
 * The outgoing parameter area is allocated within the frame when
 * the function is first entered.
 *
 * You normally wouldn't call this yourself - it is used internally
 * by the CPU back ends to set up the stack for a subroutine call.
 * @end deftypefun
@*/
int jit_insn_set_param(jit_function_t func, jit_value_t value, jit_nint offset)
{
	jit_type_t type;
	if(!value)

libjit/jit/jit-insn.c  view on Meta::CPAN

	}

	/* We need a value to hold the location of the thrown exception */
	if((func->builder->thrown_pc =
			jit_value_create(func, jit_type_void_ptr)) == 0)
	{
		return 0;
	}

	/* Get the value of "catch_pc" from within "setjmp_value" and store it
	   into the current frame.  This indicates where the exception occurred */
	value = jit_insn_load_relative
		(func, jit_insn_address_of(func, func->builder->setjmp_value),
		 jit_jmp_catch_pc_offset, jit_type_void_ptr);
	if(!value)
	{
		return 0;
	}
	if(!jit_insn_store(func, func->builder->thrown_pc, value))
	{
		return 0;

libjit/jit/jit-internal.h  view on Meta::CPAN

	unsigned		is_local : 1;
	unsigned		is_volatile : 1;
	unsigned		is_addressable : 1;
	unsigned		is_constant : 1;
	unsigned		is_nint_constant : 1;
	unsigned		is_parameter : 1;
	unsigned		is_reg_parameter : 1;
	unsigned		has_address : 1;
	unsigned		free_address : 1;
	unsigned		in_register : 1;
	unsigned		in_frame : 1;
	unsigned		in_global_register : 1;
	unsigned		live : 1;
	unsigned		next_use : 1;
	unsigned		has_frame_offset : 1;
	unsigned		global_candidate : 1;
	unsigned		has_global_register : 1;
	short			reg;
	short			global_reg;
	jit_nint		address;
	jit_nint		frame_offset;
	jit_nuint		usage_count;
	int			index;
};
#define	JIT_INVALID_FRAME_OFFSET	((jit_nint)0x7FFFFFFF)

/*
 * Free the structures that are associated with a value.
 */
void _jit_value_free(void *value);

libjit/jit/jit-internal.h  view on Meta::CPAN


	/* Mapping from label numbers to blocks */
	_jit_label_info_t	*label_info;
	jit_label_t		max_label_info;

	/* Exception handling definitions for the function */
	jit_value_t		setjmp_value;
	jit_value_t		thrown_exception;
	jit_value_t		thrown_pc;
	jit_label_t		catcher_label;
	jit_value_t		eh_frame_info;

	/* Flag that is set to indicate that this function is not a leaf */
	unsigned		non_leaf : 1;

	/* Flag that indicates if we've seen code that may throw an exception */
	unsigned		may_throw : 1;

	/* Flag that indicates if the function has an ordinary return */
	unsigned		ordinary_return : 1;

libjit/jit/jit-internal.h  view on Meta::CPAN


	/* Memory pools that contain values, instructions, and metadata blocks */
	jit_memory_pool		value_pool;
	jit_memory_pool		edge_pool;
	jit_memory_pool		meta_pool;

	/* Common constants that have been cached */
	jit_value_t		null_constant;
	jit_value_t		zero_constant;

	/* The values for the parameters, structure return, and parent frame */
	jit_value_t		*param_values;
	jit_value_t		struct_return;
	jit_value_t		parent_frame;

	/* Metadata that is stored only while the function is being built */
	jit_meta_t		meta;

	/* Current size of the local variable frame (used by the back end) */
	jit_nint		frame_size;

	/* Number of stack items that are queued for a deferred pop */
	jit_nint		deferred_items;

	/* Size of the outgoing parameter area in the frame */
	jit_nint		param_area_size;

#ifdef _JIT_COMPILE_DEBUG
	int			block_count;
	int			insn_count;
#endif
};

/*
 * Internal structure of a function.

libjit/jit/jit-interp-opcodes.ops  view on Meta::CPAN

	op_def("lda_2_nfloat") { "JIT_OPCODE_NINT_ARG" }
	op_def("ldaa_2") { "JIT_OPCODE_NINT_ARG" }
	op_def("sta_0_byte") { "JIT_OPCODE_NINT_ARG" }
	op_def("sta_0_short") { "JIT_OPCODE_NINT_ARG" }
	op_def("sta_0_int") { "JIT_OPCODE_NINT_ARG" }
	op_def("sta_0_long") { "JIT_OPCODE_NINT_ARG" }
	op_def("sta_0_float32") { "JIT_OPCODE_NINT_ARG" }
	op_def("sta_0_float64") { "JIT_OPCODE_NINT_ARG" }
	op_def("sta_0_nfloat") { "JIT_OPCODE_NINT_ARG" }
	/*
	 * Local variable frame access opcodes.
	 */
	op_def("ldl_0_sbyte") { "JIT_OPCODE_NINT_ARG" }
	op_def("ldl_0_ubyte") { "JIT_OPCODE_NINT_ARG" }
	op_def("ldl_0_short") { "JIT_OPCODE_NINT_ARG" }
	op_def("ldl_0_ushort") { "JIT_OPCODE_NINT_ARG" }
	op_def("ldl_0_int") { "JIT_OPCODE_NINT_ARG" }
	op_def("ldl_0_long") { "JIT_OPCODE_NINT_ARG" }
	op_def("ldl_0_float32") { "JIT_OPCODE_NINT_ARG" }
	op_def("ldl_0_float64") { "JIT_OPCODE_NINT_ARG" }
	op_def("ldl_0_nfloat") { "JIT_OPCODE_NINT_ARG" }

libjit/jit/jit-interp.c  view on Meta::CPAN

			(*(((type *)VM_R1_PTR) + VM_R2_NINT))
#define	VM_STORE_ELEM(type,value)	\
			(*(((type *)VM_R0_PTR) + VM_R1_NINT) = (type)(value))

/*
 * Get the address of an argument or local variable at a particular offset.
 */
#define	VM_ARG(type)		\
			((type *)(((jit_item *)args) + VM_NINT_ARG))
#define	VM_LOC(type)		\
			((type *)(((jit_item *)frame) + VM_NINT_ARG))

/*
 * Handle the return value from a function that reports a builtin exception.
 */
#define	VM_BUILTIN(value)	\
			do { \
				builtin_exception = (value); \
				if(builtin_exception < JIT_RESULT_OK) \
				{ \
					goto handle_builtin; \

libjit/jit/jit-interp.c  view on Meta::CPAN

/*
 * Perform a tail call to a new function.
 */
#define	VM_PERFORM_TAIL(newfunc)	\
			{ \
				if(jbuf) \
				{ \
					_jit_unwind_pop_setjmp(); \
				} \
				func = (newfunc); \
				if(func->frame_size > current_frame_size) \
				{ \
					current_frame_size = func->frame_size; \
					frame_base = (jit_item *)alloca(current_frame_size); \
				} \
				stacktop = frame_base + func->working_area; \
				frame = stacktop; \
				goto restart_tail; \
			}

/*
 * Call "jit_apply" from the interpreter, to invoke a native function.
 */
static void apply_from_interpreter
		(jit_type_t signature, void *func,
		 jit_item *args, unsigned int num_fixed_args,
		 void *return_area)

libjit/jit/jit-interp.c  view on Meta::CPAN

		}
	}

	/* Apply the function */
	jit_apply(signature, func, apply_args, num_fixed_args, return_area);
}

void _jit_run_function(jit_function_interp_t func, jit_item *args,
					   jit_item *return_area)
{
	jit_item *frame_base;
	jit_item *frame;
	jit_item *stacktop;
	jit_item r0, r1, r2;
	void **pc;
	jit_int builtin_exception;
	jit_nint temparg;
	void *tempptr;
	void *tempptr2;
	jit_function_t call_func;
	struct jit_backtrace call_trace;
	void *entry;
	void *exception_object = 0;
	void *exception_pc = 0;
	void *handler;
	jit_jmp_buf *jbuf;
	jit_nint current_frame_size;

	/* Define the label table for computed goto dispatch */
	#include "jit-interp-labels.h"

	/* Set up the stack frame for this function */
	current_frame_size = func->frame_size;
	frame_base = (jit_item *)alloca(current_frame_size);
	stacktop = frame_base + func->working_area;
	frame = stacktop;

	/* Get the initial program counter */
restart_tail:
	pc = jit_function_interp_entry_pc(func);

	/* Create a "setjmp" point if this function has a "try" block.
	   This is used to catch exceptions on their way up the stack */
	if(func->func->has_try)
	{
		jbuf = (jit_jmp_buf *)alloca(sizeof(jit_jmp_buf));

libjit/jit/jit-interp.c  view on Meta::CPAN

			}
			return;
		}
		/* Not reached */

		VMCASE(JIT_OP_SETUP_FOR_NESTED):
		{
			/* TODO!!! */
			/* Set up to call a nested function who is our child */
			stacktop[-1].ptr_value = args;
			stacktop[-2].ptr_value = frame;
			VM_MODIFY_PC_AND_STACK(1, -2);
		}
		VMBREAK;

		VMCASE(JIT_OP_SETUP_FOR_SIBLING):
		{
			/* TODO!!! */
			/* Set up to call a nested function who is our sibling, a sibling
			   of one of our ancestors, or one of our ancestors directly */
			temparg = VM_NINT_ARG;

libjit/jit/jit-interp.c  view on Meta::CPAN

		{
			/* Throw an exception, which may be handled in this function */
			exception_object = VM_R1_PTR;
			exception_pc = pc;
		handle_exception:
			tempptr = jit_function_from_pc(func->func->context, pc, &handler);
			if(tempptr == func->func && handler != 0)
			{
				/* We have an appropriate "catch" handler in this function */
				pc = (void **)handler;
				stacktop = frame;
				VM_R0_PTR = exception_object;
			}
			else
			{
				/* Throw the exception up to the next level */
				if(jbuf)
				{
					_jit_unwind_pop_setjmp();
				}
				jit_exception_throw(exception_object);

libjit/jit/jit-interp.c  view on Meta::CPAN


		VMCASE(JIT_INTERP_OP_STA_0_NFLOAT):
		{
			/* Store a native float into an argument */
			*VM_ARG(jit_nfloat) = VM_R0_NFLOAT;
			VM_MODIFY_PC(2);
		}
		VMBREAK;

		/******************************************************************
		 * Local variable frame access opcodes.
		 ******************************************************************/

		VMCASE(JIT_INTERP_OP_LDL_0_SBYTE):
		{
			/* Load a signed 8-bit integer local into the register 0 */
			VM_R0_INT = *VM_LOC(jit_sbyte);
			VM_MODIFY_PC(2);
		}
		VMBREAK;

libjit/jit/jit-interp.h  view on Meta::CPAN

 */
typedef struct jit_function_interp *jit_function_interp_t;
struct jit_function_interp
{
	/* The function that this structure is associated with */
	jit_function_t	func;

	/* Size of the argument area to allocate, in bytes */
	unsigned int	args_size;

	/* Size of the local stack frame to allocate, in bytes */
	unsigned int	frame_size;

	/* Size of the working stack area of the frame, in items */
	unsigned int	working_area;
};

/*
 * Get the size of the "jit_function_interp" structure, rounded
 * up to a multiple of "void *".
 */
#define	jit_function_interp_size	\
			((sizeof(struct jit_function_interp) + sizeof(void *) - 1) & \
			 ~(sizeof(void *) - 1))

libjit/jit/jit-opcodes.ops  view on Meta::CPAN

	op_def("copy_float64", =) { op_values(float64, float64) }
	op_def("copy_nfloat", =) { op_values(nfloat, nfloat) }
	op_def("copy_struct", =) { op_values(ptr, ptr), "NINT_ARG" }
	op_def("copy_store_byte") { op_values(int, int) }
	op_def("copy_store_short") { op_values(int, int) }
	op_def("address_of", address_of) { op_values(ptr, any) }
	/*
	 * Incoming registers, outgoing registers, and stack pushes.
	 */
	op_def("incoming_reg") { op_type(reg) }
	op_def("incoming_frame_posn") { op_values(empty, any, int) }
	op_def("outgoing_reg") { op_type(reg) }
	op_def("outgoing_frame_posn") { op_values(empty, any, int) }
	op_def("return_reg") { op_type(reg) }
	op_def("push_int") { op_values(empty, int) }
	op_def("push_long") { op_values(empty, long) }
	op_def("push_float32") { op_values(empty, float32) }
	op_def("push_float64") { op_values(empty, float64) }
	op_def("push_nfloat") { op_values(empty, nfloat) }
	op_def("push_struct") { op_values(empty, any, ptr), "NINT_ARG" }
	op_def("pop_stack") { op_values(empty, int), "NINT_ARG" }
	op_def("flush_small_struct") { op_values(empty, any), "NINT_ARG" }
	op_def("set_param_int") { op_values(empty, int, ptr) }

libjit/jit/jit-reg-alloc.c  view on Meta::CPAN


#ifdef JIT_REG_DEBUG
	printf("value = ");
	jit_dump_value(stdout, jit_value_get_function(desc->value), desc->value, 0);
	printf("\n");
	printf("value->in_register = %d\n", desc->value->in_register);
	printf("value->reg = %d\n", desc->value->reg);
	printf("value->has_global_register = %d\n", desc->value->has_global_register);
	printf("value->in_global_register = %d\n", desc->value->in_global_register);
	printf("value->global_reg = %d\n", desc->value->global_reg);
	printf("value->in_frame = %d\n", desc->value->in_frame);
	printf("reg = %d\n", desc->reg);
	printf("other_reg = %d\n", desc->other_reg);
	printf("live = %d\n", desc->live);
	printf("used = %d\n", desc->used);
	printf("clobber = %d\n", desc->clobber);
	printf("early_clobber = %d\n", desc->early_clobber);
	printf("duplicate = %d\n", desc->duplicate);
	printf("thrash = %d\n", desc->thrash);
	printf("store = %d\n", desc->store);
	printf("load = %d\n", desc->load);

libjit/jit/jit-reg-alloc.c  view on Meta::CPAN

}

/*
 * Compute the register spill cost. The register spill cost is computed as
 * the sum of spill costs of individual values the register contains. The
 * spill cost of a value depends on the following factors:
 *
 * 1. Values that are not used after the current instruction may be safely
 *    discareded so their spill cost is taken to be zero.
 * 2. Values that are spilled to global registers are cheaper than values
 *    that are spilled into stack frame.
 * 3. Clean values are cheaper than dirty values.
 *
 * NOTE: A value is clean if it was loaded from the stack frame or from a
 * global register and has not changed since then. Otherwise it is dirty.
 * There is no need to spill clean values. However their spill cost is
 * considered to be non-zero so that the register allocator will choose
 * those registers that do not contain live values over those that contain
 * live albeit clean values.
 *
 * For global registers this function returns the cost of zero. So global
 * registers have to be handled separately.
 */
static int

libjit/jit/jit-reg-alloc.c  view on Meta::CPAN

			{
				cost += COST_SPILL_CLEAN_GLOBAL;
			}
			else
			{
				cost += COST_SPILL_DIRTY_GLOBAL;
			}
		}
		else
		{
			if(value->in_frame)
			{
				cost += COST_SPILL_CLEAN;
			}
			else
			{
				cost += COST_SPILL_DIRTY;
			}
		}
	}

libjit/jit/jit-reg-alloc.c  view on Meta::CPAN

				{
					cost += COST_SPILL_CLEAN_GLOBAL;
				}
				else
				{
					cost += COST_SPILL_DIRTY_GLOBAL;
				}
			}
			else
			{
				if(value->in_frame)
				{
					cost += COST_SPILL_CLEAN;
				}
				else
				{
					cost += COST_SPILL_DIRTY;
				}
			}
		}
	}

libjit/jit/jit-reg-alloc.c  view on Meta::CPAN

		gen->contents[other_reg].used_for_temp = 1;
		gen->contents[other_reg].is_long_end = 0;
		gen->contents[other_reg].is_long_start = 0;
	}
}

/*
 * Associate value with register.
 */
static void
bind_value(jit_gencode_t gen, jit_value_t value, int reg, int other_reg, int still_in_frame)
{
#ifdef JIT_REG_DEBUG
	printf("bind_value(value = ");
	jit_dump_value(stdout, jit_value_get_function(value), value, 0);
	printf(", reg = %d, other_reg = %d, still_in_frame = %d)\n",
	       reg, other_reg, still_in_frame);
#endif

	if(value->has_global_register && value->global_reg == reg)
	{
		value->in_register = 0;
		value->in_global_register = 1;
		return;
	}

	if(value->is_constant)
	{
		still_in_frame = 0;
	}

#ifdef JIT_REG_DEBUG
	if(gen->contents[reg].num_values == JIT_MAX_REG_VALUES)
	{
		printf("*** Too many values for one register! ***\n");
		abort();
	}
#endif

libjit/jit/jit-reg-alloc.c  view on Meta::CPAN

	{
		gen->contents[reg].is_long_start = 1;
		gen->contents[other_reg].num_values = 0;
		gen->contents[other_reg].age = gen->current_age;
		gen->contents[other_reg].used_for_temp = 0;
		gen->contents[other_reg].is_long_start = 0;
		gen->contents[other_reg].is_long_end = 1;
	}
	++(gen->current_age);

	/* Adjust the value to reflect that it is in "reg", and maybe the frame */
	value->in_register = 1;
	if(value->has_global_register)
	{
		value->in_global_register = still_in_frame;
	}
	else
	{
		value->in_frame = still_in_frame;
	}
	value->reg = reg;
}

/*
 * Disassociate value with register.
 */
static void
unbind_value(jit_gencode_t gen, jit_value_t value, int reg, int other_reg)
{

libjit/jit/jit-reg-alloc.c  view on Meta::CPAN

			exch_stack_top(gen, reg, 1);
			return;
		}
#endif
	}

	unbind_value(gen, value, reg, other_reg);
}

/*
 * Save the value from the register into its frame position and optionally free it.
 * If the value is already in the frame or is a constant then it is not saved but
 * the free option still applies to them.
 */
static void
save_value(jit_gencode_t gen, jit_value_t value, int reg, int other_reg, int free)
{
#ifdef JIT_REG_DEBUG
	printf("save_value(value = ");
	jit_dump_value(stdout, jit_value_get_function(value), value, 0);
	printf(", reg = %d, other_reg = %d, free=%d)\n", reg, other_reg, free);
#endif

libjit/jit/jit-reg-alloc.c  view on Meta::CPAN

			_jit_gen_spill_reg(gen, reg, other_reg, value);
			value->in_global_register = 1;
		}
		if(free)
		{
			unbind_value(gen, value, reg, other_reg);
		}
		return;
	}

	/* Take care of constants and values that are already in frame. */
	if(value->is_constant || value->in_frame)
	{
		if(free)
		{
			free_value(gen, value, reg, other_reg, 0);
		}
		return;
	}

	/* Now really save the value into the frame. */
#ifdef JIT_REG_STACK
	if(IS_STACK_REG(reg))
	{
		int top;

		/* Find the top of the stack. */
		top = gen->reg_stack_top - 1;

		/* Move the value on the stack top if it is not already there. */
		if(top != reg)

libjit/jit/jit-reg-alloc.c  view on Meta::CPAN

	else
#endif
	{
		_jit_gen_spill_reg(gen, reg, other_reg, value);
		if(free)
		{
			unbind_value(gen, value, reg, other_reg);
		}
	}

	value->in_frame = 1;
}

/*
 * Spill a specific register.
 */
static void
spill_register(jit_gencode_t gen, int reg)
{
	int other_reg, index;
	jit_value_t value;

libjit/jit/jit-reg-alloc.c  view on Meta::CPAN

			{
				break;
			}

			value = gen->contents[reg].values[index];
			usage = value_usage(regs, value);
			if((usage & VALUE_INPUT) != 0)
			{
				continue;
			}
			if((usage & VALUE_DEAD) != 0 || value->in_frame)
			{
				unbind_value(gen, value, reg, -1);
			}
		}
		for(index = gen->contents[reg].num_values - 1; index >= 0; --index)
		{
			int top;

			value = gen->contents[reg].values[index];
			usage = value_usage(regs, value);
			if((usage & VALUE_INPUT) != 0)
			{
				if((usage & VALUE_DEAD) != 0 || value->in_frame)
				{
					continue;
				}

				top = gen->reg_stack_top - 1;
				if(reg != top)
				{
					exch_stack_top(gen, reg, 0);
					reg = top;
				}

libjit/jit/jit-reg-alloc.c  view on Meta::CPAN

			}
			else
			{
				top = gen->reg_stack_top - 1;
				if(reg != top)
				{
					exch_stack_top(gen, reg, 0);
					reg = top;
				}

				if((usage & VALUE_DEAD) != 0 || value->in_frame)
				{
					free_value(gen, value, reg, -1, 0);
				}
				else
				{
					save_value(gen, value, reg, -1, 1);
				}
			}
		}
	}

libjit/jit/jit-reg-alloc.c  view on Meta::CPAN

	}

#ifdef JIT_REG_DEBUG
	printf("value = ");
	jit_dump_value(stdout, jit_value_get_function(desc->value), desc->value, 0);
	printf("\n");
	printf("value->in_register = %d\n", desc->value->in_register);
	printf("value->reg = %d\n", desc->value->reg);
	printf("value->in_global_register = %d\n", desc->value->in_global_register);
	printf("value->global_reg = %d\n", desc->value->global_reg);
	printf("value->in_frame = %d\n", desc->value->in_frame);
#endif
}

static void
commit_output_value(jit_gencode_t gen, _jit_regs_t *regs, int push_stack_top)
{
	_jit_regdesc_t *desc;

#ifdef JIT_REG_DEBUG
	printf("commit_output_value()\n");

libjit/jit/jit-reg-alloc.c  view on Meta::CPAN

	}

#ifdef JIT_REG_DEBUG
	printf("value = ");
	jit_dump_value(stdout, jit_value_get_function(desc->value), desc->value, 0);
	printf("\n");
	printf("value->in_register = %d\n", desc->value->in_register);
	printf("value->reg = %d\n", desc->value->reg);
	printf("value->in_global_register = %d\n", desc->value->in_global_register);
	printf("value->global_reg = %d\n", desc->value->global_reg);
	printf("value->in_frame = %d\n", desc->value->in_frame);
#endif
}

/*@
 * @deftypefun void _jit_regs_lookup (char *name)
 * Get the pseudo register by its name.
 * @end deftypefun
@*/
int
_jit_regs_lookup(char *name)

libjit/jit/jit-reg-alloc.c  view on Meta::CPAN

	   free by now (spilled at some earlier point). */
#if 0
	/* Eject any values that are currently in the register */
	spill_register(gen, reg);
	if(other_reg >= 0)
	{
		spill_register(gen, other_reg);
	}
#endif

	/* Record that the value is in "reg", but not in the frame */
#ifdef JIT_REG_STACK
	if(IS_STACK_REG(reg))
	{
		++(gen->reg_stack_top);
	}
#endif
	bind_value(gen, value, reg, other_reg, 0);
}

/*@

libjit/jit/jit-reg-alloc.c  view on Meta::CPAN

			_jit_regs_force_out(gen, value, 0);
		}
	}
#else
	other_reg = jit_reg_get_pair(value->type, reg);
#endif

	if(value->in_register && value->reg == reg)
	{
		/* The value is already in the register, but we may need to spill
		   if the frame copy is not up to date with the register */
		if(!(value->in_global_register || value->in_frame))
		{
			save_value(gen, value, reg, other_reg, 0);
		}

		/* The value is no longer "really" in the register.  A copy is
		   left behind, but the value itself reverts to the frame copy
		   as we are about to kill the registers in a function call */
		free_value(gen, value, reg, other_reg, 1);
	}
	else
	{
		/* Reload the value into the specified register */
		spill_register(gen, reg);
		if(other_reg >= 0)
		{
			spill_register(gen, other_reg);

libjit/jit/jit-reg-alloc.c  view on Meta::CPAN

void
_jit_regs_clear_all_outgoing(jit_gencode_t gen)
{
	gen->inhibit = jit_regused_init;
}

/* TODO: remove this function */
/*@
 * @deftypefun void _jit_regs_force_out (jit_gencode_t gen, jit_value_t value, int is_dest)
 * If @code{value} is currently in a register, then force its value out
 * into the stack frame.  The @code{is_dest} flag indicates that the value
 * will be a destination, so we don't care about the original value.
 *
 * This function is deprecated and going to be removed soon.
 *
 * @end deftypefun
@*/
void _jit_regs_force_out(jit_gencode_t gen, jit_value_t value, int is_dest)
{
	int reg, other_reg;
	if(value->in_register)



( run in 0.809 second using v1.01-cache-2.11-cpan-df04353d9ac )