Alien-LibJIT

 view release on metacpan or  search on metacpan

inc/Module/Build/AlienLibJIT.pm  view on Meta::CPAN

package Module::Build::AlienLibJIT;

use warnings;
use strict;

use parent 'Module::Build';

use FindBin('$Bin');
use File::Spec;
use File::Basename ();
use Config;

our $LIBJIT_HOME = 'libjit';
our $LIBJIT_M4 = 'm4';
our $LIBJIT_INCLUDE = File::Spec->catfile($LIBJIT_HOME, 'include');
our $LIBJIT_RESULT = File::Spec->catfile($LIBJIT_HOME, 'jit', '.libs', 'libjit'.$Config::Config{lib_ext});

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


/*
 * Define this to 1 if the platform allows reads and writes on
 * any byte boundary.  Define to 0 if only properly-aligned
 * memory accesses are allowed.
 *
 * All memory access on alpha must be naturally aligned. There are 
 * unaligned load and store instructions to operate on arbitrary byte 
 * boundaries. However sometimes compilers don't always spot where 
 * to use them due to programming tricks with pointers. The kernel will 
 * do the fetch transparently if the access is unaligned and not done 
 * with the proper instructions. Kernel assisted unaligned accesses 
 * don't change the behavior of the program. 
 *
 * TODO: benchmark this to determine what is more costly... setting
 * up everything to be aligned or dealing with the unaligned accesses.
 */
#define JIT_ALIGN_OVERRIDES		1

/*
 * The jit_extra_gen_state macro can be supplied to add extra fields to 

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


@item
Large set of mathematical and trigonometric operations
(sqrt, sin, cos, min, abs, etc) for inlining floating-point library functions.

@item
Simplified type layout and exception handling mechanisms, upon which a
variety of different object models can be built.

@item
Support for nested functions, able to access their parent's local variables
(for implementing Pascal-style languages).
@end itemize

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

@node Tutorials, Tutorial 1, Features, Top
@chapter Tutorials in using libjit
@cindex Tutorials

In this chapter, we describe how to use @code{libjit} with a number of

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

We can now compile the function and execute it in the usual manner.

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

@node Tutorial 3, Tutorial 4, Tutorial 2, Tutorials
@section Tutorial 3 - compiling on-demand
@cindex On-demand compilation tutorial

In the previous tutorials, we compiled everything that we needed
at startup time, and then entered the execution phase.  The real power
of a JIT becomes apparent when you use it to compile functions
only as they are called.  You can thus avoid compiling functions
that are never called in a given program run, saving memory and
startup time.

We demonstrate how to do on-demand compilation by rewriting Tutorial 1.
The source code for the modified version is in @code{tutorial/t3.c}.

When the @code{mul_add} function is created, we don't create its function
body or call @code{jit_function_compile}.  We instead provide a
C function called @code{compile_mul_add} that performs on-demand

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

	char			   *filename;
	long				linenum;
	dpas_scope_item_t	next;
};

/*
 * Internal structure of a scope.
 */
struct dpas_scope
{
	dpas_scope_t		parent;
	dpas_scope_item_t	first;
	dpas_scope_item_t	last;
	dpas_scope_item_t	first_with;
	dpas_scope_item_t	last_with;
	int					level;
};

dpas_scope_t dpas_scope_create(dpas_scope_t parent)
{
	dpas_scope_t scope;
	scope = jit_new(struct dpas_scope);
	if(!scope)
	{
		dpas_out_of_memory();
	}
	scope->parent = parent;
	scope->first = 0;
	scope->last = 0;
	scope->first_with = 0;
	scope->last_with = 0;
	if(parent)
	{
		scope->level = parent->level + 1;
	}
	else
	{
		scope->level = 0;
	}
	return scope;
}

void dpas_scope_destroy(dpas_scope_t scope)
{

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

		item = scope->first;
		while(item != 0)
		{
			if(!jit_stricmp(item->name, name))
			{
				return item;
			}
			item = item->next;
		}

		/* Move up to the parent scope if necessary */
		if(!up)
		{
			break;
		}
		scope = scope->parent;
	}
	return 0;
}

/*
 * Add an item to a scope list.
 */
