Alien-LibJIT

 view release on metacpan or  search on metacpan

libjit/configure.ac  view on Meta::CPAN


dnl Check for computed goto support in the compiler.
AC_MSG_CHECKING(for computed goto support)
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[
	static void *labels[] = {&&label0, &&label1, &&label2};
	unsigned char *pc = 0;
	goto *labels[*pc];
	label0: ;
	label1: ;
	label2: ;
]])], [AC_DEFINE(HAVE_COMPUTED_GOTO, 1, Define if you have support for computed gotos) compgoto=yes], [compgoto=no])
AC_MSG_RESULT($compgoto)
AC_MSG_CHECKING(for pic computed goto support)
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[
	static int labelOffsets[] =
		{&&label0 - &&label0, &&label1 - &&label0, &&label2 - &&label0};
	unsigned char *pc = 0;
	goto *(&&label0 + labelOffsets[*pc]);
	label0: ;
	label1: ;
	label2: ;
]])], [AC_DEFINE(HAVE_PIC_COMPUTED_GOTO, 1, Define if you have PIC support for computed gotos) piccompgoto=yes], [piccompgoto=no])
AC_MSG_RESULT($piccompgoto)

dnl Check for building on a multi os system
if test x$GCC = xyes ; then
	multi_os_directory=`$CC -print-multi-os-directory`
	case $multi_os_directory in
	  .) ;; # Avoid trailing /.
	  *) libdir=$libdir/$multi_os_directory ;;
	esac
fi

libjit/configure.ac  view on Meta::CPAN

  include/jit/Makefile
  include/jit/jit-defs.h
  tools/Makefile
  jit/Makefile
  jitdynamic/Makefile
  jitplus/Makefile
  dpas/Makefile
  tutorial/Makefile
  tests/Makefile
  doc/Makefile])
AC_OUTPUT

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

/*
 * Special tag types.
 */
#define	JIT_TYPETAG_NAME			10000
#define	JIT_TYPETAG_STRUCT_NAME		10001
#define	JIT_TYPETAG_UNION_NAME		10002
#define	JIT_TYPETAG_ENUM_NAME		10003
#define	JIT_TYPETAG_CONST			10004
#define	JIT_TYPETAG_VOLATILE		10005
#define	JIT_TYPETAG_REFERENCE		10006
#define	JIT_TYPETAG_OUTPUT			10007
#define	JIT_TYPETAG_RESTRICT		10008
#define	JIT_TYPETAG_SYS_BOOL		10009
#define	JIT_TYPETAG_SYS_CHAR		10010
#define	JIT_TYPETAG_SYS_SCHAR		10011
#define	JIT_TYPETAG_SYS_UCHAR		10012
#define	JIT_TYPETAG_SYS_SHORT		10013
#define	JIT_TYPETAG_SYS_USHORT		10014
#define	JIT_TYPETAG_SYS_INT			10015
#define	JIT_TYPETAG_SYS_UINT		10016
#define	JIT_TYPETAG_SYS_LONG		10017

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

		#define	alloca	_alloca
	#endif
#endif
#include "jit-setjmp.h"

#if defined(JIT_BACKEND_INTERP)

/*
 * Determine what kind of interpreter dispatch to use.
 */
#ifdef HAVE_COMPUTED_GOTO
	#if defined(PIC) && defined(HAVE_PIC_COMPUTED_GOTO)
		#define	JIT_INTERP_TOKEN_PIC	1
	#elif defined(PIC)
		#define	JIT_INTERP_SWITCH		1
	#else
		#define	JIT_INTERP_TOKEN		1
	#endif
#else /* !HAVE_COMPUTED_GOTO */
	#define	JIT_INTERP_SWITCH			1
#endif /* !HAVE_COMPUTED_GOTO */

/*
 * Modify the program counter and stack pointer.
 */
#define	VM_MODIFY_PC_AND_STACK(pcmod,stkmod)	\
		do { \
			pc += (jit_nint)(int)(pcmod); \
			stacktop += (jit_nint)(int)(stkmod); \
		} while (0)
#define	VM_MODIFY_PC(pcmod) \

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

#define COST_THRASH		100
#define COST_CLOBBER_GLOBAL	1000

#ifdef JIT_BACKEND_X86
# define ALLOW_CLOBBER_GLOBAL	1
#else
# define ALLOW_CLOBBER_GLOBAL	0
#endif

