Alien-LibJIT

 view release on metacpan or  search on metacpan

libjit/ChangeLog  view on Meta::CPAN


	* jit/jit-dump.c (jit_dump_insn): Print the destination value for
	the address_of_label opcode.

2010-11-07  Klaus Treichel  <ktreichel@web.de>

	* jit/jit-cache.h: Fix comment for _jit_cache_get_end_method.

2010-10-24  Klaus Treichel  <ktreichel@web.de>

	* jit/jit-reg-alloc.c (_jit_regs_alloc_global): Set in_global_register
	on global register assignment.

2010-10-04  Klaus Treichel  <ktreichel@web.de>

	* jit/jit-internal.h: Add missing typedef in the declaration of the
	_jit_intrinsic_signature enumaeration. (Really Noah Lavine)

2010-09-21  Klaus Treichel  <ktreichel@web.de>

	* config/jit-opcodes.ops: Add definitions for the opcode's
	intrinsics.

libjit/ChangeLog  view on Meta::CPAN


2008-07-06  Klaus Treichel  <ktreichel@web.de>

	* jit/jit-rules-x86-64.ins: Replace the check if an immediate value
	is a signed 32bit value by using an if clause the new imms32 clause.
	Flag rules for branch opcodes with the branch option and add the
	commutative option where appropriate.

2008-07-06  Juan Jesus Garcia de Soria  <juanj.g_soria@grupobbva.com>

	* jit/jit-reg-alloc.c (choose_input_order): take into account global
	registers to see if it is suitable to exchange input values. This
	fixes a problem that took place when a commutative op is applied to
	a value that resides in a global register and is both the dest and
	the second source value of the op.

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

	* include/jit/jit-common.h: remove unused jit_function_compiled_t
	type.

	* include/jit/jit-except.h, include/jit/jit-common.h: move
	JIT_NO_OFFSET from jit-except.h to jit-common.h.

libjit/ChangeLog  view on Meta::CPAN

	register class which means all registers in the class are clobbered.
	Remove "only", "spill_before", "unary", and "binary" keywords.
	Replace "unary_note" and "binary_note" with "note". Also replace
	"unary_branch" and "binary_branch" with "branch".

	* jit/jit-rules-alpha.ins, jit/jit-rules-x86.ins: update according
	to the new rule syntax.

2006-12-20  Aleksey Demakov  <ademakov@gmail.com>

	* jit/jit-thread.h, jit/jit-thread.c: add _jit_global_lock mutex.
	* jit/jit-init.c (jit_init): make sure that initialization is done
	  only once.

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

	* include/jit/jit-function.h, jit/jit-function.c: Add the function
	jit_function_from_vtable_pointer to convert a vtable pointer back to
	the jit_function_t.

2006-11-29  Aleksey Demakov  <ademakov@gmail.com>

libjit/ChangeLog  view on Meta::CPAN

	(JIT_OP_THROW, JIT_OP_LOAD_PC): add position_independent check and
	stub missing cases.