static void scope_add(dpas_scope_item_t *first, dpas_scope_item_t *last,
					  const char *name, jit_type_t type, int kind,
					  void *info, jit_meta_free_func free_info,

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


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

 * Opaque type that represents a scope.
 */
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
 * check the parent scopes.
 */
dpas_scope_item_t dpas_scope_lookup(dpas_scope_t scope,
									const char *name, int up);

/*
 * Add an entry to a scope.
 */
void dpas_scope_add(dpas_scope_t scope, const char *name, jit_type_t type,
					int kind, void *info, jit_meta_free_func free_info,
					char *filename, long linenum);

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

#endif

/* Optimization levels */
#define JIT_OPTLEVEL_NONE	0
#define JIT_OPTLEVEL_NORMAL	1

jit_function_t jit_function_create
	(jit_context_t context, jit_type_t signature) JIT_NOTHROW;
jit_function_t jit_function_create_nested
	(jit_context_t context, jit_type_t signature,
	 jit_function_t parent) JIT_NOTHROW;
void jit_function_abandon(jit_function_t func) JIT_NOTHROW;
jit_context_t jit_function_get_context(jit_function_t func) JIT_NOTHROW;
jit_type_t jit_function_get_signature(jit_function_t func) JIT_NOTHROW;
int jit_function_set_meta
	(jit_function_t func, int type, void *data,
	 jit_meta_free_func free_data, int build_only) JIT_NOTHROW;
void *jit_function_get_meta(jit_function_t func, int type) JIT_NOTHROW;
void jit_function_free_meta(jit_function_t func, int type) JIT_NOTHROW;
jit_function_t jit_function_next
	(jit_context_t context, jit_function_t prev) JIT_NOTHROW;
jit_function_t jit_function_previous
	(jit_context_t context, jit_function_t prev) JIT_NOTHROW;
jit_block_t jit_function_get_entry(jit_function_t func) JIT_NOTHROW;
jit_block_t jit_function_get_current(jit_function_t func) JIT_NOTHROW;
jit_function_t jit_function_get_nested_parent(jit_function_t func) JIT_NOTHROW;
int jit_function_compile(jit_function_t func) JIT_NOTHROW;
int jit_function_is_compiled(jit_function_t func) JIT_NOTHROW;
void jit_function_set_recompilable(jit_function_t func) JIT_NOTHROW;
void jit_function_clear_recompilable(jit_function_t func) JIT_NOTHROW;
int jit_function_is_recompilable(jit_function_t func) JIT_NOTHROW;
int jit_function_compile_entry(jit_function_t func, void **entry_point) JIT_NOTHROW;
void jit_function_setup_entry(jit_function_t func, void *entry_point) JIT_NOTHROW;
void *jit_function_to_closure(jit_function_t func) JIT_NOTHROW;
jit_function_t jit_function_from_closure
	(jit_context_t context, void *closure) JIT_NOTHROW;

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-dump.c  view on Meta::CPAN

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

	/* Intuit the prefix if one was not supplied */
	if(!prefix)

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

	/* Output the function header */
	if(name)
		fprintf(stream, "function %s(", name);
	else
		fprintf(stream, "function 0x%08lX(", (long)(jit_nuint)func);
	signature = func->signature;
	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-elf-defs.h  view on Meta::CPAN

} Elf32_Syminfo;

typedef struct
{
  Elf64_Half si_boundto;		/* Direct bindings, symbol bound to */
  Elf64_Half si_flags;			/* Per symbol flags */
} Elf64_Syminfo;

/* Possible values for si_boundto.  */
#define SYMINFO_BT_SELF		0xffff	/* Symbol bound to self */
#define SYMINFO_BT_PARENT	0xfffe	/* Symbol bound to parent */
#define SYMINFO_BT_LOWRESERVE	0xff00	/* Beginning of reserved entries */

/* Possible bitmasks for si_flags.  */
#define SYMINFO_FLG_DIRECT	0x0001	/* Direct bound symbol */
#define SYMINFO_FLG_PASSTHRU	0x0002	/* Pass-thru symbol for translator */
#define SYMINFO_FLG_COPY	0x0004	/* Symbol is a copy-reloc */
#define SYMINFO_FLG_LAZYLOAD	0x0008	/* Symbol bound to object to be lazy
					   loaded */
/* Syminfo version values.  */
#define SYMINFO_NONE		0

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

	{
		jit_free(trace);
	}
}

void _jit_backtrace_push(jit_backtrace_t trace, void *pc)
{
	jit_thread_control_t control = _jit_thread_get_control();
	if(control)
	{
		trace->parent = control->backtrace_head;
		trace->pc = pc;
		trace->security_object = 0;
		trace->free_security_object = 0;
		control->backtrace_head = trace;
	}
	else
	{
		trace->parent = 0;
		trace->pc = pc;
		trace->security_object = 0;
		trace->free_security_object = 0;
	}
}

void _jit_backtrace_pop(void)
{
	jit_thread_control_t control = _jit_thread_get_control();
	jit_backtrace_t trace;
	if(control)
	{
		trace = control->backtrace_head;
		if(trace)
		{
			control->backtrace_head = trace->parent;
			if(trace->security_object && trace->free_security_object)
			{
				(*(trace->free_security_object))(trace->security_object);
			}
		}
	}
}

void _jit_backtrace_set(jit_backtrace_t trace)
{

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

	}
}

void _jit_unwind_push_setjmp(jit_jmp_buf *jbuf)
{
	jit_thread_control_t control = _jit_thread_get_control();
	if(control)
	{
		jbuf->trace = control->backtrace_head;
		jbuf->catch_pc = 0;
		jbuf->parent = control->setjmp_head;
		control->setjmp_head = jbuf;
	}
}

void _jit_unwind_pop_setjmp(void)
{
	jit_thread_control_t control = _jit_thread_get_control();
	if(control && control->setjmp_head)
	{
		control->backtrace_head = control->setjmp_head->trace;
		control->setjmp_head = control->setjmp_head->parent;
	}
}

void _jit_unwind_pop_and_rethrow(void)
{
	_jit_unwind_pop_setjmp();
	jit_exception_throw(jit_exception_get_last());
}

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

	{
		context->functions = func;
	}
	context->last_function = func;

	/* Return the function to the caller */
	return func;
}

/*@
 * @deftypefun jit_function_t jit_function_create_nested (jit_context_t @var{context}, jit_type_t @var{signature}, jit_function_t @var{parent})
 * Create a new function block and associate it with a JIT context.
 * In addition, this function is nested inside the specified
 * @var{parent} function and is able to access its parent's
 * (and grandparent's) local variables.
 *
 * The front end is responsible for ensuring that the nested function can
 * never be called by anyone except its parent and sibling functions.
 * The front end is also responsible for ensuring that the nested function
 * is compiled before its parent.
 * @end deftypefun
@*/
jit_function_t jit_function_create_nested
		(jit_context_t context, jit_type_t signature, jit_function_t parent)
{
	jit_function_t func;
	func = jit_function_create(context, signature);
	if(!func)
	{
		return 0;
	}
	func->nested_parent = parent;
	return func;
}