/* Value usage flags. */
#define VALUE_INPUT		1
#define VALUE_USED		2
#define VALUE_LIVE		4
#define VALUE_DEAD		8

/* Clobber flags. */
#define CLOBBER_NONE		0
#define CLOBBER_INPUT_VALUE	1
#define CLOBBER_REG		2
#define CLOBBER_OTHER_REG	4

#ifdef JIT_REG_DEBUG
#include <stdlib.h>

static void dump_regs(jit_gencode_t gen, const char *name)
{
	int reg, index;
	jit_value_t value;

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

	_jit_regdesc_t tdesc;
	tdesc = *desc1;
	*desc1 = *desc2;
	*desc2 = tdesc;
}

/*
 * Get value usage and liveness information. The accurate liveness data is
 * only available for values used by the current instruction.
 *
 * VALUE_INPUT flag is set if the value is one of the instruction's inputs.
 *
 * VALUE_LIVE and VALUE_USED flags are set for input values only according
 * to the liveness flags provided along with the instruction.
 *
 * VALUE_DEAD flag is set in two cases. First, it is always set for output
 * values. Second, it is set for input values that are neither live nor used.
 *
 * These flags are used when spilling a register. In this case we generally
 * do not know if the values in the register are used by the instruction. If
 * the VALUE_INPUT flag is present then it is so and the value has to be held
 * in the register for the instruction to succeed. If the VALUE_DEAD flag is
 * present then there is no need to spill the value and it may be discarded.
 * Otherwise the value must be spilled.
 *
 * The VALUE_LIVE and VALUE_USED flags may only be set for input values of
 * the instruction. For other values these flags are not set even if they are
 * perfectly alive. These flags are used as a hint for spill cost calculation.
 *
 * NOTE: The output value is considered to be dead because the instruction is
 * just about to recompute it so there is no point to save it.

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

		flags |= VALUE_DEAD;
	}
	if(!regs)
	{
		return flags;
	}
	if(value == regs->descs[0].value)
	{
		if(regs->ternary)
		{
			flags |= VALUE_INPUT;
			if(regs->descs[0].used)
			{
				flags |= VALUE_LIVE | VALUE_USED;
			}
			else if(regs->descs[0].live)
			{
				flags |= VALUE_LIVE;
			}
			else
			{
				flags |= VALUE_DEAD;
			}
		}
		else
		{
			flags |= VALUE_DEAD;
		}
	}
	if(value == regs->descs[1].value)
	{
		flags |= VALUE_INPUT;
		if(regs->descs[1].used)
		{
			flags |= VALUE_LIVE | VALUE_USED;
		}
		else if(regs->descs[1].live)
		{
			flags |= VALUE_LIVE;
		}
		else
		{
			flags |= VALUE_DEAD;
		}
	}
	if(value == regs->descs[2].value)
	{
		flags |= VALUE_INPUT;
		if(regs->descs[2].used)
		{
			flags |= VALUE_LIVE | VALUE_USED;
		}
		else if(regs->descs[2].live)
		{
			flags |= VALUE_LIVE;
		}
		else
		{

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

/*
 * Determine the effect of using a register for a value. This includes the
 * following:
 *  - whether the value is clobbered by the instruction;
 *  - whether the previous contents of the register is clobbered.
 *
 * The value is clobbered by the instruction if it is used as input value
 * and the output value will go to the same register and these two values
 * are not equal. Or the instruction has a side effect that destroys the
 * input value regardless of the output. This is indicated with the
 * CLOBBER_INPUT_VALUE flag.
 *
 * The previous content is clobbered if the register contains any non-dead
 * values that are destroyed by loading the input value, by computing the
 * output value, or as a side effect of the instruction.
 *
 * The previous content is not clobbered if the register contains only dead
 * values or it is used for input value that is already in the register so
 * there is no need to load it and at the same time the instruction has no
 * side effects that destroy the input value or the register is used for
 * output value and the only value it contained before is the same value.

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

	if(!regs->descs[index].value)
	{
		return CLOBBER_NONE;
	}

	if(regs->ternary || !regs->descs[0].value)
	{
		/* this is either a ternary or binary or unary note */
		if(regs->descs[index].clobber)
		{
			flags = CLOBBER_INPUT_VALUE;
		}
#ifdef JIT_REG_STACK
		else if(IS_STACK_REG(reg) && !regs->no_pop)
		{
			flags = CLOBBER_INPUT_VALUE;
		}