2006-11-26  Kirill Kononenko  <Kirill.Kononenko@gmail.com>

	* jit/jit-rules-x86.ins: if JIT_USE_SIGNALS is defined do not emit
	explicit division by zero check (patch #5278).

2006-11-26  Aleksey Demakov  <ademakov@gmail.com>

	* jit/jit-reg-alloc.c (choose_output_register): fix global register
	use cost computation.

	* jit/jit-rules-x86.ins: mark as commutative JIT_OP_IADD,
	JIT_OP_IMUL, JIT_OP_LADD, JIT_OP_IAND, JIT_OP_IOR, JIT_OP_IXOR,
	JIT_OP_LAND, JIT_OP_LOR, JIT_OP_XOR rules.

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

	* jit/jit-reg-alloc.c (exch_stack_top, free_value): fix freeing
	stack registers.

libjit/ChangeLog  view on Meta::CPAN


	* jit/jit-rules-alpha.c jit/jit-rules-alpha.ins Properly handle
	fixups on alpha. Implement JIT_OP_CALL_EXTERNAL for alpha.

2006-07-29  Aleksey Demakov  <ademakov@gmail.com>

	* jit/jit-reg-alloc.c (use_cheapest_register): allow a register that
	contains an input value to be used as a scratch register. The input
	value in this case is copied to another register. This resolves the
	problem with JIT_OP_IREM rule that failed to allocate a scratch reg
	in a very specific case (all EBX, ESI, EDI regs are used as global,
	dividend is initially in ECX and copied to EAX:EDX pair where x86
	idiv expects it to be).

	* jit/jit-reg-alloc.c (set_regdesc_flags): fix a bug.

2006-07-23  Thomas Cort  <linuxgeek@gmail.com>

	* jit/jit-apply-alpha.c jit/jit-apply-alpha.h jit/jit-apply-func.h
	jit/jit-gen-alpha.h jit/jit-rules-alpha.c jit/jit-rules-alpha.h
	jit/jit-rules-alpha.ins Implement the redirector for alpha. 

libjit/ChangeLog  view on Meta::CPAN

	block.

	* jit/jit-reg-alloc.c (_jit_regs_begin, _jit_regs_end):	add
	convenience functions.

	* tools/gen-rules-parser.y (gensel_output_clauses): make generated
	code more readable by using _jit_regs_begin() and _jit_regs_end()
	where appropriate.

	* jit/jit-reg-alloc.c: allow to load the second part of a register
	pair to a global register. This is because x86 long arithmetics
	use 4 registers at once: EAX:EDX and ECX:EBX. At the same time
	EBX is the global register candidate. If the instruction clobbers
	the global register, the new allocator automatically pushes it on
	the stack before and pops after the instruction.

	* jit/jit-function.c (compile_block): modify trace messages.

2006-05-28  Klaus Treichel  <ktreichel@web.de>

	* jit/jit-insn.c: Add a code_label in initialize_setjmp_block just
	before the end_label that is moved with the block to the start of
	the function as jump target to the code. Otherwise other blocks
	moved to the start after this block will never be executed.

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

	* jit/jit-reg-alloc.c (free_value, save_value): the value that has
	a global register and is also associated with a local register
	needs to be unbound from the local one.

	* jit/jit-reg-alloc.c (compute_spill_cost): assume that the spill
	cost for clean values is not zero. This keeps them in registers
	as long as there are free registers and thus reduces the number of
	loads.
	
2006-05-25  Aleksey Demakov  <ademakov@gmail.com>

	* jit/jit-reg-alloc.c (use_cheapest_register): fix cost calculation
	again for 'spill_before' rules. The last patch did not work for
	values stored in global registers. Now both global and non-global
	values should be copied to EAX.

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

	* jit/jit-reg-alloc.c (use_cheapest_register): fix cost calculation
	that sometimes caused overlooking free registers. This was a serious
	problem as there are some 'spill_before' rules that assume that the
	allocator will always choose EAX as the first free register.

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

libjit/ChangeLog  view on Meta::CPAN

	_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
	part of a register pair clobbers global registers.

	* jit/jit-reg-alloc.c (exch_stack_top): run value exchange loop
	for all values in both registers.

	* jit/jit-reg-alloc.h, jit/jit-reg-alloc.c: delete on_stack field
	from the _jit_regdesc_t struct.

	* jit/jit-reg-alloc.c (_jit_regs_gen): handle instructions that have
	both stack and flat registers.

libjit/ChangeLog  view on Meta::CPAN


	* jit/jit-internal.h (struct _jit_builder): 
	* jit/jit-function.c (compile_block, jit_function_compile): add
	some tracing.

	* jit/jit-rules.h:
	* jit/jit-rules-arm.c:
	* jit/jit-rules-interp.c: 
	* jit/jit-rules-x86.c: add _jit_gen_exch_top and _jit_gen_spill_top
	functions used by new allocator to handle stack registers. Add reg
	argument to _jit_gen_spill_global and_jit_gen_load_global
	functions.

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

	* jit/jit-insn.c (jit_insn_start_catcher): initialize
	thrown_exception (the problem was found by Klaus).

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

	* jit/jit-opcode.c: add jump table into jit_opcodes array.

libjit/ChangeLog  view on Meta::CPAN

	* jit/jit-rules-x86.c (_jit_create_call_return_insns): fix return
	code in case of no return value or struct returned via pointer.

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

	* jit/jit-reg-alloc.h: 
	* jit/jit-reg-alloc.c: Initial version of new local register
	  allocator.

	* jit/jit-rules.h: 
	* jit/jit-rules-arm.c (_jit_gen_spill_global): 
	* jit/jit-rules-interp.c (_jit_gen_spill_global): 
	* jit/jit-rules-x86.c (_jit_gen_spill_global): add function for
	spilling global registers. Used by the new allocator. Only x86
	version is really implemented.

2006-02-13  Aleksey Demakov  <ademakov@gmail.com>

	* jit/jit-internal.h (struct _jit_value): add index field.
	* jit/jit-value.c (alloc_value): initialize index field;
	* jit/Makefile.am (libjit_la_SOURCES): add jit-bitset.c and jit-cfg.c.

2006-02-12  Aleksey Demakov  <ademakov@gmail.com>

libjit/ChangeLog  view on Meta::CPAN


	* 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.

	* jit/jit-function.c, jit/jit-reg-alloc.c, jit/jit-rules-arm.c,
	jit/jit-rules-interp.c, jit/jit-rules-x86.c, jit/jit-rules.h:
	implement global register allocation for parameters in stack slots.

	* jit/jit-rules-x86.c, jit/jit-rules-x86.sel, jit/jit-rules.h:
	optimize the x86 function epilog when we are certain that the
	stack height doesn't change between entry and exit (i.e. the
	function is a leaf and there are no alloca's).

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

	* jit/jit-apply-arm.c, jit/jit-gen-arm.c, jit/jit-gen-arm.h,
	jit/jit-rules-arm.c, jit/jit-rules-arm.h, jit/jit-rules-arm.sel,

libjit/ChangeLog  view on Meta::CPAN

	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
	location after flushing the constant table.

libjit/ChangeLog  view on Meta::CPAN


	* jit/jit-gen-arm.h (arm_call): use a more efficient form of
	call for offsets beyond the simple target range.

	* jit/jit-rules-arm.sel, tools/gen-sel-parser.y,
	tools/gen-sel-scanner.l: introduce conditional rules into "gen-sel"
	so that we can disable certain rules on ARM platforms that lack
	floating-point support.

	* jit/jit-rules-arm.c (_jit_gen_spill_reg): spill properly to
	global registers for ARM.

	* jit/jit-reg-alloc.c, jit/jit-rules-arm.c, jit/jit-rules-arm.sel,
	jit/jit-rules-x86.sel: minor register assignment bugs.

	* jit/jit-rules-arm.c: ARM parameters cannot be split between
	registers and the stack.

	* jit/jit-gen-arm.c, jit/jit-gen-arm.h, jit/jit-rules-arm.c,
	jit/jit-rules-arm.h, jit/jit-rules-arm.sel: implement a
	constant pool for ARM, which gets complicated constants out

libjit/ChangeLog  view on Meta::CPAN

	jit/jit-rules-arm.sel, jit/jit-rules-x86.c, jit/jit-rules-x86.sel:
	add some more instructions to the ARM back end; split some x86
	back end code out into common code for ARM to use as well.

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

	* jit/jit-function.c, jit/jit-insn.c, jit/jit-internal.h,
	jit/jit-reg-alloc.c, jit/jit-reg-alloc.h, jit/jit-rules-arm.c,
	jit/jit-rules-arm.h, jit/jit-rules-interp.c, jit/jit-rules-interp.h,
	jit/jit-rules-x86.c, jit/jit-rules-x86.h, jit/jit-rules.h,
	jit/jit-value.c, tools/gen-sel-parser.y: implement a simple global
	register allocation policy, based on usage counts.

	* jit/jit-reg-alloc.c (_jit_regs_load_value): if a value is in a
	global register and it is not going to be destroyed by an instruction,
	then use the global register as the operand.

	* jit/jit-insn.c: recognise "t = a op b; a = t" and turn it
	into "a = a op b" to make it easier for back ends to recognise
	special idioms such as increments and decrements.

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

	* jit/jit-cache.c, jit/jit-elf-read.c, tools/gen-apply.c:
	fix some gcc 3.x compile warnings.

libjit/ChangeLog  view on Meta::CPAN

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

	* include/jit/jit-insn.h, jit/jit-insn.c, jit/jit-interp.cpp,
	jit/jit-interp.h, jit/jit-opcode.c, jit/jit-rules-interp.c:
	round out the function call handling opcodes for the interpreter.

	* jit/jit-rules-interp.c, jit/jit-rules-interp.h: implement
	the exception-handling opcodes for the interpreter.

	* dpas/dpas-parser.y, dpas/dpas-scope.c, dpas/dpas-scope.h:
	fix a bug that caused global variables in Dynamic Pascal
	to be incorrectly allocated as locals.

	* jit/jit-reg-alloc.c (_jit_regs_load_to_top_two): handle the
	case where the second value is on the stack but not the first.

	* dpas/dpas-parser.y, dpas/dpas-types.c, dpas/dpas-types.h:
	report errors for unimplemented expressions and statements,
	so that users are not "surprised" when things silently fail.

	* .cvsignore, auto_gen.sh, configure.in, doc/.cvsignore,

libjit/NEWS  view on Meta::CPAN

        * Add jit_insn_mark_breakpoint_variable function (Radek Polak).
	* Add signal handlers (Kirill Kononenko).
	* Add JIT_OPTION_POSITION_INDEPENDENT context option (not supported
	  by the backends yet) (Aleksey Demakov).
	* Add function indirectors (Klaus Treichel).
	* Allocate function redirectors and indirectors in the code cache
	  (Aleksey Demakov).
	* Use mmap to allocate executable memory where available
	  (Klaus Treichel).
	* Now can dump to any stream not just stdout and stderr (Radek Polak).
	* Use a global lock during context initialization (Aleksey Demakov).
	* Fix problems that take place after compilation is restarted on cache
	  page overflow (Aleksey Demakov).

	Register allocation/instruction selection improvements (Aleksey Demakov):

	* Completely rewrite register allocator. The new allocator works with
	  three-value intermediate instructions rather than with individual
	  values. This allows to fully analyze the effect of the instruction
	  and makes it possible to optimize commutative instructions and 
	  eliminate in some cases redundant register spills and loads.
	* Support three-address architectures.
	* Add register classes.
	* The allocator may now allocate scratch registers for instructions.
	* The allocator now automatically handles cases when a global register
	  is clobbered by the instruction (which may happen on the register
	  constrained x86 architecture).
	* Implement value coalescing for copy instructions.
	* Provide for efficient handling of x87 floating point stack.
	* Add gen-rules program that supersedes gen-sel. It generates code for
	  new register allocator and extends the syntax of instruction selection
	  rules to make use of new features such as register classes, scratch
	  registers, etc.

	Alpha:

libjit/NEWS  view on Meta::CPAN

	* Don't allow conditional branches to jump out of exception contexts.
	* Block movement to allow initialization code to be moved to the start
	  of a function, or loop condition code to be moved to the end.
	* Rewrite the exception region routines to make them easier to use.
	* Add the "gen-sel" program, for creating instruction selectors.
	* Write instruction selectors for x86 and ARM (only x86 is enabled).
	* Portability fixes for ARM, PPC, Alpha, IA64, and amd64.
	* Clarify the description of LLVM, at the request of LLVM's author.
	* Deferred argument popping after function calls.
	* Add "--enable-interpreter" to force the interpreter to be used.
	* Implement a simple global register allocator based on usage counts.
	* Recognise increment and decrement idioms.
	* Align cache flushes properly (Miroslaw Dobrzanski-Neumann).
	* Querying of x86 cpuid where necessary.
	* Add a constant pool for ARM, to make constant loads more efficient.
	* Handle register pairs for 64-bit values properly.
	* Support for parameter areas on the stack, to reduce push/pop overhead.
	* Avoid unnecessary register spills if a value won't be used again.
	* Implement tail calls from a function to itself.
	* Optimize x86 prologs and epilogs to avoid doing unnecessry work.
	* Centralise the code that handles parameter passing.

libjit/TODO  view on Meta::CPAN

Target release: 0.1.4
=====================

* CFG-based liveness analysis and dead code elimination
* global copy and constant propagation
* jitruby (in case copyright issues are resolved)
* sync jitplus with jit (jump tables, compile driver, debug)
* fix catch/throw within finally
* get rid of manual rules
* add direct conversion opcodes to/from float32 and float64
* add rounding towards zero
* try to be smarter with %rax for variadic functions on x86-64

Target Release: 0.2.0
=====================

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


#include "jit-internal.h"

#if defined(__alpha) || defined(__alpha__)

#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) */

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

	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) */

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

 *
 * This function is called at the end of the code generation process, 
 * not the beginning. At this point, it is known which callee save 
 * registers must be preserved, allowing the back end to output the 
 * 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) */

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

}

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

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);

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

	switch(opcode) {
		#define JIT_INCLUDE_SUPPORTED
		#include "jit-rules-alpha.inc"
		#undef JIT_INCLUDE_SUPPORTED
	}

	return 0;
}

/*
 * Determine if type is a candidate for allocation within global registers.
 */
int _jit_gen_is_global_candidate(jit_type_t type) {

	switch(jit_type_remove_tags(type)->kind) {
		case JIT_TYPE_INT:
		case JIT_TYPE_UINT:
		case JIT_TYPE_NINT:
		case JIT_TYPE_NUINT:
		case JIT_TYPE_PTR:
		case JIT_TYPE_SIGNATURE:
			return 1;
	}

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

			case JIT_TYPE_FLOAT32:
			case JIT_TYPE_FLOAT64:
			case JIT_TYPE_NFLOAT:
				break;
			*/

			default:
				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);

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

			case JIT_TYPE_FLOAT32:
			case JIT_TYPE_FLOAT64:
			case JIT_TYPE_NFLOAT:
				break;
		}
	}

	jit_cache_end_output();
}

void _jit_gen_load_global(jit_gencode_t gen, int reg, jit_value_t value) {
	TODO();
}


/*
 * Generate code for a redirector, which makes an indirect jump to the contents of 
 * func->entry_point. Redirectors are used on recompilable functions in place of the 
 * regular entry point. This allows libjit to redirect existing calls to the new 
 * version after recompilation.
 */

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

	{  "fe5", 27, -1, JIT_REG_FIXED}, \
	{  "fe6", 28, -1, JIT_REG_FIXED}, \
	{  "fe7", 29, -1, JIT_REG_FIXED}, \
	{  "fe8", 30, -1, JIT_REG_FIXED}, \
	{"fzero", 31, -1, JIT_REG_FIXED},

/* 32 floating-point registers + 32 integer registers */
#define JIT_NUM_REGS			64

/*
 * The number of registers that are used for global register 
 * allocation. Set to zero if global register allocation should not be 
 * used.
 */