int _jit_function_ensure_builder(jit_function_t func)
{
	/* Handle the easy cases first */
	if(!func)
	{
		return 0;
	}

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

	{
		return func->builder->current_block;
	}
	else
	{
		return 0;
	}
}

/*@
 * @deftypefun jit_function_t jit_function_get_nested_parent (jit_function_t @var{func})
 * Get the nested parent for a function, or NULL if @var{func}
 * does not have a nested parent.
 * @end deftypefun
@*/
jit_function_t jit_function_get_nested_parent(jit_function_t func)
{
	if(func)
	{
		return func->nested_parent;
	}
	else
	{
		return 0;
	}
}

/*
 * Information that is stored for an exception region in the cache.
 */

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

	/* Create a backtrace entry that blocks exceptions from
	   flowing further than this up the stack */
	_jit_backtrace_push(&call_trace, 0);

	/* Get the function's entry point */
	if(!func)
	{
		jit_exception_builtin(JIT_RESULT_NULL_FUNCTION);
		return 0;
	}
	if(func->nested_parent)
	{
		jit_exception_builtin(JIT_RESULT_CALLED_NESTED);
		return 0;
	}
	if(func->is_compiled)
	{
		entry = func->entry_point;
	}
	else
	{

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


	/* Get the default signature from "jit_func" */
	if(!signature)
	{
		signature = jit_func->signature;
	}

	/* Verify that tail calls are possible to the destination */
	if((flags & JIT_CALL_TAIL) != 0)
	{
		if(func->nested_parent || jit_func->nested_parent)
		{
			/* Cannot use tail calls with nested function calls */
			flags &= ~JIT_CALL_TAIL;
		}
		else if(!signature_identical(signature, func->signature))
		{
			/* The signatures are not the same, so tail calls not allowed */
			flags &= ~JIT_CALL_TAIL;
		}
	}

	/* Determine the nesting relationship with the current function */
	if(jit_func->nested_parent)
	{
		is_nested = 1;
		if(jit_func->nested_parent == func)
		{
			/* We are calling one of our children */
			nesting_level = -1;
		}
		else if(jit_func->nested_parent == func->nested_parent)
		{
			/* We are calling one of our direct siblings */
			nesting_level = 0;
		}
		else
		{
			/* Search up to find the actual nesting level */
			temp_func = func->nested_parent;
			nesting_level = 1;
			while(temp_func != 0 && temp_func != jit_func)
			{
				++nesting_level;
				temp_func = temp_func->nested_parent;
			}
		}
	}
	else
	{
		is_nested = 0;
		nesting_level = 0;
	}

	/* Convert the arguments to the actual parameter types */

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

	{
		return 0;
	}

	/* Verify that tail calls are possible to the destination */
#if defined(JIT_BACKEND_INTERP)
	flags &= ~JIT_CALL_TAIL;
#else
	if((flags & JIT_CALL_TAIL) != 0)
	{
		if(func->nested_parent)
		{
			flags &= ~JIT_CALL_TAIL;
		}
		else if(!signature_identical(signature, func->signature))
		{
			flags &= ~JIT_CALL_TAIL;
		}
	}
#endif

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


	/* Bail out if there is something wrong with the parameters */
	if(!_jit_function_ensure_builder(func) || !value || !signature)
	{
		return 0;
	}

	/* Verify that tail calls are possible to the destination */
	if((flags & JIT_CALL_TAIL) != 0)
	{
		if(func->nested_parent)
		{
			flags &= ~JIT_CALL_TAIL;
		}
		else if(!signature_identical(signature, func->signature))
		{
			flags &= ~JIT_CALL_TAIL;
		}
	}

	/* Convert the arguments to the actual parameter types */

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

	{
		return 0;
	}

	/* Verify that tail calls are possible to the destination */
#if defined(JIT_BACKEND_INTERP)
	flags &= ~JIT_CALL_TAIL;
#else
	if((flags & JIT_CALL_TAIL) != 0)
	{
		if(func->nested_parent)
		{
			flags &= ~JIT_CALL_TAIL;
		}
		else if(!signature_identical(signature, func->signature))
		{
			flags &= ~JIT_CALL_TAIL;
		}
	}
#endif

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

{
	return create_note(func, JIT_OP_RETURN_REG, value,
					   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)
	{

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

		jit_value_set_addressable(value);
	}
	return create_unary_note(func, JIT_OP_FLUSH_SMALL_STRUCT, value);
}

/*@
 * @deftypefun jit_value_t jit_insn_import (jit_function_t @var{func}, jit_value_t @var{value})
 * Import @var{value} from an outer nested scope into @var{func}.  Returns
 * the effective address of the value for local access via a pointer.
 * Returns NULL if out of memory or the value is not accessible via a
 * parent, grandparent, or other ancestor of @var{func}.
 * @end deftypefun
@*/
jit_value_t jit_insn_import(jit_function_t func, jit_value_t value)
{
	jit_function_t value_func;
	jit_function_t current_func;
	int level;

	/* Make sure that we have a builder before we start */
	if(!_jit_function_ensure_builder(func))

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

		return 0;
	}

	/* If the value is already local, then return the local address */
	value_func = jit_value_get_function(value);
	if(value_func == func)
	{
		return jit_insn_address_of(func, value);
	}

	/* Find the nesting level of the value, where 1 is our parent */
	level = 1;
	current_func = func->nested_parent;
	while(current_func != 0 && current_func != value_func)
	{
		++level;
		current_func = current_func->nested_parent;
	}
	if(!current_func)
	{
		/* The value is not accessible from this scope */
		return 0;
	}

	/* Output the relevant import instruction, which will also cause
	   it to be marked as a non-local addressable by "jit_value_ref" */
	return apply_binary

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;

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

 * Internal structure of a function.
 */
struct _jit_function
{
	/* The context that the function is associated with */
	jit_context_t		context;
	jit_function_t		next;
	jit_function_t		prev;

	/* Containing function in a nested context */
	jit_function_t		nested_parent;

	/* Metadata that survives once the builder is discarded */
	jit_meta_t		meta;

	/* The signature for this function */
	jit_type_t		signature;

	/* The builder information for this function */
	jit_builder_t		builder;

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

void _jit_memory_free_closure(jit_context_t context, void *ptr);
void *_jit_memory_alloc_data(jit_context_t context, jit_size_t size, jit_size_t align);

/*
 * Backtrace control structure, for managing stack traces.
 * These structures must be allocated on the stack.
 */
typedef struct jit_backtrace *jit_backtrace_t;
struct jit_backtrace
{
	jit_backtrace_t		parent;
	void			*pc;
	void			*security_object;
	jit_meta_free_func	free_security_object;
};

/*
 * Push a new backtrace onto the stack.  The fields in "trace" are filled in.
 */
void _jit_backtrace_push(jit_backtrace_t trace, void *pc);

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

	else if(signature == func->signature)
	{
		arg_buffer = (jit_item *)alloca(entry->args_size);
	}
	else
	{
		arg_buffer = (jit_item *)alloca
			(_jit_interp_calculate_arg_size(func, signature));
	}
	temp_arg = arg_buffer;
	if(func->nested_parent)
	{
		jit_exception_builtin(JIT_RESULT_CALLED_NESTED);
	}
	type = jit_type_get_return(signature);
	if(jit_type_return_via_pointer(type))
	{
		if(!return_area)
		{
			return_area = alloca(jit_type_get_size(type));
		}

libjit/jit/jit-memory-cache.c  view on Meta::CPAN

}

/*
 * Split a red-black tree at the current position.
 */
#define	Split()		\
			do { \
				SetRed(temp); \
				SetBlack(GetLeft(temp)); \
				SetBlack(GetRight(temp)); \
				if(GetRed(parent)) \
				{ \
					SetRed(grandParent); \
					if((CacheCompare(cache, key, grandParent) < 0) != \
							(CacheCompare(cache, key, parent) < 0)) \
					{ \
						parent = CacheRotate(cache, key, grandParent); \
					} \
					temp = CacheRotate(cache, key, greatGrandParent); \
					SetBlack(temp); \
				} \
			} while (0)

/*
 * Add a method region block to the red-black lookup tree
 * that is associated with a method cache.
 */
static void
AddToLookupTree(jit_cache_t cache, jit_cache_node_t method)
{
	unsigned char *key = method->start;
	jit_cache_node_t temp;
	jit_cache_node_t greatGrandParent;
	jit_cache_node_t grandParent;
	jit_cache_node_t parent;
	jit_cache_node_t nil = &(cache->nil);
	int cmp;

	/* Search for the insert position */
	temp = &(cache->head);
	greatGrandParent = temp;
	grandParent = temp;
	parent = temp;
	while(temp != nil)
	{
		/* Adjust our ancestor pointers */
		greatGrandParent = grandParent;
		grandParent = parent;
		parent = temp;

		/* Compare the key against the current node */
		cmp = CacheCompare(cache, key, temp);
		if(cmp == 0)
		{
			/* This is a duplicate, which normally shouldn't happen.
			   If it does happen, then ignore the node and bail out */
			return;
		}
		else if(cmp < 0)

libjit/jit/jit-memory-cache.c  view on Meta::CPAN

		/* Do we need to split this node? */
		if(GetRed(GetLeft(temp)) && GetRed(GetRight(temp)))
		{
			Split();
		}
	}

	/* Insert the new node into the current position */
	method->left = (jit_cache_node_t)(((jit_nuint)nil) | ((jit_nuint)1));
	method->right = nil;
	if(CacheCompare(cache, key, parent) < 0)
	{
		SetLeft(parent, method);
	}
	else
	{
		SetRight(parent, method);
	}
	Split();
	SetBlack(cache->head.right);
}

jit_cache_t
_jit_cache_create(jit_context_t context)
{
	jit_cache_t cache;
	long limit, cache_page_size;

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

 */

#include <jit/jit.h>
#include <jit/jit-objmodel-private.h>

/*@

The @code{libjit} library does not implement a particular object model
of its own, so that it is generic across bytecode formats and front end
languages.  However, it does provide support for plugging object models
into the JIT process, and for transparently proxying to external libraries
that may use a foreign object model.

There may be more than one object model active in the system at any
one time.  For example, a JVM implementation might have a primary
object model for its own use, and a secondary object model for
calling methods in an imported Objective C library.

The functions in this section support pluggable object models.  There is
no requirement that you use them: you can ignore them and use the rest
of @code{libjit} directly if you wish.

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

	/* Reset the frame size for this function */
	func->builder->frame_size = 0;

	/* The starting parameter offset.  We use negative offsets to indicate
	   an offset into the "args" block, and positive offsets to indicate
	   an offset into the "frame" block.  The negative values will be
	   flipped when we output the argument opcodes for interpretation */
	offset = -1;

	/* If the function is nested, then we need two extra parameters
	   to pass the pointer to the parent's local variables and arguments */
	if(func->nested_parent)
	{
		offset -= 2;
	}

	/* Allocate the structure return pointer */
	value = jit_value_get_struct_pointer(func);
	if(value)
	{
		if(!jit_insn_incoming_frame_posn(func, value, offset))
		{

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

/*@
 * @deftypefun int _jit_create_call_setup_insns (jit_function_t @var{func}, jit_type_t @var{signature}, jit_value_t *@var{args}, unsigned int @var{num_args}, int @var{is_nested}, int @var{nested_level}, jit_value_t *@var{struct_return}, int @var{flag...
 * Create instructions within @var{func} necessary to set up for a
 * function call to a function with the specified @var{signature}.
 * Use @code{jit_insn_push} to push values onto the system stack,
 * or @code{jit_insn_outgoing_reg} to copy values into call registers.
 *
 * If @var{is_nested} is non-zero, then it indicates that we are calling a
 * nested function within the current function's nested relationship tree.
 * 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.  The @code{jit_insn_setup_for_nested}
 * instruction should be used to create the nested function setup code.
 *
 * If the function returns a structure by pointer, then @var{struct_return}
 * must be set to a new local variable that will contain the returned
 * structure.  Otherwise it should be set to NULL.
 * @end deftypefun
@*/
int _jit_create_call_setup_insns
	(jit_function_t func, jit_type_t signature,
	 jit_value_t *args, unsigned int num_args,

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

			if(!jit_insn_setup_for_nested(func, nested_level, -1))
			{
				return 0;
			}
		}
	}
	else
	{
		/* Copy the arguments into our own parameter slots */
		offset = -1;
		if(func->nested_parent)
		{
			offset -= 2;
		}
		type = jit_type_get_return(signature);
		if(jit_type_return_via_pointer(type))
		{
			--offset;
		}
		for(arg_num = 0; arg_num < num_args; ++arg_num)
		{

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

		pop_items += JIT_NUM_ITEMS_IN_STRUCT(size);
	}
	return_type = jit_type_normalize(jit_type_get_return(signature));
	ptr_return = jit_type_return_via_pointer(return_type);
	if(ptr_return)
	{
		++pop_items;
	}
	if(is_nested)
	{
		/* The interpreter needs two arguments for the parent frame info */
		pop_items += 2;
	}

	/* Pop the items from the system stack */
	if(pop_items > 0)
	{
		if(!jit_insn_pop_stack(func, pop_items))
		{
			return 0;
		}

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

 */
unsigned int _jit_interp_calculate_arg_size
		(jit_function_t func, jit_type_t signature)
{
	unsigned int size = 0;
	jit_type_t type;
	unsigned int num_params;
	unsigned int param;

	/* Determine if we need nested parameter information */
	if(func->nested_parent)
	{
		size += 2 * sizeof(jit_item);
	}

	/* Determine if we need a structure pointer argument */
	type = jit_type_get_return(signature);
	if(jit_type_return_via_pointer(type))
	{
		size += sizeof(jit_item);
	}

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

	jit_memset(&passing, 0, sizeof(jit_param_passing_t));
	jit_memset(param, 0, sizeof(_jit_param_t) * num_args);

	passing.params = param;
	passing.stack_size = JIT_INITIAL_STACK_OFFSET;

	/* Let the specific backend initialize it's part of the params */
	_jit_init_args(abi, &passing);

	/* If the function is nested, then we need an extra parameter
	   to pass the pointer to the parent's local variable frame */
	if(func->nested_parent)
	{
		jit_memset(&nested_param, 0, sizeof(_jit_param_t));
		if(!(_jit_classify_param(&passing, &nested_param,
								 jit_type_void_ptr)))
		{
			return 0;
		}
	}

	/* Allocate the structure return pointer */

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

#if JIT_APPLY_X86_FASTCALL == 1
	/* Determine the number of parameter bytes to pop when we return */
	{
		jit_type_t signature;
		unsigned int num_params;
		unsigned int param;
		signature = func->signature;
		if(jit_type_get_abi(signature) == jit_abi_stdcall ||
		   jit_type_get_abi(signature) == jit_abi_fastcall)
		{
			if(func->nested_parent)
			{
				pop_bytes += sizeof(void *);
			}
			if(jit_type_return_via_pointer(jit_type_get_return(signature)))
			{
				struct_return_offset = 2 * sizeof(void *) + pop_bytes;
				pop_bytes += sizeof(void *);
			}
			num_params = jit_type_num_params(signature);
			for(param = 0; param < num_params; ++param)

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

				{
					pop_bytes -= 2 * sizeof(void *);
				}
				else
				{
					pop_bytes = 0;
				}
				struct_return_offset = 0;
			}
		}
		else if(!(func->nested_parent) &&
				jit_type_return_via_pointer(jit_type_get_return(signature)))
		{
#if JIT_APPLY_X86_POP_STRUCT_RETURN == 1
			pop_bytes += sizeof(void *);
#endif
			struct_return_offset = 2 * sizeof(void *);
		}
	}
#else
	{
		/* We only need to pop structure pointers in non-nested functions */
		jit_type_t signature;
		signature = func->signature;
		if(!(func->nested_parent) &&
		   jit_type_return_via_pointer(jit_type_get_return(signature)))
		{
#if JIT_APPLY_X86_POP_STRUCT_RETURN == 1
			pop_bytes += sizeof(void *);
#endif
			struct_return_offset = 2 * sizeof(void *);
		}
	}
#endif

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

		}
		else
		{
			x86_mov_reg_reg(inst, _jit_reg_info[nest_reg].cpu_reg,
							X86_EBP, sizeof(void *));
		}
	}

JIT_OP_SETUP_FOR_SIBLING: branch
	[] -> {
		jit_value_t parent;
		jit_nint level = jit_value_get_nint_constant(insn->value1);
		jit_nint nest_reg = jit_value_get_nint_constant(insn->value2);
		int cpu_reg;
		if(nest_reg == -1)
		{
			cpu_reg = X86_EAX;
		}
		else
		{
			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)
		{
			gen->ptr = inst;
			_jit_gen_check_space(gen, 16);
			x86_mov_reg_membase(inst, cpu_reg, cpu_reg, 0, sizeof(void *));
			--level;
		}
		if(nest_reg == -1)
		{

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

		}
	}

JIT_OP_IMPORT: manual
	[] -> {
		unsigned char *inst;
		int reg;
		jit_nint level = jit_value_get_nint_constant(insn->value2);
		_jit_gen_fix_value(insn->value1);
		reg = _jit_regs_load_value
			(gen, func->builder->parent_frame, 1, 0);
		inst = gen->ptr;
		_jit_gen_check_space(gen, 32 + level * 8);
		reg = _jit_reg_info[reg].cpu_reg;
		while(level > 0)
		{
			x86_mov_reg_membase(inst, reg, reg, 0, sizeof(void *));
			--level;
		}
		if(insn->value1->frame_offset != 0)
		{

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

#endif
	{
		passing.word_regs = cdecl_word_regs;
	}
	for(size = 0; size < JIT_MAX_WORD_REG_PARAMS; ++size)
	{
		passing.word_values[size] = 0;
	}

	/* If the function is nested, then we need an extra parameter
	   to pass the pointer to the parent's local variable frame */
	if(func->nested_parent)
	{
		value = jit_value_create(func, jit_type_void_ptr);
		if(!value)
		{
			return 0;
		}
		func->builder->parent_frame = value;
		if(!alloc_incoming_word(func, &passing, value, 0))
		{
			return 0;
		}
	}

	/* Allocate the structure return pointer */
	value = jit_value_get_struct_pointer(func);
	if(value)
	{

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

#endif

/*
 * Jump buffer structure, with link.
 */
typedef struct jit_jmp_buf
{
	jmp_buf				buf;
	jit_backtrace_t		trace;
	void			   *catch_pc;
	struct jit_jmp_buf *parent;

} jit_jmp_buf;
#define	jit_jmp_catch_pc_offset	\
			((jit_nint)&(((jit_jmp_buf *)0)->catch_pc))

/*
 * Push a "setjmp" buffer onto the current thread's unwind stck.
 */
void _jit_unwind_push_setjmp(jit_jmp_buf *jbuf);

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

#endif

	if(!unwind || !unwind->frame)
	{
		return 0;
	}

	unwind->cache = 0;

#if defined(JIT_BACKEND_INTERP) || JIT_APPLY_BROKEN_FRAME_BUILTINS != 0
	unwind->frame =  ((jit_backtrace_t) unwind->frame)->parent;
	return (unwind->frame != 0);
#else

#ifdef _JIT_ARCH_UNWIND_NEXT_PRE
	func = jit_unwind_get_function(unwind);
	if(func)
	{
		_JIT_ARCH_UNWIND_NEXT_PRE(unwind, func);
	}
#endif

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

jit_unwind_next_pc(jit_unwind_context_t *unwind)
{
	if(!unwind || !unwind->frame)
	{
		return 0;
	}

	unwind->cache = 0;

#if defined(JIT_BACKEND_INTERP) || JIT_APPLY_BROKEN_FRAME_BUILTINS != 0
	unwind->frame =  ((jit_backtrace_t) unwind->frame)->parent;
#else
	unwind->frame = jit_get_next_frame_address(unwind->frame);
#endif
	return (unwind->frame != 0);
}

void *
jit_unwind_get_pc(jit_unwind_context_t *unwind)
{
	if(!unwind || !unwind->frame)

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


/*@
 * @deftypefun void jit_value_ref (jit_function_t @var{func}, jit_value_t @var{value})
 * Create a reference to the specified @var{value} from the current
 * block in @var{func}.  This will convert a temporary value into
 * a local value if @var{value} is being referenced from a different
 * block than its original.
 *
 * It is not necessary that @var{func} be the same function as the
 * one where the value was originally created.  It may be a nested
 * function, referring to a local variable in its parent function.
 * @end deftypefun
@*/
void jit_value_ref(jit_function_t func, jit_value_t value)
{
	if(!value || !_jit_function_ensure_builder(func))
	{
		return;
	}
	++(value->usage_count);
	if(value->is_temporary)

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

	unsigned int param;
	if(func->builder->param_values)
	{
		num_params = jit_type_num_params(func->signature);
		for(param = 0; param < num_params; ++param)
		{
			jit_value_ref(func, func->builder->param_values[param]);
		}
	}
	jit_value_ref(func, func->builder->struct_return);
	jit_value_ref(func, func->builder->parent_frame);
}

/*@
 * @deftypefun void jit_value_set_volatile (jit_value_t @var{value})
 * Set a flag on a value to indicate that it is volatile.  The contents
 * of the value must always be reloaded from memory, never from a
 * cached register copy.
 * @end deftypefun
@*/
void jit_value_set_volatile(jit_value_t value)

libjit/jitdynamic/jit-cpp-mangle.c  view on Meta::CPAN

 * @vindex JIT_MANGLE_IS_DTOR
 * @item JIT_MANGLE_IS_DTOR
 * The method is a destructor.  The @var{name} parameter will be ignored.
 *
 * @vindex JIT_MANGLE_BASE
 * @item JIT_MANGLE_BASE
 * Fetch the "base" constructor or destructor entry point, rather than
 * the "complete" entry point.
 * @end table
 *
 * The @var{class_name} may include namespace and nested parent qualifiers
 * by separating them with @code{::} or @code{.}.  Class names that involve
 * template parameters are not supported yet.
 * @end deftypefun
@*/
char *jit_mangle_member_function
	(const char *class_name, const char *name,
	 jit_type_t signature, int form, int flags)
{
	struct jit_mangler mangler;
	init_mangler(&mangler);

libjit/jitruby/ext/jit.c  view on Meta::CPAN

static void mark_function(jit_function_t function)
{
  rb_gc_mark((VALUE)jit_function_get_meta(function, RJT_VALUE_OBJECTS));
  rb_gc_mark((VALUE)jit_function_get_meta(function, RJT_CONTEXT));
}

static VALUE create_function(int argc, VALUE * argv, VALUE klass)
{
  VALUE context_v;
  VALUE signature_v;
  VALUE parent_function_v;

  jit_function_t function;
  jit_function_t parent_function;
  jit_context_t context;
  jit_type_t signature;
  jit_type_t untagged_signature;

  VALUE function_v;
  VALUE functions;

  int signature_tag;

  rb_scan_args(argc, argv, "21", &context_v, &signature_v, &parent_function_v);

  Data_Get_Struct(context_v, struct _jit_context, context);
  Data_Get_Struct(signature_v, struct _jit_type, signature);

  signature_tag = jit_type_get_kind(signature);

  /* If this signature was tagged, get the untagged type */
  if((untagged_signature = jit_type_get_tagged_type(signature)))
  {
    signature = untagged_signature;
  }

  if(RTEST(parent_function_v))
  {
    /* If this function has a parent, then it is a nested function */
    Data_Get_Struct(parent_function_v, struct _jit_function, parent_function);
    function = jit_function_create_nested(context, signature, parent_function);
  }
  else
  {
    /* Otherwise, it's a standalone function */
    function = jit_function_create(context, signature);
  }

  /* Make sure the function is around as long as the context is */
  if(!jit_function_set_meta(function, RJT_VALUE_OBJECTS, (void *)rb_ary_new(), 0, 0))
  {

libjit/jitruby/ext/jit.c  view on Meta::CPAN

  Data_Get_Struct(self, struct _jit_function, function);
  if(!jit_function_compile(function))
  {
    rb_raise(rb_eRuntimeError, "Unable to compile function");
  }
  return self;
}

/*
 * call-seq:
 *   function = Function.new(context, signature, [parent])
 *
 * Create a new function.
 */
static VALUE function_s_new(int argc, VALUE * argv, VALUE klass)
{
  if(rb_block_given_p())
  {
    rb_raise(rb_eArgError, "Function.new does not take a block");
  }

libjit/jitruby/ext/jit.c  view on Meta::CPAN

  {
    jit_function_t function;
    Data_Get_Struct(function_v, struct _jit_function, function);
    jit_function_abandon(function);
  }
  return Qnil;
}

/*
 * call-seq:
 *   function = Function.new(context, signature, [parent]) { |function| ... }
 *
 * Create a new function, begin compiling it, and pass the function to
 * the block.
 */
static VALUE function_s_compile(int argc, VALUE * argv, VALUE klass)
{
  VALUE function = create_function(argc, argv, klass);
  rb_yield(function);
  function_compile(function);
#ifdef HAVE_RB_ENSURE

libjit/tools/gen-apply.c  view on Meta::CPAN

int return_doubles_after = 0;
int return_nfloats_after = 0;
int varargs_on_stack = 0;
int struct_return_special_reg = 0;
int struct_reg_overlaps_word_reg = 0;
int struct_return_in_reg[64];
int align_long_regs = 0;
int align_long_stack = 0;
int can_split_long = 0;
int x86_fastcall = 0;
int parent_frame_offset = 0;
int return_address_offset = 0;
int broken_frame_builtins = 0;
int max_struct_in_reg = 0;
int x86_pop_struct_return = 0;
int pad_float_regs = 0;
#else
int num_word_regs = JIT_APPLY_NUM_WORD_REGS;
int num_float_regs = JIT_APPLY_NUM_FLOAT_REGS;
int num_double_regs = JIT_APPLY_NUM_DOUBLE_REGS;
int num_nfloat_regs = JIT_APPLY_NUM_NFLOAT_REGS;

libjit/tools/gen-apply.c  view on Meta::CPAN

int return_doubles_after = JIT_APPLY_RETURN_DOUBLES_AFTER;
int return_nfloats_after = JIT_APPLY_RETURN_NFLOATS_AFTER;
int varargs_on_stack = JIT_APPLY_VARARGS_ON_STACK;
int struct_return_special_reg = JIT_APPLY_STRUCT_RETURN_SPECIAL_REG;
int struct_reg_overlaps_word_reg = JIT_APPLY_STRUCT_REG_OVERLAPS_WORD_REG;
int struct_return_in_reg[64] = JIT_APPLY_STRUCT_RETURN_IN_REG;
int align_long_regs = JIT_APPLY_ALIGN_LONG_REGS;
int align_long_stack = JIT_APPLY_ALIGN_LONG_STACK;
int can_split_long = JIT_APPLY_CAN_SPLIT_LONG;
int x86_fastcall = JIT_APPLY_X86_FASTCALL;
int parent_frame_offset = JIT_APPLY_PARENT_FRAME_OFFSET;
int return_address_offset = JIT_APPLY_RETURN_ADDRESS_OFFSET;
int broken_frame_builtins = JIT_APPLY_BROKEN_FRAME_BUILTINS;
int max_struct_in_reg = JIT_APPLY_MAX_STRUCT_IN_REG;
int x86_pop_struct_return = JIT_APPLY_X86_POP_STRUCT_RETURN;
int pad_float_regs = JIT_APPLY_PAD_FLOAT_REGS;
#endif
int max_apply_size = 0;

void *mem_copy(void *dest, const void *src, unsigned int len)
{

libjit/tools/gen-apply.c  view on Meta::CPAN

	{
		max_apply_size += pad_float_regs * sizeof(jit_nint);
	}
	if(x86_fastcall && max_apply_size < 12)
	{
		max_apply_size = 12;
	}
}

/*
 * Detect the offsets of parent frame and return address pointers
 * in the values returned by "__builtin_frame_address".  We have to
 * do this carefully, to deal with architectures that don't create
 * a real frame for leaf functions.
 */
#if defined(PLATFORM_IS_GCC)
void find_frame_offset_inner(void *looking_for, void **frame)
{
	int offset;
	if(looking_for == (void *)frame || !frame)
	{
		/* Can happen on Alpha platforms */
		broken_frame_builtins = 1;
		return;
	}
	for(offset = 0; offset >= -8; --offset)
	{
		if(frame[offset] == looking_for)
		{
			parent_frame_offset = offset * sizeof(void *);
			return;
		}
	}
	for(offset = 1; offset <= 8; ++offset)
	{
		if(frame[offset] == looking_for)
		{
			parent_frame_offset = offset * sizeof(void *);
			return;
		}
	}
}
void find_frame_offset_outer(void *looking_for)
{
	void *frame_address;
#if defined(_JIT_ARCH_GET_CURRENT_FRAME)
	_JIT_ARCH_GET_CURRENT_FRAME(frame_address);
#else

libjit/tools/gen-apply.c  view on Meta::CPAN

{
	void *frame_address, *return_address;
#if defined(_JIT_ARCH_GET_CURRENT_FRAME)
	_JIT_ARCH_GET_CURRENT_FRAME(frame_address);
#else
	frame_address = __builtin_frame_address(0);
#endif
	return_address = __builtin_return_address(0);
	find_frame_offset_outer(frame_address);
	find_return_offset(return_address, frame_address);
	if(parent_frame_offset == 0 && return_address_offset == 0)
	{
		/* Can happen on platforms like ia64 where there are so
		   many registers that the frame is almost never concrete */
		broken_frame_builtins = 1;
	}
}
#else
void detect_frame_offsets(void)
{
	/* We don't know how to detect the offsets, so assume some defaults */
	parent_frame_offset = 0;
	return_address_offset = sizeof(void *);
}
#endif

/*
 * Dump the definition of the "jit_apply_return" union, which defines
 * the layout of the return value from "__builtin_apply".
 */
void dump_return_union(void)
{

libjit/tools/gen-apply.c  view on Meta::CPAN


	/* Detect whether x86 platforms pop the structure return pointer */
#if defined(PLATFORM_IS_X86)
	x86_pop_struct_return = 1;
	/* TODO */
#endif

	/* Detect the alignment of "long" values */
	detect_long_alignment();

	/* Detect the location of parent frames and return addresses
	   in the value returned by "__builtin_frame_address" */
	detect_frame_offsets();
#endif

	/* Determine the maximum sizes */
	detect_max_sizes();

	/* Print the results */
	printf("/%c This file was auto-generated by \"gen-apply\" - DO NOT EDIT %c/\n\n", '*', '*');
	printf("#ifndef _JIT_APPLY_RULES_H\n");

libjit/tools/gen-apply.c  view on Meta::CPAN

		}
		else
		{
			printf("0x%02X", flags);
		}
	}
	printf("}\n");
	printf("#define JIT_APPLY_MAX_STRUCT_IN_REG %d\n", max_struct_in_reg);
	printf("#define JIT_APPLY_MAX_APPLY_SIZE %d\n", max_apply_size);
	printf("#define JIT_APPLY_X86_FASTCALL %d\n", x86_fastcall);
	printf("#define JIT_APPLY_PARENT_FRAME_OFFSET %d\n", parent_frame_offset);
	printf("#define JIT_APPLY_RETURN_ADDRESS_OFFSET %d\n",
		   return_address_offset);
	printf("#define JIT_APPLY_BROKEN_FRAME_BUILTINS %d\n",
		   broken_frame_builtins);
	printf("#define JIT_APPLY_X86_POP_STRUCT_RETURN %d\n",
		   x86_pop_struct_return);
	printf("#define JIT_APPLY_PAD_FLOAT_REGS %d\n", pad_float_regs);
	printf("\n");

	/* Dump the definition of the "jit_apply_return" union */



( run in 0.728 second using v1.01-cache-2.11-cpan-4d50c553e7e )