#endif
		else
		{
			flags = CLOBBER_NONE;
		}
	}
	else if(index == 0)
	{
		/* this is the output value of a binary or unary op */

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

	}
	else if(regs->copy)
	{
		flags = CLOBBER_NONE;
	}
#ifdef JIT_REG_STACK
	else if(IS_STACK_REG(reg) && !regs->no_pop)
	{
		/* this is a binary or unary stack op -- the input value
		   is either popped or overwritten by the output */
		flags = CLOBBER_INPUT_VALUE;
	}
#endif
	else if(reg == regs->descs[0].reg
		|| reg == regs->descs[0].other_reg
		|| other_reg == regs->descs[0].reg)
	{
		/* the input value of a binary or unary op is clobbered
		   by the output value */
		flags = CLOBBER_INPUT_VALUE;
	}
	else if(regs->descs[index].clobber)
	{
		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)

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


	desc = &regs->descs[index];
	if(desc->reg < 0 || desc->duplicate)
	{
		return;
	}

	/* See if the value clobbers the register it is assigned to. */
	clobber = clobbers_register(gen, regs, index, desc->reg, desc->other_reg);
#ifdef JIT_REG_DEBUG
	if((clobber & CLOBBER_INPUT_VALUE) != 0)
	{
		printf("clobber input\n");
	}
	if((clobber & CLOBBER_REG) != 0)
	{
		printf("clobber reg\n");
	}
	if((clobber & CLOBBER_OTHER_REG) != 0)
	{
		printf("clobber other reg\n");

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

			/* See if the input value is destroyed by the instruction. */
			clobber_input = 0;
			if(!desc->copy)
			{
				if(jit_reg_is_used(regs->clobber, desc->reg)
				   || (desc->other_reg >= 0
				       && jit_reg_is_used(regs->clobber, desc->other_reg)))
				{
					clobber_input = 1;
				}
				else if ((clobber & CLOBBER_INPUT_VALUE) != 0)
				{
					clobber_input = 1;
				}
			}
			else if(reg >= 0)
			{
				if(jit_reg_is_used(regs->clobber, reg)
				   || (other_reg >= 0
				       && jit_reg_is_used(regs->clobber, other_reg)))
				{

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

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

		clobber = clobbers_register(gen, regs, index, reg, other_reg);
		if((clobber & CLOBBER_INPUT_VALUE) != 0)
		{
			if(desc->used)
			{
				use_cost += COST_SPILL_CLEAN;
			}
		}
		if((clobber & (CLOBBER_REG | CLOBBER_OTHER_REG)) != 0)
		{
			if(jit_reg_is_used(gen->permanent, reg))
			{

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

	{
		for(index = gen->contents[reg].num_values - 1; index >= 0; --index)
		{
			if(gen->contents[reg].num_values == 1)
			{
				break;
			}

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

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

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

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

		{
			other_reg = -1;
		}

		for(index = gen->contents[reg].num_values - 1; index >= 0; --index)
		{
			value = gen->contents[reg].values[index];
			usage = value_usage(regs, value);
			if((usage & VALUE_DEAD) == 0)
			{
				if((usage & VALUE_INPUT) == 0)
				{
					save_value(gen, value, reg, other_reg, 1);
				}
				else
				{
					save_value(gen, value, reg, other_reg, 0);
				}
			}
			else
			{
				if((usage & VALUE_INPUT) == 0)
				{
					free_value(gen, value, reg, other_reg, 0);
				}
			}
		}
	}
}

static void
update_age(jit_gencode_t gen, _jit_regdesc_t *desc)

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

 * @item JIT_TYPETAG_VOLATILE
 * The underlying value is assumed to be volatile.  The @code{libjit}
 * library will automatically call @code{jit_value_set_volatile} when a
 * value is constructed using this type.
 *
 * @vindex JIT_TYPETAG_REFERENCE
 * @item JIT_TYPETAG_REFERENCE
 * The underlying value is a pointer, but it is assumed to refer to a
 * pass-by-reference parameter.
 *
 * @vindex JIT_TYPETAG_OUTPUT
 * @item JIT_TYPETAG_OUTPUT
 * This is similar to @code{JIT_TYPETAG_REFERENCE}, except that the
 * underlying parameter is assumed to be output-only.
 *
 * @vindex JIT_TYPETAG_RESTRICT
 * @item JIT_TYPETAG_RESTRICT
 * The underlying type is marked as @code{restrict}.  Normally ignored.
 *
 * @vindex JIT_TYPETAG_SYS_BOOL
 * @vindex JIT_TYPETAG_SYS_CHAR
 * @vindex JIT_TYPETAG_SYS_SCHAR

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

		case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_UNION_NAME:
		case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_ENUM_NAME:
		{
			/* Output the qualified name of the type */
			mangle_name_gcc2
				(mangler, (const char *)jit_type_get_tagged_data(type));
		}
		break;

		case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_REFERENCE:
		case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_OUTPUT:
		{
			add_ch(mangler, 'R');
			mangle_type_gcc2
				(mangler, jit_type_get_ref(jit_type_remove_tags(type)));
		}
		break;

		case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_SYS_BOOL:
			add_ch(mangler, 'b'); break;
		case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_SYS_CHAR:

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

		case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_UNION_NAME:
		case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_ENUM_NAME:
		{
			/* Output the qualified name of the type */
			mangle_name_gcc3
				(mangler, (const char *)jit_type_get_tagged_data(type), 0);
		}
		break;

		case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_REFERENCE:
		case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_OUTPUT:
		{
			add_ch(mangler, 'R');
			mangle_type_gcc3
				(mangler, jit_type_get_ref(jit_type_remove_tags(type)));
		}
		break;

		case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_SYS_BOOL:
			add_ch(mangler, 'b'); break;
		case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_SYS_CHAR:

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

		{
			add_ch(mangler, 'W');
			add_ch(mangler, (int)('0' + jit_type_get_size(type)));
			mangle_name_msvc6
				(mangler, (const char *)jit_type_get_tagged_data(type));
			add_string(mangler, "@@");
		}
		break;

		case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_REFERENCE:
		case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_OUTPUT:
		{
			add_ch(mangler, 'A');
			sub_type = jit_type_get_ref(jit_type_remove_tags(type));
			if(jit_type_has_tag(sub_type, JIT_TYPETAG_CONST))
			{
				if(jit_type_has_tag(sub_type, JIT_TYPETAG_VOLATILE))
				{
					add_ch(mangler, 'D');
				}
				else

libjit/tools/gen-rules-parser.y  view on Meta::CPAN


/*
 * Amount of space to reserve for the primary instruction output.
 */
static int gensel_reserve_space = 32;
static int gensel_reserve_more_space = 128;

/*
 * Maximal number of input values in a pattern.
 */
#define MAX_INPUT				3

/*
 * Maximal number of scratch registers in a pattern.
 */
#define MAX_SCRATCH				6

/*
 * Maximal number of pattern elements.
 */
#define MAX_PATTERN				(MAX_INPUT + MAX_SCRATCH)

/*
 * Rule Options.
 */
#define	GENSEL_OPT_TERNARY			1
#define GENSEL_OPT_BRANCH			2
#define GENSEL_OPT_NOTE				3
#define	GENSEL_OPT_COPY				4
#define GENSEL_OPT_COMMUTATIVE			5
#define	GENSEL_OPT_STACK			6

libjit/tools/gen-rules-parser.y  view on Meta::CPAN

			case GENSEL_PATT_LOCAL:
			case GENSEL_PATT_FRAME:
				++locals;
				break;

			case GENSEL_PATT_SCRATCH:
				++scratch;
			}
			pattern = pattern->next;
		}
		if((regs + imms + locals + others) > MAX_INPUT)
		{
			gensel_error(
				clauses->filename,
				clauses->linenum,
				"too many input args in the pattern");
		}
		if(scratch > MAX_SCRATCH)
		{
			gensel_error(
				clauses->filename,

libjit/tools/gen-rules-parser.y  view on Meta::CPAN

	}
	return string;
}

/*
 * Output the clauses for a rule.
 */
static void gensel_output_clauses(gensel_clause_t clauses, gensel_option_t options)
{
	char *name;
	char *args[MAX_INPUT];
	char *names[MAX_PATTERN];
	char *other_names[MAX_PATTERN];
	gensel_clause_t clause;
	gensel_option_t pattern;
	gensel_option_t space, more_space;
	gensel_value_t values;
	int regs, imms, locals, scratch, index;
	int first, seen_option;
	int ternary, free_dest;
	int contains_registers;



( run in 0.493 second using v1.01-cache-2.11-cpan-4e96b696675 )