#define JIT_NUM_GLOBAL_REGS		14

/*
 * Define to 1 if we should always load values into registers
 * before operating on them.  i.e. the CPU does not have reg-mem
 * and mem-reg addressing modes.
 *
 * The maximum number of operands for an alpha instruction is 3,

libjit/doc/mangling_rules.txt  view on Meta::CPAN


GCC 2.95.3 name mangling grammar (intuited from gcc sources):
------------------------------------------------------------

<global-function>   ::= <name> '__F' <func-params>

<member-function>   ::= <name> '__' <class-name> <func-params>

<ctor-function>		::= '__' <class-name> <func-params>

<dtor-function>		::= '_' <joiner> '_' <class-name> <func-params>

<joiner>			::= '.' | '$'			  # system-dependent joiner

<class-name>		::= <qualified-name>

libjit/doc/mangling_rules.txt  view on Meta::CPAN

<pointer-to-member-type> ::= M </class/ type> </member/ type>

<template-param>    ::= T </parameter/ number> _

<template-template-param> ::= <template-param>
                          ::= <substitution>

MSVC 6.0 name mangling rules (determined by trial and error):
------------------------------------------------------------

<global-function>	::= '?' <name> '@@Y' <callconv> <return-type> <parameters>

<member-function>	::= '?' <name> '@' <class-name> '@@' <access>
							[<const>] <callconv> <return-type> <parameters>

<ctor-function>		::= '??0' <class-name> '@@' <access> <const> <callconv>
							'@' <parameters>

<dtor-function>		::= '??1' <class-name> '@@' <access> <const> <callconv>
							'@' <parameters>

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

void dpas_error_on_line(const char *filename, long linenum,
                        const char *format, ...);

/*
 * Get the JIT context that we are using to compile functions.
 */
jit_context_t dpas_current_context(void);

/*
 * Get the current function that is being compiled.  Returns NULL
 * if we are currently at the global level.
 */
jit_function_t dpas_current_function(void);

/*
 * Create a new function and push it onto the context stack.
 * The function is initialized to read parameters that are
 * compatible with the supplied signature.
 */
jit_function_t dpas_new_function(jit_type_t signature);

libjit/dpas/dpas-parser.y  view on Meta::CPAN

							{
								dpas_out_of_memory();
							}
							dpas_scope_add(dpas_scope_current(),
										   $1.list[posn], $3,
										   DPAS_ITEM_VARIABLE, value, 0,
										   dpas_filename, dpas_linenum);
						}
						else
						{
							/* Allocate some memory to hold the global data */
							void *space = jit_calloc(1, jit_type_get_size($3));
							if(!space)
							{
								dpas_out_of_memory();
							}
							dpas_scope_add(dpas_scope_current(),
										   $1.list[posn], $3,
										   DPAS_ITEM_GLOBAL_VARIABLE, space, 0,
										   dpas_filename, dpas_linenum);
						}

libjit/dpas/dpas-scope.c  view on Meta::CPAN

	{
		/* Search through the "with" items for a field match */
		if(check_with)
		{
			item = scope->first_with;
			if(!item)
			{
				/* We are exiting from the top-most "with" scope
				   in the current procedure.  Ignore the rest of
				   the "with" scopes on the stack because we only
				   care about local/global variables from now on */
				check_with = 0;
			}
			while(item != 0)
			{
				if(dpas_type_find_name(item->type, name) != JIT_INVALID_NAME)
				{
					return item;
				}
				item = item->next;
			}

libjit/dpas/dpas-scope.c  view on Meta::CPAN

{
	return item->linenum;
}

int dpas_scope_level(dpas_scope_t scope)
{
	return scope->level;
}

/*
 * The global and current scopes.
 */
static dpas_scope_t global_scope = 0;
static dpas_scope_t current_scope = 0;

dpas_scope_t dpas_scope_current(void)
{
	if(!current_scope)
	{
		/* Create the global scope for the first time */
		global_scope = dpas_scope_create(0);

		/* Create a wrapper around the global scope to contain
		   the program-private definitions.  This allows the
		   program to override the global scope if it wants to */
		current_scope = dpas_scope_create(global_scope);
	}
	return current_scope;
}

dpas_scope_t dpas_scope_global(void)
{
	if(!current_scope)
	{
		dpas_scope_current();
	}
	return global_scope;
}

dpas_scope_t dpas_scope_push(void)
{
	current_scope = dpas_scope_create(dpas_scope_current());
	return current_scope;
}

void dpas_scope_pop(void)
{
	dpas_scope_t scope = dpas_scope_current();
	if(scope->parent && scope->parent != global_scope)
	{
		current_scope = scope->parent;
		dpas_scope_destroy(scope);
	}
}

int dpas_scope_is_module(void)
{
	return (dpas_scope_current()->parent == dpas_scope_global());
}

libjit/dpas/dpas-scope.h  view on Meta::CPAN

 */
typedef struct dpas_scope *dpas_scope_t;

/*
 * Opaque type that represents a scope item.
 */
typedef struct dpas_scope_item *dpas_scope_item_t;

/*
 * Create a new scope, with a specified parent scope.  If the parent
 * scope is NULL, then this creates the global scope.
 */
dpas_scope_t dpas_scope_create(dpas_scope_t parent);

/*
 * Destroy a scope that is no longer required.
 */
void dpas_scope_destroy(dpas_scope_t scope);

/*
 * Look up a name within a scope.  If "up" is non-zero, then also

libjit/dpas/dpas-scope.h  view on Meta::CPAN

 * Get the filename associated with a scope item.
 */
const char *dpas_scope_item_filename(dpas_scope_item_t item);

/*
 * Get the line number associated with a scope item.
 */
long dpas_scope_item_linenum(dpas_scope_item_t item);

/*
 * Get the level associated with the current scope (global is zero).
 */
int dpas_scope_level(dpas_scope_t scope);

/*
 * Get the current scope.
 */
dpas_scope_t dpas_scope_current(void);

/*
 * Get the global scope.
 */
dpas_scope_t dpas_scope_global(void);

/*
 * Create a new scope and push into it.
 */
dpas_scope_t dpas_scope_push(void);

/*
 * Pop the current scope level and destroy it.
 */
void dpas_scope_pop(void);

/*
 * Determine if the current scope is the module-global scope.
 */
int dpas_scope_is_module(void);

#ifdef	__cplusplus
};
#endif

#endif	/* _DPAS_SCOPE_H */

libjit/dpas/dpas-types.c  view on Meta::CPAN

jit_type_t dpas_type_boolean;
jit_type_t dpas_type_cboolean;
jit_type_t dpas_type_char;
jit_type_t dpas_type_string;
jit_type_t dpas_type_address;
jit_type_t dpas_type_nil;
jit_type_t dpas_type_size_t;
jit_type_t dpas_type_ptrdiff_t;

/*
 * Register a predefined type within the global scope.
 */
static void register_type(const char *name, jit_type_t type)
{
	dpas_scope_add(dpas_scope_global(), name, type, DPAS_ITEM_TYPE, 0, 0,
	               "(builtin)", 1);
}

/*
 * Get an integer type of a specific size.
 */
static jit_type_t get_int_type(unsigned int size)
{
	if(size == sizeof(jit_int))
	{

libjit/dpas/dpas-types.c  view on Meta::CPAN


	register_type("SysLongestInt", jit_type_sys_longlong);
	register_type("SysLongestCard", jit_type_sys_ulonglong);
	register_type("SysLongestWord", jit_type_sys_ulonglong);

	/*
	 * Register the "True" and "False" constants.
	 */
	value.type = dpas_type_boolean;
	value.un.int_value = 1;
	dpas_scope_add_const(dpas_scope_global(), "True", &value, "(builtin)", 1);
	value.type = dpas_type_boolean;
	value.un.int_value = 0;
	dpas_scope_add_const(dpas_scope_global(), "False", &value, "(builtin)", 1);
}

unsigned int dpas_type_find_name(jit_type_t type, const char *name)
{
	unsigned int field = jit_type_num_fields(type);
	const char *fname;
	while(field > 0)
	{
		--field;
		fname = jit_type_get_name(type, field);

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

#define	JIT_MANGLE_PUBLIC			0x0001
#define	JIT_MANGLE_PROTECTED		0x0002
#define	JIT_MANGLE_PRIVATE			0x0003
#define	JIT_MANGLE_STATIC			0x0008
#define	JIT_MANGLE_VIRTUAL			0x0010
#define	JIT_MANGLE_CONST			0x0020
#define	JIT_MANGLE_EXPLICIT_THIS	0x0040
#define	JIT_MANGLE_IS_CTOR			0x0080
#define	JIT_MANGLE_IS_DTOR			0x0100
#define	JIT_MANGLE_BASE				0x0200
char *jit_mangle_global_function
	(const char *name, jit_type_t signature, int form) JIT_NOTHROW;
char *jit_mangle_member_function
	(const char *class_name, const char *name,
	 jit_type_t signature, int form, int flags) JIT_NOTHROW;

#ifdef	__cplusplus
};
#endif

#endif /* _JIT_DYNAMIC_H */

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

					}
				}
			}
		}
	}

	return 1;
}

static int
compute_global_live_sets(_jit_cfg_t cfg)
{
	int change;
	int index, succ_index;
	_jit_node_t node;
	_jit_node_t succ;
	_jit_bitset_t bitset;

	if(!_jit_bitset_allocate(&bitset, cfg->num_values))
	{
		return 0;

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

	}

	return cfg;
}

int
_jit_cfg_compute_liveness(_jit_cfg_t cfg)
{
	return (create_value_entries(cfg)
		&& compute_local_live_sets(cfg)
		&& compute_global_live_sets(cfg));
}

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

			/* 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 */
			_jit_gen_insn(gen, func, block, insn);

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;

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

	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. */
		gen->touched = jit_regused_init;
	}
	else
	{
		gen->touched = gen->permanent;
	}

	/* Reset the epilog fixup list */
	gen->epilog_fixup = 0;
}

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

		state->func->no_throw = 1;
	}
	if(!state->func->builder->ordinary_return)
	{
		state->func->no_return = 1;
	}

	/* Compute liveness and "next use" information for this function */
	_jit_function_compute_liveness(state->func);

	/* Allocate global registers to variables within the function */
#ifndef JIT_BACKEND_INTERP
	_jit_regs_alloc_global(&state->gen, state->func);
#endif
}

/*
 * Run codegen.
 */
static void
codegen(_jit_compile_t *state)
{
	jit_function_t func = state->func;

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

#define VER_DEF_NONE	0		/* No version */
#define VER_DEF_CURRENT	1		/* Current version */
#define VER_DEF_NUM	2		/* Given version number */

/* Legal values for vd_flags (version information flags).  */
#define VER_FLG_BASE	0x1		/* Version definition of file itself */
#define VER_FLG_WEAK	0x2		/* Weak version identifier */

/* Versym symbol index values.  */
#define	VER_NDX_LOCAL		0	/* Symbol is local.  */
#define	VER_NDX_GLOBAL		1	/* Symbol is global.  */
#define	VER_NDX_LORESERVE	0xff00	/* Beginning of reserved entries.  */
#define	VER_NDX_ELIMINATE	0xff01	/* Symbol is to be eliminated.  */

/* Auxialiary version information.  */

typedef struct
{
  Elf32_Word	vda_name;		/* Version or dependency names */
  Elf32_Word	vda_next;		/* Offset in bytes to next verdaux
					   entry */

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

#define SHT_MIPS_PIXIE	       0x70000023
#define SHT_MIPS_XLATE	       0x70000024
#define SHT_MIPS_XLATE_DEBUG   0x70000025
#define SHT_MIPS_WHIRL	       0x70000026
#define SHT_MIPS_EH_REGION     0x70000027
#define SHT_MIPS_XLATE_OLD     0x70000028
#define SHT_MIPS_PDR_EXCEPTION 0x70000029

/* Legal values for sh_flags field of Elf32_Shdr.  */

#define SHF_MIPS_GPREL	 0x10000000	/* Must be part of global data area */
#define SHF_MIPS_MERGE	 0x20000000
#define SHF_MIPS_ADDR	 0x40000000
#define SHF_MIPS_STRINGS 0x80000000
#define SHF_MIPS_NOSTRIP 0x08000000
#define SHF_MIPS_LOCAL	 0x04000000
#define SHF_MIPS_NAMES	 0x02000000
#define SHF_MIPS_NODUPE	 0x01000000


/* Symbol tables.  */

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

} Elf32_RegInfo;

/* Entries found in sections of type SHT_MIPS_OPTIONS.  */

typedef struct
{
  unsigned char kind;		/* Determines interpretation of the
				   variable part of descriptor.  */
  unsigned char size;		/* Size of descriptor, including header.  */
  Elf32_Section section;	/* Section header index of section affected,
				   0 for global options.  */
  Elf32_Word info;		/* Kind-specific information.  */
} Elf_Options;

/* Values for `kind' field in Elf_Options.  */

#define ODK_NULL	0	/* Undefined.  */
#define ODK_REGINFO	1	/* Register usage information.  */
#define ODK_EXCEPTIONS	2	/* Exception processing options.  */
#define ODK_PAD		3	/* Section padding options.  */
#define ODK_HWPATCH	4	/* Hardware workarounds performed */

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

@*/
void
jit_init(void)
{
	static int init_done = 0;

	/* Make sure that the thread subsystem is initialized */
	_jit_thread_init();

	/* Make sure that the initialization is done only once
	   (requires the global lock initialized above) */
	jit_mutex_lock(&_jit_global_lock);
	if(init_done)
	{
		goto done;
	}
	init_done = 1;

#ifdef JIT_USE_SIGNALS
	/* Initialize the signal handlers */
	_jit_signal_init();
#endif

	/* Initialize the virtual memory system */
	jit_vmem_init();

	/* Initialize the backend */
	_jit_init_backend();

done:
	jit_mutex_unlock(&_jit_global_lock);
}

/*@
 * @deftypefun int jit_uses_interpreter (void)
 * Determine if the JIT uses a fall-back interpreter to execute code
 * rather than generating and executing native code.  This can be
 * called prior to @code{jit_init}.
 * @end deftypefun
@*/
int

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

		   pointer. Adjust the current offset accordingly */
		offset += jit_value_get_nint_constant(insn->value2);
		value = insn->value1;
		insn = find_base_insn(func, iter, value, &last);
		last = 0;
	}
	if(insn && insn->opcode == JIT_OP_ADDRESS_OF && !last)
	{
		/* Shift the "address_of" instruction down, to make
		   it easier for the code generator to handle field
		   accesses within local and global variables */
		value = jit_insn_address_of(func, insn->value1);
		if(!value)
		{
			return 0;
		}
	}
	return apply_binary
		(func, _jit_load_opcode(JIT_OP_LOAD_RELATIVE_SBYTE, type, 0, 0), value,
		 jit_value_create_nint_constant(func, jit_type_nint, offset), type);
}

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

		   pointer. Adjust the current offset accordingly */
		offset += jit_value_get_nint_constant(insn->value2);
		dest = insn->value1;
		insn = find_base_insn(func, iter, value, &last);
		last = 0;
	}
	if(insn && insn->opcode == JIT_OP_ADDRESS_OF && !last)
	{
		/* Shift the "address_of" instruction down, to make
		   it easier for the code generator to handle field
		   accesses within local and global variables */
		dest = jit_insn_address_of(func, insn->value1);
		if(!dest)
		{
			return 0;
		}
	}

	offset_value = jit_value_create_nint_constant(func, jit_type_nint, offset);
	if(!offset_value)
	{

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

	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.
 */

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


@*/

/*
 * Dump debug information about the register allocation state.
 */
#undef JIT_REG_DEBUG

/*
 * Minimum number of times a candidate must be used before it
 * is considered worthy of putting in a global register.
 */
#define	JIT_MIN_USED		3

/*
 * Use is_register_occupied() function.
 */
#undef IS_REGISTER_OCCUPIED

/*
 * Check if the register is on the register stack.

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

static int
is_register_alive(jit_gencode_t gen, _jit_regs_t *regs, int reg)
{
	int index, usage;

	if(reg < 0)
	{
		return 0;
	}

	/* Assume that a global register is always alive unless it is to be
	   computed right away. */
	if(jit_reg_is_used(gen->permanent, reg))
	{
		if(!regs->ternary
		   && regs->descs[0].value
		   && regs->descs[0].value->has_global_register
		   && regs->descs[0].value->global_reg == reg)
		{
			return 0;
		}
		return 1;
	}

	if(gen->contents[reg].is_long_end)
	{
		reg = get_long_pair_start(reg);
	}

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

 * that may need to be evicted from it.
 */
static int
is_register_occupied(jit_gencode_t gen, _jit_regs_t *regs, int reg)
{
	if(reg < 0)
	{
		return 0;
	}

	/* Assume that a global register is always occupied. */
	if(jit_reg_is_used(gen->permanent, reg))
	{
		return 1;
	}

	if(gen->contents[reg].is_long_end)
	{
		reg = get_long_pair_start(reg);
	}
	if(gen->contents[reg].num_values)

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

	{
		flags = CLOBBER_INPUT_VALUE;
	}
	else
	{
		flags = CLOBBER_NONE;
	}

	if(flags == CLOBBER_NONE)
	{
		if(regs->descs[index].value->has_global_register
		   && regs->descs[index].value->global_reg == reg)
		{
			return CLOBBER_NONE;
		}
		if(regs->descs[index].value->in_register
		   && regs->descs[index].value->reg == reg)
		{
			return CLOBBER_NONE;
		}
	}

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

			if(desc->thrash)
			{
				reg = -1;
				other_reg = -1;
			}
		}

		/* See if the value needs to be loaded or copied or none. */
		if(reg != desc->reg)
		{
			if(desc->value->has_global_register)
			{
				desc->copy = (desc->value->global_reg != desc->reg);
			}
			else if(reg < 0)
			{
				desc->load = 1;
			}
			else
			{
				desc->copy = 1;
			}
		}

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

		{
			++(regs->wanted_stack_count);
			if(!desc->load && !desc->copy)
			{
				++(regs->loaded_stack_count);
			}
		}
#endif
	}

	/* See if the value clobbers a global register. In this case the global
	   register is pushed onto stack before the instruction and popped back
	   after it. */
	if(!desc->copy
	   && (!desc->value->has_global_register || desc->value->global_reg != desc->reg)
	   && (jit_reg_is_used(gen->permanent, desc->reg)
	       || (desc->other_reg >= 0 && jit_reg_is_used(gen->permanent, desc->other_reg))))
	{
		desc->kill = 1;
	}

	/* Set clobber flags (this indicates registers to be spilled). */
	if((clobber & CLOBBER_REG) != 0)
	{
		jit_reg_set_used(regs->clobber, desc->reg);

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

	{
		jit_reg_set_used(regs->clobber, desc->other_reg);
	}

#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);

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

#endif
}

/*
 * 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
compute_spill_cost(jit_gencode_t gen, _jit_regs_t *regs, int reg, int other_reg)
{
	int cost, index, usage;
	jit_value_t value;

	if(gen->contents[reg].is_long_end)
	{

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

		usage = value_usage(regs, value);
		if((usage & VALUE_DEAD) != 0)
		{
			/* the value is not spilled */
			continue;
		}
		if((usage & VALUE_LIVE) != 0 && (usage & VALUE_USED) == 0)
		{
			/* the value has to be spilled anyway */
			/* NOTE: This is true for local register allocation,
			   review for future global allocator. */
			continue;
		}
		if(value->has_global_register)
		{
			if(value->in_global_register)
			{
				cost += COST_SPILL_CLEAN_GLOBAL;
			}
			else
			{
				cost += COST_SPILL_DIRTY_GLOBAL;
			}
		}
		else
		{

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

			usage = value_usage(regs, value);
			if((usage & VALUE_DEAD) != 0)
			{
				/* the value is not spilled */
				continue;
			}
			if((usage & VALUE_LIVE) != 0 && (usage & VALUE_USED) == 0)
			{
				/* the value has to be spilled anyway */
				/* NOTE: This is true for local register allocation,
				   review for future global allocator. */
				continue;
			}
			if(value->has_global_register)
			{
				if(value->in_global_register)
				{
					cost += COST_SPILL_CLEAN_GLOBAL;
				}
				else
				{
					cost += COST_SPILL_DIRTY_GLOBAL;
				}
			}
			else
			{

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

}

static int
thrashes_value(jit_gencode_t gen,
	       _jit_regdesc_t *desc, int reg, int other_reg,
	       _jit_regdesc_t *desc2)
{
	int reg2, other_reg2;

#if ALLOW_CLOBBER_GLOBAL
	if(desc2->value->has_global_register)
	{
		if(desc2->value->global_reg == reg)
		{
			if(desc && desc2->value == desc->value)
			{
				return 0;
			}
			return 1;
		}
		if(desc2->value->global_reg == other_reg)
		{
			return 1;
		}
	}
#endif

	if(desc2->value->in_register)
	{
		reg2 = desc2->value->reg;
		if(reg2 == reg)

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

		}

		other_reg = jit_reg_get_pair(regs->descs[0].value->type, reg);
		if(other_reg >= 0 && jit_reg_is_used(gen->inhibit, other_reg))
		{
			continue;
		}

		if(jit_reg_is_used(gen->permanent, reg))
		{
			if(!regs->descs[0].value->has_global_register
			   || regs->descs[0].value->global_reg != reg)
			{
				/* It is not allowed to assign an output value to a global
				   register unless it is the very value the global register
				   contains. */
				continue;
			}
			if(regs->free_dest)
			{
				if(regs->descs[0].early_clobber
				   && regs->descs[0].value->in_global_register)
				{
					if(regs->descs[0].value == regs->descs[1].value)
					{
						continue;
					}
					if(regs->descs[0].value == regs->descs[2].value)
					{
						continue;
					}
				}
				use_cost = 0;
			}
			else if(regs->descs[0].value->in_global_register)
			{
				if(regs->descs[0].value == regs->descs[1].value)
				{
					use_cost = 0;
				}
				else if(regs->descs[0].value == regs->descs[2].value)
				{
					if(regs->commutative)
					{
						/* This depends on choose_input_order()

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

#endif
				else
				{
					use_cost = COST_THRASH;
				}
			}
			else
			{
				use_cost = COST_COPY;
			}
			if(regs->descs[0].value->has_global_register)
			{
				use_cost += COST_GLOBAL_BIAS;
			}
		}

		if(!jit_reg_is_used(regs->clobber, reg)
		   && !(other_reg >= 0 && jit_reg_is_used(regs->clobber, other_reg)))
		{
			use_cost += compute_spill_cost(gen, regs, reg, other_reg);
		}

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

 */
static void
choose_input_order(jit_gencode_t gen, _jit_regs_t *regs)
{
	jit_value_t value;

	value = regs->descs[2].value;
	if(value && value != regs->descs[1].value
	   && ((value->in_register
		&& value->reg == regs->descs[0].reg)
	       || (value->in_global_register
		   && value->global_reg == regs->descs[0].reg)))
	{
#ifdef JIT_REG_STACK
		if(regs->reversible && regs->no_pop)
		{
			regs->dest_input_index = 2;
		}
		else
#endif
		{
			if(regs->commutative)

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

		{
			continue;
		}

		other_reg = jit_reg_get_pair(desc->value->type, reg);
		if(other_reg >= 0 && jit_reg_is_used(regs->assigned, other_reg))
		{
			continue;
		}

		if((desc->value->in_global_register && desc->value->global_reg == reg)
		   || (desc->value->in_register && desc->value->reg == reg))
		{
			use_cost = 0;
		}
		else
		{
			use_cost = COST_COPY;
		}
		if(desc2->value->has_global_register && desc2->value->global_reg != reg)
		{
			use_cost += COST_GLOBAL_BIAS;
		}

		if(index != 0 && regs->ternary && regs->descs[0].value
		   && thrashes_value(gen, desc, reg, other_reg, &regs->descs[0]))
		{
			use_cost += COST_THRASH;
		}
		else if(index != 1 && regs->descs[1].value

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

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)

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

		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.

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

 */
static void
free_value(jit_gencode_t gen, jit_value_t value, int reg, int other_reg, int temp)
{
#ifdef JIT_REG_DEBUG
	printf("free_value(value = ");
	jit_dump_value(stdout, jit_value_get_function(value), value, 0);
	printf(", reg = %d, other_reg = %d, temp = %d)\n", reg, other_reg, temp);
#endif

	/* Never free global registers. */
	if(value->has_global_register && value->global_reg == reg)
	{
		return;
	}

	if(gen->contents[reg].num_values == 1)
	{
		if(temp)
		{
			unbind_value(gen, value, reg, other_reg);
			bind_temporary(gen, reg, other_reg);

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

 * 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
	/* First take care of values that reside in global registers. */
	if(value->has_global_register)
	{
		/* Never free global registers. */
		if(value->global_reg == reg)
		{
			return;
		}

		if(!value->in_global_register)
		{
			_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)

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

#ifdef JIT_REG_DEBUG
	printf("load_input_value(%d)\n", index);
#endif

	desc = &regs->descs[index];
	if(!desc->value || desc->duplicate)
	{
		return;
	}

	if(desc->value->has_global_register)
	{
		if(desc->value->in_global_register && desc->value->global_reg == desc->reg)
		{
			return;
		}
		if(desc->value->in_register && desc->value->reg == desc->reg)
		{
			update_age(gen, desc);
			return;
		}
		_jit_gen_load_value(gen, desc->reg, desc->other_reg, desc->value);
	}

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

		}
		free_value(gen, desc->value, reg, other_reg, 0);
	}

#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

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

	{
		save_value(gen, desc->value, desc->reg, desc->other_reg, 1);
	}

#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

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

			if(strcmp(jit_reg_name(reg), name) == 0)
			{
				return reg;
			}
		}
	}
	return -1;
}

/*@
 * @deftypefun void _jit_regs_alloc_global (jit_gencode_t gen, jit_function_t func)
 * Perform global register allocation on the values in @code{func}.
 * This is called during function compilation just after variable
 * liveness has been computed.
 * @end deftypefun
@*/
void _jit_regs_alloc_global(jit_gencode_t gen, jit_function_t func)
{
#if JIT_NUM_GLOBAL_REGS != 0
	jit_value_t candidates[JIT_NUM_GLOBAL_REGS];
	int num_candidates = 0;
	int index, reg, posn, num;
	jit_pool_block_t block;
	jit_value_t value, temp;

	/* If the function has a "try" block, then don't do global allocation
	   as the "longjmp" for exception throws will wipe out global registers */
	if(func->has_try)
	{
		return;
	}

	/* If the current function involves a tail call, then we don't do
	   global register allocation and we also prevent the code generator
	   from using any of the callee-saved registers.  This simplifies
	   tail calls, which don't have to worry about restoring such registers */
	if(func->builder->has_tail_call)
	{
		for(reg = 0; reg < JIT_NUM_REGS; ++reg)
		{
			if((jit_reg_flags(reg) & (JIT_REG_FIXED|JIT_REG_CALL_USED)) == 0)
			{
				jit_reg_set_used(gen->permanent, reg);
			}

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

	num = (int)(func->builder->value_pool.elems_per_block);
	while(block != 0)
	{
		if(!(block->next))
		{
			num = (int)(func->builder->value_pool.elems_in_last);
		}
		for(posn = 0; posn < num; ++posn)
		{
			value = (jit_value_t)(block->data + posn * sizeof(struct _jit_value));
			if(value->global_candidate && value->usage_count >= JIT_MIN_USED &&
			   !(value->is_addressable) && !(value->is_volatile))
			{
				/* Insert this candidate into the list, ordered on count */
				index = 0;
				while(index < num_candidates &&
				      value->usage_count <= candidates[index]->usage_count)
				{
					++index;
				}
				while(index < num_candidates)

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

				{
					candidates[num_candidates++] = value;
				}
			}
		}
		block = block->next;
	}

	/* Allocate registers to the candidates.  We allocate from the top-most
	   register in the allocation order, because some architectures like
	   PPC require global registers to be saved top-down for efficiency */
	reg = JIT_NUM_REGS - 1;
	for(index = 0; index < num_candidates; ++index)
	{
		while(reg >= 0 && (jit_reg_flags(reg) & JIT_REG_GLOBAL) == 0)
		{
			--reg;
		}
		candidates[index]->has_global_register = 1;
		candidates[index]->in_global_register = 1;
		candidates[index]->global_reg = (short)reg;
		jit_reg_set_used(gen->touched, reg);
		jit_reg_set_used(gen->permanent, reg);
		--reg;
	}

#endif
}

/*@
 * @deftypefun void _jit_regs_init_for_block (jit_gencode_t gen)

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

		}
	}
#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

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

int
_jit_regs_load_value(jit_gencode_t gen, jit_value_t value, int destroy, int used_again)
{
	int type;
	int reg, other_reg;
	int spill_cost;
	int suitable_reg, suitable_other_reg;
	int suitable_cost;
	int suitable_age;

	/* If the value is in a global register, and we are not going
	   to destroy the value, then use the global register itself.
	   This will avoid a redundant register copy operation */
	if(value->in_global_register && !destroy)
	{
		return value->global_reg;
	}

	/* If the value is already in a register, then try to use that register */
	if(value->in_register && (!destroy || !used_again))
	{
		reg = value->reg;
		if(!used_again)
		{
			other_reg = jit_reg_get_pair(value->type, reg);
			free_value(gen, value, reg, other_reg, 1);

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

			continue;
		}

		if(!jit_reg_is_used(regs->clobber, reg))
		{
			continue;
		}
		if(jit_reg_is_used(gen->permanent, reg))
		{
#ifdef IS_REGISTER_OCCUPIED
			/* If the op computes the value assigned to the global
			   register then it is not really clobbered. */
			if(!regs->ternary
			   && regs->descs[0].value
			   && regs->descs[0].value->has_global_register
			   && regs->descs[0].value->global_reg == reg)
			{
				continue;
			}
#endif
			/* Oops, the global register is going to be clobbered. Save
			   it on the stack in order to restore after the op. */
#ifdef JIT_REG_DEBUG
			printf("*** Spill global register: %d ***\n", reg);
#endif
			if(regs->branch)
			{
				/* After the branch is taken there is no way
				   to load the global register back. */
				jit_exception_builtin(JIT_RESULT_COMPILE_ERROR);
			}
			_jit_gen_spill_global(gen, reg, 0);
			continue;
		}

#ifdef JIT_REG_STACK
		/* If this is a stack register, then we need to find the
		   register that contains the top-most stack position,
		   because we must spill stack registers from top down.
		   As we spill each one, something else will become the top */
		if(IS_STACK_REG(reg))
		{

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

		commit_output_value(gen, regs, 0);
	}
#endif
	else
	{
		commit_input_value(gen, regs, 2, 0);
		commit_input_value(gen, regs, 1, 0);
		commit_output_value(gen, regs, 1);
	}

	/* Load clobbered global registers. */
	for(reg = JIT_NUM_REGS - 1; reg >= 0; reg--)
	{
		if(jit_reg_is_used(regs->clobber, reg) && jit_reg_is_used(gen->permanent, reg))
		{
#ifdef IS_REGISTER_OCCUPIED
			if(!regs->ternary
			   && regs->descs[0].value
			   && regs->descs[0].value->has_global_register
			   && regs->descs[0].value->global_reg == reg)
			{
				continue;
			}
#endif
			_jit_gen_load_global(gen, reg, 0);
		}
	}

#ifdef JIT_REG_DEBUG
	dump_regs(gen, "leave _jit_regs_commit");
#endif
}

void
_jit_regs_begin(jit_gencode_t gen, _jit_regs_t *regs, int space)

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

	jit_regused_t	clobber;

#ifdef JIT_REG_STACK
	int		wanted_stack_count;
	int		loaded_stack_count;
#endif

} _jit_regs_t;

int _jit_regs_lookup(char *name);
void _jit_regs_alloc_global(jit_gencode_t gen, jit_function_t func);
void _jit_regs_init_for_block(jit_gencode_t gen);
void _jit_regs_spill_all(jit_gencode_t gen);
void _jit_regs_set_incoming(jit_gencode_t gen, int reg, jit_value_t value);
void _jit_regs_set_outgoing(jit_gencode_t gen, int reg, jit_value_t value);
void _jit_regs_clear_all_outgoing(jit_gencode_t gen);
void _jit_regs_force_out(jit_gencode_t gen, jit_value_t value, int is_dest);
int _jit_regs_load_value(jit_gencode_t gen, jit_value_t value, int destroy, int used_again);

void _jit_regs_init(jit_gencode_t gen, _jit_regs_t *regs, int flags);

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

 * Setup or teardown the ARM code output process.
 */
#define	jit_cache_setup_output(needed)	\
	arm_inst_buf inst; \
	jit_gen_load_inst_ptr(gen, inst)
#define	jit_cache_end_output()	\
	jit_gen_save_inst_ptr(gen, inst)

/** 
 * Spill the content of register "reg" (and "other_reg", if it's different from -1) 
 * into the global register or the memory area associated with "value"
 * NB: it doesn't set value->in_global_register or value->in_frame. The caller has to
 * take care of that.
 */
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(flush_if_too_far(gen))
	{
		jit_gen_load_inst_ptr(gen, inst);
	}

	/* Output an appropriate instruction to spill the value */
	if(value->has_global_register)
	{
		if (IS_FLOAT_REG(reg))
		{
			printf("TODO:Copy from float reg to global reg is not handled properly in %s\n", __FILE__);
			abort();
		}
		else
		{
			arm_mov_reg_reg(inst, _jit_reg_info[value->global_reg].cpu_reg, _jit_reg_info[reg].cpu_reg);
		}
	}
	else
	{
		_jit_gen_fix_value(value);
		offset = (int)(value->frame_offset);
		if(IS_WORD_REG(reg))
		{
			arm_store_membase(inst, reg, ARM_FP, offset);
			if(other_reg != -1)

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

				{
					mov_freg_imm_64
						(gen, &inst, _jit_reg_info[reg].cpu_reg,
					     ((int *)&float64_value)[0],
					     ((int *)&float64_value)[1]);
				}
			}
			break;
		}
	}
	else if(value->in_global_register)
	{
		/* Load the value out of a global register */
		if(IS_FLOAT_REG(reg))
		{
			/* Load into a floating point register */
#ifdef JIT_ARM_HAS_VFP
			/* Vector Floating Point instructions */
			if(jit_type_normalize(value->type)->kind == JIT_TYPE_FLOAT32)
			{
				arm_mov_float_reg(inst,
						  _jit_reg_info[reg].cpu_reg,
						  _jit_reg_info[value->global_reg].cpu_reg);
			}
			else
			{
				//JIT_TYPE_FLOAT64 or JIT_TYPE_NFLOAT
				arm_mov_double_reg_reg(inst,
						       _jit_reg_info[reg].cpu_reg,
						       _jit_reg_info[value->global_reg].cpu_reg,
						       _jit_reg_info[value->global_reg].cpu_reg + 1);
			}
#endif
#ifdef JIT_ARM_HAS_FPA
			/* Floating Point Architecture instructions */
			TODO();
			abort();
#endif
		}
		else
		{
			/* Load into a general-purpose register */
			arm_mov_reg_reg(inst,
					_jit_reg_info[reg].cpu_reg,
					_jit_reg_info[value->global_reg].cpu_reg);
		}
	}
	else if(value->in_register)
	{
		/* The value is already in another register. Move it */
		switch(jit_type_normalize(value->type)->kind)
		{
			case JIT_TYPE_SBYTE:
			case JIT_TYPE_UBYTE:
			case JIT_TYPE_SHORT:

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

				TODO();
				abort();
#endif
			}
			break;
		}
	}
	else
	{
		/* Load from the stack */
		assert(!value->in_global_register && !value->is_constant && !value->in_register);
		
		/* Fix the position of the value in the stack frame */
		_jit_gen_fix_value(value);
		offset = (int)(value->frame_offset);

		switch(jit_type_normalize(value->type)->kind)
		{
			case JIT_TYPE_SBYTE:
			{
				arm_load_membase_sbyte(inst, _jit_reg_info[reg].cpu_reg,

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

	if(flush_if_too_far(gen))
	{
		jit_gen_load_inst_ptr(gen, inst);
	}

	if(value->is_constant)
	{
		TODO();
		abort();
	}
	else if(value->has_global_register)
	{
		/*
		 * This value has been assinged a global register. This means
		 * that it can use that register, but not necessarily that it's
		 * already in it!!
		 */
		
		/* Ensure that the value is already in the global_register */
		if (!value->in_global_register)
		{	
			/* Find the other register in a long pair */
			int reg = value->reg;
			int other_reg = jit_reg_current_other_reg(gen,reg);
			
			//Spill to the global register
			_jit_gen_spill_reg(gen, reg, other_reg, value);
			value->in_global_register=1;

			/* A new instruction has probably been generated by _jit_gen_spill_reg: reload the inst pointer */
			jit_gen_load_inst_ptr(gen, inst);
		}
		/* Load the value out of a global register */
		arm_mov_reg_reg(inst, _jit_reg_info[reg].cpu_reg,
						_jit_reg_info[value->global_reg].cpu_reg);
	}
	else
	{
		/* Fix the position of the value in the stack frame */
		_jit_gen_fix_value(value);
		offset = (int)(value->frame_offset);

		/* Ensure that the value is already in the stack frame */
		if(value->in_register)
		{

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

			TODO();
			abort();
		}
		
	}

	/* End the code output process */
	jit_cache_end_output();
}

void _jit_gen_spill_global(jit_gencode_t gen, int reg, jit_value_t value)
{
	/* TODO: Implement if ARM needs it. */
}

void _jit_gen_load_global(jit_gencode_t gen, int reg, jit_value_t value)
{
	jit_cache_setup_output(32);
	arm_load_membase(inst, _jit_reg_info[value->global_reg].cpu_reg,
					 ARM_FP, value->frame_offset);
	jit_cache_end_output();
}

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;

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

		fixup = next;
	}
	block->fixup_list = 0;
}

void _jit_gen_end_block(jit_gencode_t gen, jit_block_t block)
{
	/* Nothing to do here for ARM */
}

int _jit_gen_is_global_candidate(jit_type_t type)
{
	switch(jit_type_remove_tags(type)->kind)
	{
		case JIT_TYPE_INT:
		case JIT_TYPE_UINT:
		case JIT_TYPE_NINT:
		case JIT_TYPE_NUINT:
		case JIT_TYPE_PTR:
		case JIT_TYPE_SIGNATURE:	return 1;
	}

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


/*
 * Determine if this ARM core uses floating point registers available 
 */
#if defined(JIT_ARM_HAS_FPA) || defined(JIT_ARM_HAS_VFP)
# define JIT_ARM_HAS_FLOAT_REGS	1
#endif

/*
 * Information about all of the registers, in allocation order.
 * We use r0-r5 for general-purpose values and r6-r8 for globals.
 *
 * The floating-point registers are only present on some ARM cores.
 *
 * The definitions of the used flags are in jit-rules.h
 */
#define	JIT_REG_INFO	\
	{"r0",   0,  1, JIT_REG_WORD | JIT_REG_LONG | JIT_REG_CALL_USED}, \
	{"r1",   1, -1, JIT_REG_WORD | JIT_REG_CALL_USED}, \
	{"r2",   2,  3, JIT_REG_WORD | JIT_REG_LONG | JIT_REG_CALL_USED}, \
	{"r3",   3, -1, JIT_REG_WORD | JIT_REG_CALL_USED}, \

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

	{"d12",   12, -1, JIT_REG_ARM_FLOAT64},	\
	{"d13",   13, -1, JIT_REG_ARM_FLOAT64},	\
	{"d14",   14, -1, JIT_REG_ARM_FLOAT64},	\
	{"d15",   15, -1, JIT_REG_ARM_FLOAT64},

/* JIT_NUM_REGS is the total number of registers (general purpose+floating point) */
#define JIT_NUM_REGS		40

#endif

/* The number of global registers */
#define	JIT_NUM_GLOBAL_REGS	3

//Floating point registers are NOT handled like a stack
#undef JIT_REG_STACK

/*
 * Define to 1 if we should always load values into registers
 * before operating on them.  i.e. the CPU does not have reg-mem
 * and mem-reg addressing modes.
 */

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

@item JIT_REG_FIXED
This register has a fixed meaning and cannot be used for general allocation.

@item JIT_REG_CALL_USED
This register will be destroyed by a function call.

@item JIT_REG_IN_STACK
This register is in a stack-like arrangement.

@item JIT_REG_GLOBAL
This register is a candidate for global register allocation.
@end table

A CPU may have some registers arranged into a stack.  In this case
operations can typically only occur at the top of the stack, and
may automatically pop values as a side-effect of the operation.
An example of such architecture is x87 floating point unit.  Such
CPU requires three additional macros.

@table @code

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

up to @code{JIT_REG_STACK_END} must also have the @code{JIT_REG_IN_STACK}
flag set.

@subsection Other architecture macros

@noindent
The rule file may also have definitions of the following macros:

@table @code
@item JIT_NUM_GLOBAL_REGS
The number of registers that are used for global register allocation.
Set to zero if global register allocation should not be used.

@item JIT_ALWAYS_REG_REG
Define this to 1 if arithmetic operations must always be performed
on registers.  Define this to 0 if register/memory and memory/register
operations are possible.

@item JIT_PROLOG_SIZE
If defined, this indicates the maximum size of the function prolog.

@item JIT_FUNCTION_ALIGNMENT

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

 * with @code{_jit_gen_fix_value}.
 * @end deftypefun
@*/
void _jit_gen_load_value
	(jit_gencode_t gen, int reg, int other_reg, jit_value_t value)
{
	/* Registers are not used in the interpreted back end */
}

/*@
 * @deftypefun void _jit_gen_spill_global (jit_gencode_t @var{gen}, int @var{reg}, jit_value_t @var{value})
 * Spill the contents of @var{value} from its corresponding global register.
 * This is used in rare cases when a machine instruction requires its operand
 * to be in the specific register that happens to be global. In such cases the
 * register is spilled just before the instruction and loaded back immediately
 * after it.
 * @end deftypefun
@*/
void _jit_gen_spill_global(jit_gencode_t gen, int reg, jit_value_t value)
{
	/* Global registers are not used in the interpreted back end */
}

/*@
 * @deftypefun void _jit_gen_load_global (jit_gencode_t @var{gen}, int @var{reg}, jit_value_t @var{value})
 * Load the contents of @var{value} into its corresponding global register.
 * This is used at the head of a function to pull parameters out of stack
 * slots into their global register copies.
 * @end deftypefun
@*/
void _jit_gen_load_global(jit_gencode_t gen, int reg, jit_value_t value)
{
	/* Global registers are not used in the interpreted back end */
}

/*@
 * @deftypefun void _jit_gen_exch_top (jit_gencode_t @var{gen}, int @var{reg})
 * Generate instructions to exchange the contents of the top stack register
 * with a stack register specified by the @var{reg} argument.
 *
 * It needs to be implemented only by backends that support stack registers.

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

 * has been reached.
 * @end deftypefun
@*/
void _jit_gen_end_block(jit_gencode_t gen, jit_block_t block)
{
	/* Reset the working area size to zero for the next block */
	gen->working_area = 0;
}

/*@
 * @deftypefun int _jit_gen_is_global_candidate (jit_type_t @var{type})
 * Determine if @var{type} is a candidate for allocation within
 * global registers.
 * @end deftypefun
@*/
int _jit_gen_is_global_candidate(jit_type_t type)
{
	/* Global register allocation is not used by the interpreter */
	return 0;
}

/*@
 * @deftypefun int _jit_reg_get_pair (jit_type_t @var{type}, int @var{reg})
 * Determine if a type requires a register pair. If so then for the specified
 * register @var{reg} return the other register of the corresponding pair.
 * Return -1 if no pair is required.

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

		/* Align the new frame_size for the value */
		frame_size = (frame_size + (alignment - 1)) & ~(alignment - 1);

		value->block->func->builder->frame_size = frame_size;
		value->frame_offset = -frame_size;
		value->has_frame_offset = 1;
	}
}

void
_jit_gen_spill_global(jit_gencode_t gen, int reg, jit_value_t value)
{
	jit_cache_setup_output(16);
	if(value)
	{
		jit_type_t type = jit_type_normalize(value->type);

		_jit_gen_fix_value(value);

		_spill_reg(&inst, type, value->global_reg, value->frame_offset);
	}
	else
	{
		x86_64_push_reg_size(inst, _jit_reg_info[reg].cpu_reg, 8);
	}
	jit_cache_end_output();
}

void
_jit_gen_load_global(jit_gencode_t gen, int reg, jit_value_t value)
{
	jit_cache_setup_output(16);
	if(value)
	{
		x86_64_mov_reg_membase_size(inst,
			_jit_reg_info[value->global_reg].cpu_reg,
			X86_64_RBP, value->frame_offset, 8);
	}
	else
	{
		x86_64_pop_reg_size(inst, _jit_reg_info[reg].cpu_reg, 8);
	}
	jit_cache_end_output();
}

void
_jit_gen_spill_reg(jit_gencode_t gen, int reg,
				   int other_reg, jit_value_t value)
{
	jit_type_t type;

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

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

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

	/* Get the normalized type */
	type = jit_type_normalize(value->type);

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

						{
							/* We have to use an extra general register */
							TODO();
						}
					}
				}
			}
			break;
		}
	}
	else if(value->in_register || value->in_global_register)
	{
		if(value->in_register)
		{
			src_reg = value->reg;
			other_src_reg = -1;
		}
		else
		{
			src_reg = value->global_reg;
			other_src_reg = -1;
		}

		switch(type->kind)
		{
#if 0
			case JIT_TYPE_SBYTE:
			{
				x86_widen_reg(inst, _jit_reg_info[reg].cpu_reg,
					      _jit_reg_info[src_reg].cpu_reg, 1, 0);

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

	block->fixup_absolute_list = 0;
}

void
_jit_gen_end_block(jit_gencode_t gen, jit_block_t block)
{
	/* Nothing to do here for x86 */
}

int
_jit_gen_is_global_candidate(jit_type_t type)
{
	switch(jit_type_remove_tags(type)->kind)
	{
		case JIT_TYPE_SBYTE:
		case JIT_TYPE_UBYTE:
		case JIT_TYPE_SHORT:
		case JIT_TYPE_USHORT:
		case JIT_TYPE_INT:
		case JIT_TYPE_UINT:
		case JIT_TYPE_LONG:

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

}

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(16);

	/* If the value is associated with a global register, then copy to that */
	if(value->has_global_register)
	{
		reg = _jit_reg_info[reg].cpu_reg;
		other_reg = _jit_reg_info[value->global_reg].cpu_reg;
		x86_mov_reg_reg(inst, other_reg, reg, sizeof(void *));
		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);

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

						else
						{
							x86_fld80_mem(inst, ptr);
						}
					}
				}
			}
			break;
		}
	}
	else if(value->in_register || value->in_global_register)
	{
		if(value->in_register)
		{
			src_reg = value->reg;
			if(other_reg >= 0)
			{
				other_src_reg = jit_reg_other_reg(src_reg);
			}
			else
			{
				other_src_reg = -1;
			}
		}
		else
		{
			src_reg = value->global_reg;
			other_src_reg = -1;
		}

		switch(type->kind)
		{
#if 0
			case JIT_TYPE_SBYTE:
			{
				x86_widen_reg(inst, _jit_reg_info[reg].cpu_reg,
					      _jit_reg_info[src_reg].cpu_reg, 1, 0);

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

				}
			}
			break;
		}
	}

	/* End the code output process */
	jit_cache_end_output();
}

void _jit_gen_spill_global(jit_gencode_t gen, int reg, jit_value_t value)
{
	jit_cache_setup_output(16);
	if(value)
	{
		_jit_gen_fix_value(value);
		x86_mov_membase_reg(inst,
			 X86_EBP, value->frame_offset,
			_jit_reg_info[value->global_reg].cpu_reg, sizeof(void *));
	}
	else
	{
		x86_push_reg(inst, _jit_reg_info[reg].cpu_reg);
	}
	jit_cache_end_output();
}

void _jit_gen_load_global(jit_gencode_t gen, int reg, jit_value_t value)
{
	jit_cache_setup_output(16);
	if(value)
	{
		x86_mov_reg_membase(inst,
			_jit_reg_info[value->global_reg].cpu_reg,
			X86_EBP, value->frame_offset, sizeof(void *));
	}
	else
	{
		x86_pop_reg(inst, _jit_reg_info[reg].cpu_reg);
	}
	jit_cache_end_output();
}

void _jit_gen_fix_value(jit_value_t value)

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

		fixup = next;
	}
	block->fixup_absolute_list = 0;
}

void _jit_gen_end_block(jit_gencode_t gen, jit_block_t block)
{
	/* Nothing to do here for x86 */
}

int _jit_gen_is_global_candidate(jit_type_t type)
{
	switch(jit_type_remove_tags(type)->kind)
	{
		case JIT_TYPE_INT:
		case JIT_TYPE_UINT:
		case JIT_TYPE_NINT:
		case JIT_TYPE_NUINT:
		case JIT_TYPE_PTR:
		case JIT_TYPE_SIGNATURE:	return 1;
	}

libjit/jit/jit-rules-x86.ins  view on Meta::CPAN

		{
			cpu_reg = _jit_reg_info[nest_reg].cpu_reg;
		}
		parent = func->builder->parent_frame;
		if(parent->in_register)
		{
			x86_mov_reg_reg(inst, cpu_reg,
							_jit_reg_info[parent->reg].cpu_reg,
							sizeof(void *));
		}
		else if(parent->in_global_register)
		{
			x86_mov_reg_reg(inst, cpu_reg,
							_jit_reg_info[parent->global_reg].cpu_reg,
							sizeof(void *));
		}
		else
		{
			_jit_gen_fix_value(parent);
			x86_mov_reg_membase(inst, cpu_reg, X86_EBP,
							    parent->frame_offset, sizeof(void *));
		}
		while(level > 0)
		{

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

#define	JIT_REG_WORD		(1 << 0)	/* Can be used for word values */
#define	JIT_REG_LONG		(1 << 1)	/* Can be used for long values */
#define	JIT_REG_FLOAT32		(1 << 2)	/* Can be used for float32 values */
#define	JIT_REG_FLOAT64		(1 << 3)	/* Can be used for float64 values */
#define	JIT_REG_NFLOAT		(1 << 4)	/* Can be used for nfloat values */
#define	JIT_REG_FRAME		(1 << 5)	/* Contains frame pointer */
#define	JIT_REG_STACK_PTR	(1 << 6)	/* Contains CPU stack pointer */
#define	JIT_REG_FIXED		(1 << 7)	/* Fixed use; not for allocation */
#define	JIT_REG_CALL_USED	(1 << 8)	/* Destroyed by a call */
#define	JIT_REG_IN_STACK	(1 << 9)	/* Middle of stack-like allocation */
#define	JIT_REG_GLOBAL		(1 << 10)	/* Candidate for global allocation */
#define	JIT_REG_ALL		(JIT_REG_WORD | JIT_REG_LONG \
				 | JIT_REG_FLOAT32 | JIT_REG_FLOAT64 \
 				 | JIT_REG_NFLOAT)

/*
 * Include definitions that are specific to the backend.
 */
#if defined(JIT_BACKEND_INTERP)
# include "jit-rules-interp.h"
#elif defined(JIT_BACKEND_ALPHA)

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

 */
typedef struct jit_gencode *jit_gencode_t;
struct jit_gencode
{
	jit_context_t		context;	/* Context this position is attached to */
	unsigned char		*ptr;		/* Current code pointer */
	unsigned char		*mem_start;	/* Available space start */
	unsigned char		*mem_limit;	/* Available space limit */
	unsigned char		*code_start;	/* Real code start */
	unsigned char		*code_end;	/* Real code end */
	jit_regused_t		permanent;	/* Permanently allocated global regs */
	jit_regused_t		touched;	/* All registers that were touched */
	jit_regused_t		inhibit;	/* Temporarily inhibited registers */
	jit_regcontents_t	contents[JIT_NUM_REGS]; /* Contents of each register */
	int			current_age;	/* Current age value for registers */
#ifdef JIT_REG_STACK
	int			reg_stack_top;	/* Current register stack top */
#endif
#ifdef jit_extra_gen_state
	jit_extra_gen_state;			/* CPU-specific extra information */
#endif

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

int _jit_opcode_is_supported(int opcode);
void *_jit_gen_prolog(jit_gencode_t gen, jit_function_t func, void *buf);
void _jit_gen_epilog(jit_gencode_t gen, jit_function_t func);
void *_jit_gen_redirector(jit_gencode_t gen, jit_function_t func);
void _jit_gen_spill_reg(jit_gencode_t gen, int reg,
					    int other_reg, jit_value_t value);
void _jit_gen_free_reg(jit_gencode_t gen, int reg,
					   int other_reg, int value_used);
void _jit_gen_load_value
	(jit_gencode_t gen, int reg, int other_reg, jit_value_t value);
void _jit_gen_spill_global(jit_gencode_t gen, int reg, jit_value_t value);
void _jit_gen_load_global(jit_gencode_t gen, int reg, jit_value_t value);
void _jit_gen_exch_top(jit_gencode_t gen, int reg);
void _jit_gen_move_top(jit_gencode_t gen, int reg);
void _jit_gen_spill_top(jit_gencode_t gen, int reg, jit_value_t value, int pop);
void _jit_gen_fix_value(jit_value_t value);
void _jit_gen_insn(jit_gencode_t gen, jit_function_t func,
				   jit_block_t block, jit_insn_t insn);
void _jit_gen_start_block(jit_gencode_t gen, jit_block_t block);
void _jit_gen_end_block(jit_gencode_t gen, jit_block_t block);
int _jit_gen_is_global_candidate(jit_type_t type);

#if defined(JIT_NATIVE_INT32) && !defined(JIT_BACKEND_INTERP)
int _jit_reg_get_pair(jit_type_t type, int reg);
#endif

/*
 * Determine the byte number within a "jit_int" where the low
 * order byte can be found.
 */
int _jit_int_lowest_byte(void);

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

    #elif !defined(__palmos__)
        #include <time.h>
    #endif
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include <errno.h>

/*
 * Mutex that synchronizes global data initialization.
 */
jit_mutex_t _jit_global_lock;

#if defined(JIT_THREADS_PTHREAD)

/*
 * The thread-specific key to use to fetch the control object.
 */
static pthread_key_t control_key;

/*
 * Initialize the pthread support routines.  Only called once.
 */
static void init_pthread(void)
{
	jit_mutex_create(&_jit_global_lock);

	/* Allocate a thread-specific variable for the JIT's thread
	   control object, and arrange for it to be freed when the
	   thread exits or is otherwise terminated */
	pthread_key_create(&control_key, jit_free);
}

#elif defined(JIT_THREADS_WIN32)

/*
 * The thread-specific key to use to fetch the control object.
 */
static DWORD control_key;

/*
 * Initialize the Win32 thread support routines.  Only called once.
 */
static void init_win32_thread(void)
{
	jit_mutex_create(&_jit_global_lock);

	control_key = TlsAlloc();
}

jit_thread_id_t _jit_thread_self(void)
{
	HANDLE new_handle;
	DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
					GetCurrentProcess(), &new_handle,
					0, 0, DUPLICATE_SAME_ACCESS);

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


typedef int jit_mutex_t;
#define	jit_mutex_create(mutex)		do { ; } while (0)
#define	jit_mutex_destroy(mutex)	do { ; } while (0)
#define	jit_mutex_lock(mutex)		do { ; } while (0)
#define	jit_mutex_unlock(mutex)		do { ; } while (0)

#endif

/*
 * Mutex that synchronizes global data initialization.
 */
extern jit_mutex_t _jit_global_lock;

/*
 * Define the primitive monitor operations.
 */

#if defined(JIT_THREADS_PTHREAD)

typedef struct
{
	pthread_mutex_t	_mutex;



( run in 1.722 second using v1.01-cache-2.11-cpan-49f99fa48dc )