view release on metacpan or search on metacpan
inc/Module/Build/AlienLibJIT.pm view on Meta::CPAN
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});
sub new {
my ($class, @args) = @_;
return $class->SUPER::new(
#include_dirs => [$LIBJIT_INCLUDE],
#extra_linker_flags => [$LIBJIT_RESULT, '-lpthread'],
@args,
);
}
sub ACTION_code {
my ($self) = @_;
$self->depends_on('libjit');
return $self->SUPER::ACTION_code(@_);
libjit/ChangeLog view on Meta::CPAN
accesses to possibly freed memory.
2009-12-09 Aleksey Demakov <ademakov@gmail.com>
* jit/jit-block.c (_jit_block_record_label): bail out on previously
assigned label.
* jit/jit-block.c (merge_empty): fix label merging.
* jit/jit-internal.h, jit/jit-insn.c (jit_insn_address_of_label)
* jit/jit-block.c (_jit_block_record_label_flags): flag labels that
are taken address of.
* jit/jit-block.c (eliminate_unreachable, _jit_block_clean_cfg):
do not optimize away blocks with labels flagged as being taken
address of.
2009-11-01 Aleksey Demakov <ademakov@gmail.com>
* jit/jit-block.c (_jit_block_clean_cfg): implement the "combine" part
of cleanup algorithm.
2009-10-31 Klaus Treichel <ktreichel@web.de>
* jit/jit-compile.c (_JIT_RESULT_TO_OBJECT, _JIT_RESULT_FROM_OBJECT):
libjit/ChangeLog view on Meta::CPAN
2009-04-21 Aleksey Demakov <ademakov@gmail.com>
* jit/jit-dump.c (jit_dump_insn): fix "call_finally" dump.
2009-04-16 Michele Tartara <mikyt@users.sourceforge.net>
* jit/jit-rules-arm.c: ARM backend fixes.
2009-04-16 Aleksey Demakov <ademakov@gmail.com>
* jit/jit-reg-alloc.c (set_regdesc_flags): fix bug reported by
jan@wedesoft.de.
2009-04-05 Michele Tartara <mikyt@users.sourceforge.net>
* jit/jit-type.c (perform_layout): let struct alignment be greater
than alignment of every indvidual field.
2009-03-28 Aleksey Demakov <ademakov@gmail.com>
* jit/jit-rules.h (jit_reg_name, jit_reg_flags, jit_reg_code); add
convenience macros for register info access.
* jit/jit-rules.h, jit/jit-rules-interp.c, jit/jit-rules-x86.c,
* jit/jit-rules-arm.c (_jit_reg_get_pair, jit_reg_get_pair): add
function and macro for finding register pair.
* jit/jit-reg-alloc.c: replace use of _jit_regs_needs_long_pair with
jit_reg_get_pair().
* jit/jit-reg-alloc.h, jit/jit-reg-alloc.c (_jit_regs_get_cpu)
(_jit_regs_needs_long_pair): remove unused functions.
2009-03-25 Michele Tartara <mikyt@users.sourceforge.net>
libjit/ChangeLog view on Meta::CPAN
2009-02-07 Aleksey Demakov <ademakov@gmail.com>
* gen-sel-parser.y, gen-sel-scanner.l: remove obsolete files.
* tools/Makefile.am: remove gen-sel target.
* jit/jit-apply-arm.h (jit_builtin_apply): fix bug and optimize.
2009-02-06 Klaus Treichel <ktreichel@web.de>
* jit/jit-apply-x86.h: Add @PLT to the definition of JIT_MEMCPY to
prevent set TEXTREL flags in the shared library.
2009-02-06 Michele Tartara <mikyt@users.sourceforge.net>
* jit/jit-rules.h: define JIT_BACKEND_ARM on ARM.
* tools/gen-apply.c: define PLATFORM_IS_ARM on ARM.
* include/jit/jit-arch-arm.h: add ARM arch header.
* jit/Makefile.am, jit/jit-rules-arm.ins, jit/jit-rules-arm.sel:
replace obsolete .sel file for ARM with .ins file.
* jit/jit-apply-arm.h: define jit_indirector_size, jit_should_pad,
override jit_builtin_apply.
libjit/ChangeLog view on Meta::CPAN
* jit/jit-insn.c (jit_insn_sign): the dest value of the sign insn
has to be int regardless of the argument type.
2008-04-13 Klaus Treichel <ktreichel@web.de>
* include/jit/Makefile.am:
* include/jit/jit-arch-x86-64.h: new file with x86-64 architecture
specific macros for stack frame inspection.
* configure.in: check for x86-64 arch, add -fno-omit-frame-pointer
flag.
* include/jit/jit-walk.h: use _JIT_ARCH_GET_RETURN_ADDRESS and
_JIT_ARCH_GET_CURRENT_RETURN if available.
* jit/jit-gen-x86-64.h: Add additional macros for saving and
restoring the fpu controlword and the mxcsr register. Add
additional SSE conversion macros. Add SSE compare macros.
Add macros for the SSE bit operations on packed values.
Add macros for SSE sqrt and rounding. Add macros for fpu rounding.
libjit/ChangeLog view on Meta::CPAN
* jit/jit-apply-x86-64.c: do either a memory indirect, RIP relative
or register relative jump in the redirector whatever is appropriate
for the address location in _jit_create_indirector.
* jit/jit-gen-x86-64.h: add lots of additional code generation
macros and fix some bugs.
* jit/jit-insn.c: don't mark the current block dead after throwing
an exception in jit_insn_call_intrinsic because this is handled in
jit_insn_call_native if the flag JIT_CALL_NORETURN is specified.
* jit/Makefile.am: Add the new files jit-rules-x86-64.c,
jit-rules-x86-64.h and jit-rules-x86-64.ins to the sources.
* jit/jit-rules.h: add the native backend for X86_64.
* jit/jit-rules-x86-64.c, jit/jit-rules-x86-64.h,
jit/jit-rules-x86-64.ins: add the first native code generation for
X86_64.
libjit/ChangeLog view on Meta::CPAN
* jit/jit-live.c (forward_propagation, backward_propagation): do not
optimize addressable and volatile values.
2007-05-28 Aleksey Demakov <ademakov@gmail.com>
* jit/jit-live.c (_jit_function_compute_liveness)
(forward_propagation, backward_propagation): add simple copy
propagation that works only within basic blocks.
* jit/jit-value.c (jit_value_ref): do not set the live flag here
as this is done in jit-live.c now.
2007-05-26 Klaus Treichel <ktreichel@web.de>
* jit/jit-intrinsic.c: Fix conversion from ulong to nfloat for values
greater that jit_max_long.
2007-05-26 Aleksey Demakov <ademakov@gmail.com>
* jit/jit-insn.c (jit_insn_store): remove incorrect optimization
libjit/ChangeLog view on Meta::CPAN
* jit/jit-reg-alloc.h, jit/jit-reg-alloc.c: remove _jit_regs_abort()
function as the new cleanup-on-restart code makes it superflows.
* jit/jit-reg-alloc.c (is_register_occupied): add new function;
(clobbers_register, spill_clobbered_register, _jit_regs_gen): fix
a problem that shows up with the new cleanup method.
* tools/gen-rules-parser.y (gensel_output_clauses): the conditions
for the local and frame patterns are changed. If the value is used
before it is defined then both in_frame and in_register flags are
clear. This situation is perfectly valid if there is a backward
branch form a point after the definition to a point before the use.
So if the value is not a constant and it is not in a register assume
that it is on the stack even if the in_frame flag is not set.
2007-02-10 Klaus Treichel <ktreichel@web.de>
* jit/jit-function.c: Use the on-demand compilation driver in
jit_function_apply too. Return the functions' entry point if the
function is allready compiled in jit_function_compile_entry.
2007-02-04 Aleksey Demakov <ademakov@gmail.com>
* include/jit/jit-common.h, include/jit/jit-context.h,
* include/jit/jit-function.h, jit/jit-internal.h, jit/jit-context.c,
* jit/jit-function.c: provide for user defined on-demand compilation
driver and delayed function entry point setup.
2007-01-28 Aleksey Demakov <ademakov@gmail.com>
* jit/jit-reg-alloc.c (_jit_regs_gen, set_regdesc_flags): fix bugs
introduced 2006-12-30 with loading registers for ternary ops and
handling input register thrash.
2007-01-26 Aleksey Demakov <ademakov@gmail.com>
* include/jit/jit-arch-x86.h (_JIT_ARCH_GET_CURRENT_FRAME): tweak
gcc version of the macro.
* jit/jit-apply-x86.c (_jit_create_redirector): redirector does not
use stack frame so remove frame set up and restore instructions.
libjit/ChangeLog view on Meta::CPAN
* jit/jit-rules-alpha.c: initialize alpha register classes.
Fix signed-ness warnings.
2007-01-02 Aleksey Demakov <ademakov@gmail.com>
* jit/jit-rules-x86.ins: add JIT_OP_IMIN_UN rule (based on the
patch #5540 by Kirill Kononenko).
* jit/jit-reg-alloc.c (set_regdesc_value, set_regdesc_register)
(choose_output_register): handle EARLY_CLOBBER flag for dest value.
2006-12-30 Aleksey Demakov <ademakov@gmail.com>
* jit/jit-reg-class.c, jit/jit-reg-class.h, jit/Makefile.am: add
register classes.
* jit/jit-rules-x86.c (_jit_init_backend): initialize x86 register
classes.
* jit/jit-reg-alloc.h, jit/jit-reg-alloc.c: specify register class
libjit/ChangeLog view on Meta::CPAN
* configure.in: remove --enable-new-reg-alloc option.
* jit/jit-rules-x86.ins: simplify JIT_OP_RETURN_LONG rule, lift code
from load_small_struct() function to JIT_OP_RETURN_SMALL_STRUCT rule.
* jit/jit-rules-x86.c: remove load_small_struct() function.
2006-09-09 Aleksey Demakov <ademakov@gmail.com>
* jit/jit-reg-alloc.h, jit/jit-reg-alloc.c:
* tools/gen-rules-parser.y: add _JIT_REGS_CLOBBER_STACK flag and use
it in the code generated for "only" rules instead of the explicit
stack top check followed by the _jit_regs_spill_all() call.
2006-09-02 Aleksey Demakov <ademakov@gmail.com>
* jit/jit-interp.c (_jit_run_function):
* jit/jit-rules-interp.c (_jit_gen_insn): remove last traces of
register allocation from the interpreter.
2006-08-31 Klaus Treichel <ktreichel@web.de>
libjit/ChangeLog view on Meta::CPAN
* jit/jit-insn.c (jit_insn_return, jit_insn_return_ptr): do not pop
the setjmp context for the interpreter backend because it takes care
of this by itself.
* jit/jit-rules.h, jit/jit-rules-alpha.c, jit/jit-rules-arm.c,
* jit/jit-rules-interp.c, jit/jit-rules-x86.c, jit/jit-reg-alloc.c:
move part of the _jit_gen_exch_top() functionality into a separate
_jit_gen_move_top() function.
* include/jit/jit-opcode.h:
* jit/jit-opcode.c: add JIT_OPCODE_IS_JUMP_TABLE flag to mark the
JIT_OP_JUMP_TABLE opcode.
* jit/jit-dump.c (jit_dump_insn, dump_interp_code): add jump table
dumping.
2006-08-28 Klaus Treichel <ktreichel@web.de>
* dpas/Makefile.am, jit/Makefile.am, tests/Makefile.am: Add missing
sources to fix creation of tarballs (make dist).
libjit/ChangeLog view on Meta::CPAN
2006-08-20 Thomas Cort <linuxgeek@gmail.com>
* jit/jit-apply-alpha.c jit/jit-apply-alpha.h jit/jit-rules-alpha.h
jit/jit-rules-alpha.ins jit/jit-rules-alpha.c jit/jit-gen-alpha.h:
Remove unnecessary code from the prolog, epilog, redirector, and
closure. Implement > and >= opcodes for signed and unsigned values.
2006-08-19 Aleksey Demakov <ademakov@gmail.com>
* jit/jit-reg-alloc.c (set_regdesc_flags): fix a problem with the
clobber flag being ignored. The problem was introduced by the patch
from 2006-06-17.
2006-08-15 Thomas Cort <linuxgeek@gmail.com>
* jit/jit-rules-alpha.c jit/jit-rules-alpha.h jit/jit-rules-alpha.ins
Add a TODO() macro to print unimplemented warnings. Fix some
casting warnings. Implement _jit_gen_redirector(...). Fix
JIT_CDECL_WORD_REG_PARAMS to use the correct parameter
registers. Add some stack push and pop instructions.
libjit/ChangeLog view on Meta::CPAN
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.
Continue to implement more functions in jit/jit-rules-alpha.c.
2006-07-15 Thomas Cort <linuxgeek@gmail.com>
libjit/ChangeLog view on Meta::CPAN
removes unused values just as well but with enough knowledge to be
safe. The new code also does not move JIT_OP_ADDRESS_OF towards the
relative instructions that uses the address. Supposedly such move
may be used by the code generator as a hint. However currently the
code generator does not use such a hint. The old code is kept for
reference #ifdefed out.
2006-06-17 Aleksey Demakov <ademakov@gmail.com>
* jit/jit-reg-alloc.h, jit/jit-reg-alloc.c: implement support of the
JIT_REGS_FREE_DEST flag for 3-argument instructions. Tweak reg alloc
API.
* tools/gen-rules-parser.y: adjust for reg alloc API changes. Use
'$0' pattern element to refer to destination register in 3-argument
instructions.
* jit/jit-rules-x86.ins: rewrite JIT_OP_IDIV, JIT_OP_IDIV_UN,
JIT_OP_IREM, JIT_OP_IREM_UN, JIT_OP_ADDRESS_OF_LABEL,
JIT_OP_LOAD_RELATIVE_FLOAT32, JIT_OP_LOAD_RELATIVE_FLOAT32,
JIT_OP_LOAD_RELATIVE_NFLOAT, JIT_OP_LOAD_ELEMENT_FLOAT32,
libjit/ChangeLog view on Meta::CPAN
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>
* jit/jit-reg-alloc.h: add _JIT_REGS_FREE_DEST flag to be used in
cases when the destination register is independent of any input
register.
* tools/gen-rules-parser.y: allow specification of independent
destination register with '=reg' pattern syntax. (But the allocator
does not yet handle this.)
2006-05-20 Aleksey Demakov <ademakov@gmail.com>
* jit/jit-rules-x86.c (_jit_gen_exch_top): fix computation of stack
register index.
libjit/ChangeLog view on Meta::CPAN
* tools/gen-apply.c: fix a crash in gen-apply under x86-64.
* jit/jit-apply-func.h, jit/jit-apply-x86-64.h, tools/gen-apply.c:
write an x86-64 assembly version of "__builtin_apply", because
the version inside gcc has an unusable register ordering.
2004-06-24 Rhys Weatherley <rweather@southern-storm.com.au>
* jit/jit-reg-alloc.c, jit/jit-rules-arm.h, jit/jit-rules-interp.c,
jit/jit-rules-interp.h, jit/jit-rules-x86.h, jit/jit-rules.h:
use separate JIT_REG_xxx flags for float32, float64, and nfloat
because some platforms need to put these values in different
types of registers (e.g. x86-64).
2004-06-22 Rhys Weatherley <rweather@southern-storm.com.au>
* jit/jit-insn.c: properly set the "may_throw" flag for opcodes
that throw exceptions and which are also supported by the back end.
2004-06-21 Rhys Weatherley <rweather@southern-storm.com.au>
* jit/jit-rules-x86.c, jit/jit-rules-x86.sel: move the code
for loading/storing small structures into a central location.
2004-06-18 Rhys Weatherley <rweather@southern-storm.com.au>
* jit/jit-dump.c, jit/jit-reg-alloc.c, jit/jit-rules-arm.c,
libjit/ChangeLog view on Meta::CPAN
2004-04-27 Rhys Weatherley <rweather@southern-storm.com.au>
* jit/jit-dump.c, jit/jit-reg-alloc.c: fix a register stack bug
in "_jit_regs_set_value"; add some more debug code.
* include/jit/jit-opcode.h, jit/jit-insn.c, jit/jit-internal.h,
jit/jit-interp.cpp, jit/jit-opcode.c: wrap function calls
with code to set up and remove exception frame information.
* jit/jit-function.c, jit/jit-insn.c, jit/jit-internal.h:
intuit "nothrow" and "noreturn" flags for compiled functions.
* include/jit/jit-insn.h, include/jit/jit-plus.h, jit/jit-insn.c,
jitplus/jit-plus-function.cpp: add "jit_insn_throw",
"jit_insn_rethrow", and "jit_insn_get_call_stack" to assist
with throwing exceptions.
* include/jit/jit-insn.h, jit/jit-block.c, jit/jit-insn.c,
jit/jit-internal.h: add some instructions for managing "try" blocks.
* include/jit/jit-opcode.h, jit/jit-block.c, jit/jit-insn.c,
libjit/ChangeLog view on Meta::CPAN
and "jit_function_apply_vararg" for the interpreter back end.
* jitplus/jit-plus-function.cpp: initialization errors in
the C++ binding.
* jit/jit-function.c, jit/jit-insn.c, jit/jit-interp.cpp,
jit/jit-rules-interp.c: work on code generation for function calls.
* doc/libjit.texi, include/jit/jit-insn.h, include/jit/jit-plus.h,
jit/jit-insn.c, jitplus/jit-plus-function.cpp, tutorial/t2.c:
add a "flags" parmeter to "jit_insn_call" and friends, so that
"nothrow", "noreturn", and "tail" options can be supplied.
* jit/jit-dump.c, jit/jit-interp.cpp, jit/jit-interp.h,
jit/jit-opcode.c, jit/jit-rules-interp.c: dump the translated
native code from "jit_dump_function" are compilation.
* jit/jit-interp.cpp, jit/jit-rules-interp.c: argument variable
offsets should in item units, not byte units.
* jit/jit-insn.c, jit/jit-reg-alloc.c, jit/jit-reg-alloc.h,
libjit/configure.ac view on Meta::CPAN
AC_PROG_CXX
AM_PROG_AR
AC_PROG_INSTALL
AC_PROG_LN_S
AC_PROG_MAKE_SET
AC_PROG_YACC
AM_PROG_LEX
AC_LIBTOOL_WIN32_DLL
AC_PROG_LIBTOOL
dnl Set the correct flags for compiling with MSVC. "/QIfist" is needed
dnl on systems with both VC 6.0 and VC 7.0 installed: sometimes VC 7.0
dnl picks up the wrong intrinsic libraries (particularly for __ftol2).
dnl The "/EHs" option is required to enable exception handling in C++.
if test "x$CC" = "xcl" ; then
CFLAGS="/nologo /QIfist"
CXXFLAGS="/nologo /QIfist /EHs"
fi
dnl Check for file extensions.
AC_EXEEXT
libjit/doc/libjit.texi view on Meta::CPAN
When the on-demand compiler returns, @code{libjit} will call
@code{jit_function_compile} and then jump to the newly compiled code.
Upon the second and subsequent calls to the function, @code{libjit}
will bypass the on-demand compiler and call the compiled code directly.
Note that in case of on-demand compilation @code{libjit} automatically
locks and unlocks the corresponding context with
@code{jit_context_build_start} and @code{jit_context_build_end} calls.
Sometimes you may wish to force a commonly used function to
be recompiled, so that you can apply additional optimization.
To do this, you must set the "recompilable" flag just after the
function is first created:
@example
jit_function_t function;
...
function = jit_function_create(context, signature);
jit_function_set_recompilable(function);
jit_function_set_on_demand_compiler(function, compile_mul_add);
@end example
libjit/doc/libjit.texi view on Meta::CPAN
@node Tutorial 5, Dynamic Pascal, Tutorial 4, Tutorials
@section Tutorial 5 - gcd, with tail calls
@cindex gcd with tail calls
Astute readers would have noticed that Tutorial 2 included two instances
of "tail calls". That is, calls to the same function that are immediately
followed by a @code{return} instruction.
Libjit can optimize tail calls if you provide the @code{JIT_CALL_TAIL}
flag to @code{jit_insn_call}. Previously, we used the following code
to call @code{gcd} recursively:
@example
temp3 = jit_insn_call
(function, "gcd", function, 0, temp_args, 2, 0);
jit_insn_return(function, temp3);
@end example
@noindent
In Tutorial 5, this is modified to the following:
libjit/doc/libjit.texi view on Meta::CPAN
of the function.
Tail calls can only be used in certain circumstances. The source
and destination of the call must have the same function signatures.
None of the parameters should point to local variables in the current
stack frame. And tail calls cannot be used from any source function
that uses @code{try} or @code{alloca} statements.
Because it can be difficult for @code{libjit} to determine when these
conditions have been met, it relies upon the caller to supply the
@code{JIT_CALL_TAIL} flag when it is appropriate to use a tail call.
@c -----------------------------------------------------------------------
@node Dynamic Pascal, Initialization, Tutorial 5, Tutorials
@section Dynamic Pascal - A full JIT example
@cindex Dynamic Pascal
This @code{libjit/dpas} directory contains an implementation of
"Dynamic Pascal", or "dpas" as we like to call it. It is provided
as an example of using @code{libjit} in a real working environment.
libjit/dpas/dpas-parser.y view on Meta::CPAN
* Imports from the lexical analyser.
*/
extern int yylex(void);
#ifdef YYTEXT_POINTER
extern char *yytext;
#else
extern char yytext[];
#endif
/*
* Error reporting flag.
*/
int dpas_error_reported = 0;
/*
* Function dumping flag.
*/
int dpas_dump_functions = 0;
/*
* Report error messages from the parser.
*/
static void yyerror(char *msg)
{
char *text = yytext;
char *newmsg;
libjit/include/jit/jit-debugger.h view on Meta::CPAN
#define JIT_DEBUGGER_TYPE_QUIT 0
#define JIT_DEBUGGER_TYPE_HARD_BREAKPOINT 1
#define JIT_DEBUGGER_TYPE_SOFT_BREAKPOINT 2
#define JIT_DEBUGGER_TYPE_USER_BREAKPOINT 3
#define JIT_DEBUGGER_TYPE_ATTACH_THREAD 4
#define JIT_DEBUGGER_TYPE_DETACH_THREAD 5
typedef struct jit_debugger_breakpoint_info
{
int flags;
jit_debugger_thread_id_t thread;
jit_function_t function;
jit_nint data1;
jit_nint data2;
} *jit_debugger_breakpoint_info_t;
#define JIT_DEBUGGER_FLAG_THREAD (1 << 0)
#define JIT_DEBUGGER_FLAG_FUNCTION (1 << 1)
#define JIT_DEBUGGER_FLAG_DATA1 (1 << 2)
libjit/include/jit/jit-debugger.h view on Meta::CPAN
jit_context_t jit_debugger_get_context(jit_debugger_t dbg) JIT_NOTHROW;
jit_debugger_t jit_debugger_from_context(jit_context_t context) JIT_NOTHROW;
jit_debugger_thread_id_t jit_debugger_get_self(jit_debugger_t dbg) JIT_NOTHROW;
jit_debugger_thread_id_t jit_debugger_get_thread
(jit_debugger_t dbg, const void *native_thread) JIT_NOTHROW;
int jit_debugger_get_native_thread
(jit_debugger_t dbg, jit_debugger_thread_id_t thread,
void *native_thread) JIT_NOTHROW;
void jit_debugger_set_breakable
(jit_debugger_t dbg, const void *native_thread, int flag) JIT_NOTHROW;
void jit_debugger_attach_self
(jit_debugger_t dbg, int stop_immediately) JIT_NOTHROW;
void jit_debugger_detach_self(jit_debugger_t dbg) JIT_NOTHROW;
int jit_debugger_wait_event
(jit_debugger_t dbg, jit_debugger_event_t *event,
jit_int timeout) JIT_NOTHROW;
jit_debugger_breakpoint_id_t jit_debugger_add_breakpoint
libjit/include/jit/jit-dynamic.h view on Meta::CPAN
/*
* Dynamic library routines.
*/
typedef void *jit_dynlib_handle_t;
jit_dynlib_handle_t jit_dynlib_open(const char *name) JIT_NOTHROW;
void jit_dynlib_close(jit_dynlib_handle_t handle) JIT_NOTHROW;
void *jit_dynlib_get_symbol
(jit_dynlib_handle_t handle, const char *symbol) JIT_NOTHROW;
const char *jit_dynlib_get_suffix(void) JIT_NOTHROW;
void jit_dynlib_set_debug(int flag) JIT_NOTHROW;
/*
* C++ name mangling definitions.
*/
#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/include/jit/jit-elf.h view on Meta::CPAN
#define JIT_READELF_CANNOT_OPEN 1 /* Could not open the file */
#define JIT_READELF_NOT_ELF 2 /* Not an ELF-format binary */
#define JIT_READELF_WRONG_ARCH 3 /* Wrong architecture for local system */
#define JIT_READELF_BAD_FORMAT 4 /* ELF file, but badly formatted */
#define JIT_READELF_MEMORY 5 /* Insufficient memory to load the file */
/*
* External function declarations.
*/
int jit_readelf_open
(jit_readelf_t *readelf, const char *filename, int flags) JIT_NOTHROW;
void jit_readelf_close(jit_readelf_t readelf) JIT_NOTHROW;
const char *jit_readelf_get_name(jit_readelf_t readelf) JIT_NOTHROW;
void *jit_readelf_get_symbol
(jit_readelf_t readelf, const char *name) JIT_NOTHROW;
void *jit_readelf_get_section
(jit_readelf_t readelf, const char *name, jit_nuint *size) JIT_NOTHROW;
void *jit_readelf_get_section_by_type
(jit_readelf_t readelf, jit_int type, jit_nuint *size) JIT_NOTHROW;
void *jit_readelf_map_vaddr
(jit_readelf_t readelf, jit_nuint vaddr) JIT_NOTHROW;
libjit/include/jit/jit-insn.h view on Meta::CPAN
(jit_function_t func, jit_value_t value1) JIT_NOTHROW;
jit_value_t jit_insn_address_of_label
(jit_function_t func, jit_label_t *label) JIT_NOTHROW;
jit_value_t jit_insn_convert
(jit_function_t func, jit_value_t value,
jit_type_t type, int overflow_check) JIT_NOTHROW;
jit_value_t jit_insn_call
(jit_function_t func, const char *name,
jit_function_t jit_func, jit_type_t signature,
jit_value_t *args, unsigned int num_args, int flags) JIT_NOTHROW;
jit_value_t jit_insn_call_indirect
(jit_function_t func, jit_value_t value, jit_type_t signature,
jit_value_t *args, unsigned int num_args, int flags) JIT_NOTHROW;
jit_value_t jit_insn_call_indirect_vtable
(jit_function_t func, jit_value_t value, jit_type_t signature,
jit_value_t *args, unsigned int num_args, int flags) JIT_NOTHROW;
jit_value_t jit_insn_call_native
(jit_function_t func, const char *name,
void *native_func, jit_type_t signature,
jit_value_t *args, unsigned int num_args, int flags) JIT_NOTHROW;
jit_value_t jit_insn_call_intrinsic
(jit_function_t func, const char *name, void *intrinsic_func,
const jit_intrinsic_descr_t *descriptor,
jit_value_t arg1, jit_value_t arg2) JIT_NOTHROW;
int jit_insn_incoming_reg
(jit_function_t func, jit_value_t value, int reg) JIT_NOTHROW;
int jit_insn_incoming_frame_posn
(jit_function_t func, jit_value_t value, jit_nint frame_offset) JIT_NOTHROW;
int jit_insn_outgoing_reg
(jit_function_t func, jit_value_t value, int reg) JIT_NOTHROW;
libjit/include/jit/jit-objmodel-private.h view on Meta::CPAN
(jit_objmodel_t model, jitom_class_t klass, unsigned int *num);
jitom_class_t *(*class_get_interfaces)
(jit_objmodel_t model, jitom_class_t klass, unsigned int *num);
jitom_field_t *(*class_get_fields)
(jit_objmodel_t model, jitom_class_t klass, unsigned int *num);
jitom_method_t *(*class_get_methods)
(jit_objmodel_t model, jitom_class_t klass, unsigned int *num);
jit_value_t (*class_new)
(jit_objmodel_t model, jitom_class_t klass,
jitom_method_t ctor, jit_function_t func,
jit_value_t *args, unsigned int num_args, int flags);
jit_value_t (*class_new_value)
(jit_objmodel_t model, jitom_class_t klass,
jitom_method_t ctor, jit_function_t func,
jit_value_t *args, unsigned int num_args, int flags);
int (*class_delete)
(jit_objmodel_t model, jitom_class_t klass, jit_value_t obj_value);
int (*class_add_ref)
(jit_objmodel_t model, jitom_class_t klass, jit_value_t obj_value);
/*
* Operations on object model fields.
*/
char *(*field_get_name)
(jit_objmodel_t model, jitom_class_t klass, jitom_field_t field);
libjit/include/jit/jit-objmodel-private.h view on Meta::CPAN
*/
char *(*method_get_name)
(jit_objmodel_t model, jitom_class_t klass, jitom_method_t method);
jit_type_t (*method_get_type)
(jit_objmodel_t model, jitom_class_t klass, jitom_method_t method);
int (*method_get_modifiers)
(jit_objmodel_t model, jitom_class_t klass, jitom_method_t method);
jit_value_t (*method_invoke)
(jit_objmodel_t model, jitom_class_t klass, jitom_method_t method,
jit_function_t func, jit_value_t *args,
unsigned int num_args, int flags);
jit_value_t (*method_invoke_virtual)
(jit_objmodel_t model, jitom_class_t klass, jitom_method_t method,
jit_function_t func, jit_value_t *args,
unsigned int num_args, int flags);
};
#ifdef __cplusplus
};
#endif
#endif /* _JIT_OBJMODEL_PRIVATE_H */
libjit/include/jit/jit-objmodel.h view on Meta::CPAN
/*
* Opaque types that describe object model elements.
*/
typedef struct jit_objmodel *jit_objmodel_t;
typedef struct jitom_class *jitom_class_t;
typedef struct jitom_field *jitom_field_t;
typedef struct jitom_method *jitom_method_t;
/*
* Modifier flags that describe an item's properties.
*/
#define JITOM_MODIFIER_ACCESS_MASK 0x0007
#define JITOM_MODIFIER_PUBLIC 0x0000
#define JITOM_MODIFIER_PRIVATE 0x0001
#define JITOM_MODIFIER_PROTECTED 0x0002
#define JITOM_MODIFIER_PACKAGE 0x0003
#define JITOM_MODIFIER_PACKAGE_OR_PROTECTED 0x0004
#define JITOM_MODIFIER_PACKAGE_AND_PROTECTED 0x0005
#define JITOM_MODIFIER_OTHER1 0x0006
#define JITOM_MODIFIER_OTHER2 0x0007
libjit/include/jit/jit-objmodel.h view on Meta::CPAN
(jit_objmodel_t model, jitom_class_t klass, unsigned int *num) JIT_NOTHROW;
jitom_class_t *jitom_class_get_interfaces
(jit_objmodel_t model, jitom_class_t klass, unsigned int *num) JIT_NOTHROW;
jitom_field_t *jitom_class_get_fields
(jit_objmodel_t model, jitom_class_t klass, unsigned int *num) JIT_NOTHROW;
jitom_method_t *jitom_class_get_methods
(jit_objmodel_t model, jitom_class_t klass, unsigned int *num) JIT_NOTHROW;
jit_value_t jitom_class_new
(jit_objmodel_t model, jitom_class_t klass,
jitom_method_t ctor, jit_function_t func,
jit_value_t *args, unsigned int num_args, int flags) JIT_NOTHROW;
jit_value_t jitom_class_new_value
(jit_objmodel_t model, jitom_class_t klass,
jitom_method_t ctor, jit_function_t func,
jit_value_t *args, unsigned int num_args, int flags) JIT_NOTHROW;
int jitom_class_delete
(jit_objmodel_t model, jitom_class_t klass,
jit_value_t obj_value) JIT_NOTHROW;
int jitom_class_add_ref
(jit_objmodel_t model, jitom_class_t klass,
jit_value_t obj_value) JIT_NOTHROW;
/*
* Operations on object model fields.
*/
libjit/include/jit/jit-objmodel.h view on Meta::CPAN
jitom_method_t method) JIT_NOTHROW;
jit_type_t jitom_method_get_type
(jit_objmodel_t model, jitom_class_t klass,
jitom_method_t method) JIT_NOTHROW;
int jitom_method_get_modifiers
(jit_objmodel_t model, jitom_class_t klass,
jitom_method_t method) JIT_NOTHROW;
jit_value_t jitom_method_invoke
(jit_objmodel_t model, jitom_class_t klass, jitom_method_t method,
jit_function_t func, jit_value_t *args,
unsigned int num_args, int flags) JIT_NOTHROW;
jit_value_t jitom_method_invoke_virtual
(jit_objmodel_t model, jitom_class_t klass, jitom_method_t method,
jit_function_t func, jit_value_t *args,
unsigned int num_args, int flags) JIT_NOTHROW;
/*
* Manipulate types that represent objects and inline values.
*/
jit_type_t jitom_type_tag_as_class
(jit_type_t type, jit_objmodel_t model,
jitom_class_t klass, int incref) JIT_NOTHROW;
jit_type_t jitom_type_tag_as_value
(jit_type_t type, jit_objmodel_t model,
jitom_class_t klass, int incref) JIT_NOTHROW;
libjit/include/jit/jit-plus.h view on Meta::CPAN
void create();
int compile();
int is_compiled() const { return jit_function_is_compiled(func); }
int is_recompilable() const { return jit_function_is_recompilable(func); }
void set_recompilable() { jit_function_set_recompilable(func); }
void clear_recompilable() { jit_function_clear_recompilable(func); }
void set_recompilable(int flag)
{ if(flag) set_recompilable(); else clear_recompilable(); }
void set_optimization_level(unsigned int level)
{ jit_function_set_optimization_level(func, level); }
unsigned int optimization_level() const
{ return jit_function_get_optimization_level(func); }
static unsigned int max_optimization_level()
{ return jit_function_get_max_optimization_level(); }
void *closure() const { return jit_function_to_closure(func); }
void *vtable_pointer() const
libjit/include/jit/jit-plus.h view on Meta::CPAN
void insn_branch_if(const jit_value& value, jit_label& label);
void insn_branch_if_not(const jit_value& value, jit_label& label);
void insn_jump_table(const jit_value& value, jit_jump_table& jump_table);
jit_value insn_address_of(const jit_value& value1);
jit_value insn_address_of_label(jit_label& label);
jit_value insn_convert
(const jit_value& value, jit_type_t type, int overflow_check=0);
jit_value insn_call
(const char *name, jit_function_t jit_func,
jit_type_t signature, jit_value_t *args, unsigned int num_args,
int flags=0);
jit_value insn_call_indirect
(const jit_value& value, jit_type_t signature,
jit_value_t *args, unsigned int num_args, int flags=0);
jit_value insn_call_indirect_vtable
(const jit_value& value, jit_type_t signature,
jit_value_t *args, unsigned int num_args, int flags=0);
jit_value insn_call_native
(const char *name, void *native_func, jit_type_t signature,
jit_value_t *args, unsigned int num_args, int flags=0);
jit_value insn_call_intrinsic
(const char *name, void *intrinsic_func,
const jit_intrinsic_descr_t& descriptor,
const jit_value& arg1, const jit_value& arg2);
void insn_incoming_reg(const jit_value& value, int reg);
void insn_incoming_frame_posn(const jit_value& value, jit_nint posn);
void insn_outgoing_reg(const jit_value& value, int reg);
void insn_outgoing_frame_posn(const jit_value& value, jit_nint posn);
void insn_return_reg(const jit_value& value, int reg);
void insn_setup_for_nested(int nested_level, int reg);
libjit/jit/jit-alloc.c view on Meta::CPAN
while (p < end)
{
__asm__ __volatile__ ("flush %0" :: "r"(p));
p += CLSIZE;
}
__asm__ __volatile__ ("nop; nop; nop; nop; nop");
#elif (defined(__arm__) || defined(__arm)) && defined(linux)
/* ARM Linux has a "cacheflush" system call */
/* R0 = start of range, R1 = end of range, R3 = flags */
/* flags = 0 indicates data cache, flags = 1 indicates both caches */
__asm __volatile ("mov r0, %0\n"
"mov r1, %1\n"
"mov r2, %2\n"
"swi 0x9f0002 @ sys_cacheflush"
: /* no outputs */
: "r" (ptr),
"r" (((int)ptr) + (int)size),
"r" (0)
: "r0", "r1", "r3" );
libjit/jit/jit-block.c view on Meta::CPAN
/* helper data structure for CFG DFS traversal */
typedef struct _jit_block_stack_entry
{
jit_block_t block;
int index;
} _jit_block_stack_entry_t;
static void
create_edge(jit_function_t func, jit_block_t src, jit_block_t dst, int flags, int create)
{
_jit_edge_t edge;
/* Create edge if required */
if(create)
{
/* Allocate memory for it */
edge = jit_memory_pool_alloc(&func->builder->edge_pool, struct _jit_edge);
if(!edge)
{
jit_exception_builtin(JIT_RESULT_OUT_OF_MEMORY);
}
/* Initialize edge fields */
edge->src = src;
edge->dst = dst;
edge->flags = flags;
/* Store edge pointers in source and destination nodes */
src->succs[src->num_succs] = edge;
dst->preds[dst->num_preds] = edge;
}
/* Count it */
++(src->num_succs);
++(dst->num_preds);
}
static void
build_edges(jit_function_t func, int create)
{
jit_block_t src, dst;
jit_insn_t insn;
int opcode, flags;
jit_label_t *labels;
int index, num_labels;
/* TODO: Handle catch, finally, filter blocks. */
for(src = func->builder->entry_block; src != func->builder->exit_block; src = src->next)
{
/* Check the last instruction of the block */
insn = _jit_block_get_last(src);
opcode = insn ? insn->opcode : JIT_OP_NOP;
if(opcode >= JIT_OP_RETURN && opcode <= JIT_OP_RETURN_SMALL_STRUCT)
{
flags = _JIT_EDGE_RETURN;
dst = func->builder->exit_block;
}
else if(opcode == JIT_OP_BR)
{
flags = _JIT_EDGE_BRANCH;
dst = jit_block_from_label(func, (jit_label_t) insn->dest);
if(!dst)
{
/* Bail out on undefined label */
jit_exception_builtin(JIT_RESULT_UNDEFINED_LABEL);
}
}
else if(opcode > JIT_OP_BR && opcode <= JIT_OP_BR_NFGE_INV)
{
flags = _JIT_EDGE_BRANCH;
dst = jit_block_from_label(func, (jit_label_t) insn->dest);
if(!dst)
{
/* Bail out on undefined label */
jit_exception_builtin(JIT_RESULT_UNDEFINED_LABEL);
}
}
else if(opcode == JIT_OP_THROW || opcode == JIT_OP_RETHROW)
{
flags = _JIT_EDGE_EXCEPT;
dst = jit_block_from_label(func, func->builder->catcher_label);
if(!dst)
{
dst = func->builder->exit_block;
}
}
else if(opcode == JIT_OP_CALL_FINALLY || opcode == JIT_OP_CALL_FILTER)
{
flags = _JIT_EDGE_EXCEPT;
dst = jit_block_from_label(func, (jit_label_t) insn->dest);
if(!dst)
{
/* Bail out on undefined label */
jit_exception_builtin(JIT_RESULT_UNDEFINED_LABEL);
}
}
else if(opcode >= JIT_OP_CALL && opcode <= JIT_OP_CALL_EXTERNAL_TAIL)
{
flags = _JIT_EDGE_EXCEPT;
dst = jit_block_from_label(func, func->builder->catcher_label);
if(!dst)
{
dst = func->builder->exit_block;
}
}
else if(opcode == JIT_OP_JUMP_TABLE)
{
labels = (jit_label_t *) insn->value1->address;
num_labels = (int) insn->value2->address;
libjit/jit/jit-block.c view on Meta::CPAN
dst = 0;
}
else
{
dst = 0;
}
/* create a branch or exception edge if appropriate */
if(dst)
{
create_edge(func, src, dst, flags, create);
}
/* create a fall-through edge if appropriate */
if(!src->ends_in_dead)
{
create_edge(func, src, src->next, _JIT_EDGE_FALLTHRU, create);
}
}
}
static void
libjit/jit/jit-block.c view on Meta::CPAN
#ifdef _JIT_BLOCK_DEBUG
label_loop_check(func, dst, label);
#endif
while(label != jit_label_undefined)
{
info = &func->builder->label_info[label];
alias = info->alias;
if((info->flags & JIT_LABEL_ADDRESS_OF) == 0)
{
info->block = dst;
info->alias = dst->label;
dst->label = label;
}
else
{
info->alias = src->label;
src->label = label;
}
libjit/jit/jit-block.c view on Meta::CPAN
succ_block = succ_edge->dst;
/* Retarget labels bound to this block to the successor block. */
merge_labels(func, block, succ_block);
/* Retarget all incoming edges except a fallthrough edge */
fallthru_edge = 0;
for(index = 0; index < block->num_preds; index++)
{
pred_edge = block->preds[index];
if(pred_edge->flags == _JIT_EDGE_FALLTHRU)
{
fallthru_edge = pred_edge;
}
else
{
*changed = 1;
attach_edge_dst(pred_edge, succ_block);
}
}
/* Unless the block is taken address of, the incoming fallthrough edge
can be retargeted and then the block deleted if the outgoing edge is
also fallthrough. */
if(!block->address_of && fallthru_edge && succ_edge->flags == _JIT_EDGE_FALLTHRU)
{
*changed = 1;
attach_edge_dst(fallthru_edge, succ_block);
fallthru_edge = 0;
}
/* Free the block if there is no incoming edge left and it is not taken
address of. Otherwise adjust the preds array accordingly. */
if(fallthru_edge)
{
libjit/jit/jit-block.c view on Meta::CPAN
combine_block(jit_function_t func, jit_block_t block, int *changed)
{
jit_block_t succ_block;
int branch, num_insns, max_insns;
jit_insn_t insns;
/* Find block successor */
succ_block = block->succs[0]->dst;
/* Does block end with a (redundant) branch instruction? */
branch = (block->succs[0]->flags == _JIT_EDGE_BRANCH);
/* If the branch is there then preallocate memory for it,
doing it here simplifies handling of the out-of-memory
condition */
if(branch && !succ_block->max_insns)
{
succ_block->insns = jit_malloc(sizeof(struct _jit_insn));
if(!succ_block->insns)
{
jit_exception_builtin(JIT_RESULT_OUT_OF_MEMORY);
libjit/jit/jit-block.c view on Meta::CPAN
int index;
jit_insn_t insn;
jit_label_t branch_label;
jit_label_t *jump_labels;
int jump_index, num_labels;
branch_label = jit_label_undefined;
for(index = 0; index < block->num_preds; index++)
{
if(block->preds[index]->flags != _JIT_EDGE_BRANCH)
{
continue;
}
if(branch_label == jit_label_undefined)
{
branch_label = (func->builder->next_label)++;
if(!_jit_block_record_label(block, branch_label))
{
jit_exception_builtin(JIT_RESULT_OUT_OF_MEMORY);
libjit/jit/jit-block.c view on Meta::CPAN
static void
set_address_of(jit_function_t func)
{
int index, count;
jit_block_t block;
count = func->builder->max_label_info;
for(index = 0; index < count; index++)
{
block = func->builder->label_info[index].block;
if(block && (func->builder->label_info[index].flags & JIT_LABEL_ADDRESS_OF) != 0)
{
block->address_of = 1;
split_address_of(func, block, index);
}
}
}
/* Delete block along with references to it */
static void
eliminate_block(jit_block_t block)
libjit/jit/jit-block.c view on Meta::CPAN
{
block = func->builder->block_order[index];
if(block->num_succs == 0)
{
continue;
}
/* Take care of redundant branches that is, if possible, either
replace a branch with NOP turning it to a fallthrough case
or reduce a conditional branch to unconditional */
if(block->succs[0]->flags == _JIT_EDGE_BRANCH)
{
insn = _jit_block_get_last(block);
if(insn->opcode == JIT_OP_JUMP_TABLE)
{
/* skip jump tables, handle only branches */
continue;
}
if(block->succs[0]->dst == block->next)
{
/* Replace useless branch with NOP */
libjit/jit/jit-block.c view on Meta::CPAN
delete_edge(func, block->succs[0]);
}
else
{
/* For unconditional branch replace the branch
edge with a fallthrough edge */
#ifdef _JIT_BLOCK_DEBUG
printf("%d ubranch->fallthru %d\n", index, block->label);
#endif
block->ends_in_dead = 0;
block->succs[0]->flags = _JIT_EDGE_FALLTHRU;
}
}
else if(block->num_succs == 2
&& block->next->num_succs == 1
&& block->next->succs[0]->flags == _JIT_EDGE_BRANCH
&& block->succs[0]->dst == block->next->succs[0]->dst
&& is_empty_block(block->next))
{
/* For conditional branch followed by unconditional
that has the same target make the first branch
unconditional too, remove the fallthrough edge while
leaving the branch edge intact */
#ifdef _JIT_BLOCK_DEBUG
printf("%d cbranch->ubranch %d\n", index, block->label);
#endif
changed = 1;
insn->opcode = JIT_OP_BR;
block->ends_in_dead = 1;
delete_edge(func, block->succs[1]);
}
}
/* Try to simplify basic blocks that end with fallthrough or
unconditional branch */
if(block->num_succs == 1
&& (block->succs[0]->flags == _JIT_EDGE_BRANCH
|| block->succs[0]->flags == _JIT_EDGE_FALLTHRU))
{
if(is_empty_block(block))
{
/* Remove empty block */
#ifdef _JIT_BLOCK_DEBUG
printf("%d merge_empty %d\n", index, block->label);
#endif
merge_empty(func, block, &changed);
}
else if(block->succs[0]->dst->num_preds == 1
libjit/jit/jit-block.c view on Meta::CPAN
/* Record label info to the table */
builder->label_info[label].block = block;
builder->label_info[label].alias = block->label;
block->label = label;
return 1;
}
int
_jit_block_record_label_flags(jit_function_t func, jit_label_t label, int flags)
{
if(!ensure_label_table(func, label))
{
return 0;
}
func->builder->label_info[label].flags = flags;
return 1;
}
jit_insn_t
_jit_block_add_insn(jit_block_t block)
{
int max_insns;
jit_insn_t insns;
/* Make space for the instruction in the block's instruction list */
libjit/jit/jit-cfg.c view on Meta::CPAN
#include "jit-cfg.h"
static void
init_node(_jit_node_t node, jit_block_t block)
{
node->block = block;
if(block)
{
jit_block_set_meta(block, _JIT_BLOCK_CFG_NODE, node, 0);
}
node->flags = 0;
node->succs = 0;
node->num_succs = 0;
node->preds = 0;
node->num_preds = 0;
_jit_bitset_init(&node->live_in);
_jit_bitset_init(&node->live_out);
_jit_bitset_init(&node->live_use);
_jit_bitset_init(&node->live_def);
node->dfn = -1;
}
static void
init_edge(_jit_edge_t edge)
{
edge->src = 0;
edge->dst = 0;
edge->flags = 0;
}
static void
init_value_entry(_jit_value_entry_t value)
{
value->value = 0;
}
static _jit_node_t
create_node()
libjit/jit/jit-cfg.c view on Meta::CPAN
jit_label_t label;
label = cfg->func->builder->catcher_label;
if(label == jit_label_undefined)
{
return cfg->exit;
}
return get_label_node(cfg, label);
}
static void
enum_edge(_jit_cfg_t cfg, _jit_node_t src, _jit_node_t dst, int flags, int create)
{
if(!cfg || !src || !dst)
{
return;
}
if(create)
{
cfg->edges[cfg->num_edges].src = src;
cfg->edges[cfg->num_edges].dst = dst;
cfg->edges[cfg->num_edges].flags = flags;
src->succs[src->num_succs] = &cfg->edges[cfg->num_edges];
dst->preds[dst->num_preds] = &cfg->edges[cfg->num_edges];
}
++(cfg->num_edges);
++(src->num_succs);
++(dst->num_preds);
}
static void
libjit/jit/jit-cfg.c view on Meta::CPAN
stack[0].node = cfg->entry;
stack[0].index = 0;
sp = 1;
while(sp)
{
node = stack[sp - 1].node;
index = stack[sp - 1].index;
succ = node->succs[index]->dst;
if(succ != cfg->exit && (succ->flags & _JIT_NODE_VISITED) == 0)
{
succ->flags |= _JIT_NODE_VISITED;
if(succ->num_succs > 0)
{
stack[sp].node = succ;
stack[sp].index = 0;
++sp;
}
else
{
cfg->post_order[post_order_num++] = succ;
}
libjit/jit/jit-cfg.c view on Meta::CPAN
}
jit_free(stack);
return 1;
}
static jit_value_t
get_dest(jit_insn_t insn)
{
if(insn->opcode == JIT_OP_NOP
|| (insn->flags & JIT_INSN_DEST_OTHER_FLAGS) != 0
|| (insn->dest && insn->dest->is_constant))
{
return 0;
}
return insn->dest;
}
static jit_value_t
get_value1(jit_insn_t insn)
{
if(insn->opcode == JIT_OP_NOP
|| (insn->flags & JIT_INSN_VALUE1_OTHER_FLAGS) != 0
|| (insn->value1 && insn->value1->is_constant))
{
return 0;
}
return insn->value1;
}
static jit_value_t
get_value2(jit_insn_t insn)
{
if(insn->opcode == JIT_OP_NOP
|| (insn->flags & JIT_INSN_VALUE2_OTHER_FLAGS) != 0
|| (insn->value2 && insn->value2->is_constant))
{
return 0;
}
return insn->value2;
}
static int
create_value_entry(_jit_cfg_t cfg, jit_value_t value)
{
libjit/jit/jit-cfg.c view on Meta::CPAN
if(value1 && !use_value(cfg, node, value1))
{
return 0;
}
if(value2 && !use_value(cfg, node, value2))
{
return 0;
}
if(dest)
{
if((insn->flags & JIT_INSN_DEST_IS_VALUE) != 0)
{
if(!use_value(cfg, node, dest))
{
return 0;
}
}
else
{
if(!def_value(cfg, node, dest))
{
libjit/jit/jit-cfg.h view on Meta::CPAN
int num_values;
int max_values;
};
/*
* Control flow graph node.
*/
struct _jit_node
{
jit_block_t block;
int flags;
/* edges to successor nodes */
_jit_edge_t *succs;
int num_succs;
/* edges to predecessor nodes */
_jit_edge_t *preds;
int num_preds;
/* liveness analysis data */
libjit/jit/jit-cfg.h view on Meta::CPAN
int dfn;
};
/*
* Control flow graph edge.
*/
struct _jit_edge
{
_jit_node_t src;
_jit_node_t dst;
int flags;
};
/*
* Value entry that contains information for data flow analysis
* and register allocation.
*/
struct _jit_value_entry
{
jit_value_t value;
short reg;
libjit/jit/jit-compile.c view on Meta::CPAN
{
/* Clear the block addresses and fixup lists */
block->address = 0;
block->fixup_list = 0;
block->fixup_absolute_list = 0;
/* Reset values referred to by block instructions */
jit_insn_iter_init(&iter, block);
while((insn = jit_insn_iter_next(&iter)) != 0)
{
if(insn->dest && (insn->flags & JIT_INSN_DEST_OTHER_FLAGS) == 0)
{
reset_value(insn->dest);
}
if(insn->value1 && (insn->flags & JIT_INSN_VALUE1_OTHER_FLAGS) == 0)
{
reset_value(insn->value1);
}
if(insn->value2 && (insn->flags & JIT_INSN_VALUE2_OTHER_FLAGS) == 0)
{
reset_value(insn->value2);
}
}
}
/* Reset values referred to by builder */
if(func->builder->setjmp_value)
{
reset_value(func->builder->setjmp_value);
libjit/jit/jit-compile.c view on Meta::CPAN
/* Start with with allocated space */
memory_start(state);
}
/*
* Prepare function info needed for code generation.
*/
static void
codegen_prepare(_jit_compile_t *state)
{
/* Intuit "nothrow" and "noreturn" flags for this function */
if(!state->func->builder->may_throw)
{
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 */
libjit/jit/jit-debugger.c view on Meta::CPAN
return 1;
}
else
{
unlock_debugger(dbg);
return 0;
}
}
/*@
* @deftypefun void jit_debugger_set_breakable (jit_debugger_t @var{dbg}, const void *@var{native_thread}, int @var{flag})
* Set a flag that indicates if a native thread can stop at breakpoints.
* If set to 1 (the default), breakpoints will be active on the thread.
* If set to 0, breakpoints will be ignored on the thread. Typically
* this is used to mark threads associated with the debugger's user
* interface, or the virtual machine's finalization thread, so that they
* aren't accidentally suspended by the debugger (which might cause a
* deadlock).
* @end deftypefun
@*/
void jit_debugger_set_breakable
(jit_debugger_t dbg, const void *native_thread, int flag)
{
jit_debugger_thread_t th;
jit_debugger_thread_id_t id;
id = jit_debugger_get_thread(dbg, native_thread);
lock_debugger(dbg);
th = get_specific_thread(dbg, id);
if(th)
{
th->breakable = flag;
}
unlock_debugger(dbg);
}
/*@
* @deftypefun void jit_debugger_attach_self (jit_debugger_t @var{dbg}, int @var{stop_immediately})
* Attach the current thread to a debugger. If @var{stop_immediately}
* is non-zero, then the current thread immediately suspends, waiting for
* the user to start it with @code{jit_debugger_run}. This function is
* typically called in a thread's startup code just before any "real work"
libjit/jit/jit-debugger.c view on Meta::CPAN
return 1;
}
/*@
* @deftypefun jit_debugger_breakpoint_id_t jit_debugger_add_breakpoint (jit_debugger_t @var{dbg}, jit_debugger_breakpoint_info_t @var{info})
* Add a hard breakpoint to a debugger instance. The @var{info} structure
* defines the conditions under which the breakpoint should fire.
* The fields of @var{info} are as follows:
*
* @table @code
* @item flags
* Flags that indicate which of the following fields should be matched.
* If a flag is not present, then all possible values of the field will match.
* Valid flags are @code{JIT_DEBUGGER_FLAG_THREAD},
* @code{JIT_DEBUGGER_FLAG_FUNCTION}, @code{JIT_DEBUGGER_FLAG_DATA1},
* and @code{JIT_DEBUGGER_FLAG_DATA2}.
*
* @item thread
* The thread to match against, if @code{JIT_DEBUGGER_FLAG_THREAD} is set.
*
* @item function
* The function to match against, if @code{JIT_DEBUGGER_FLAG_FUNCTION} is set.
*
* @item data1
libjit/jit/jit-debugger.c view on Meta::CPAN
/*@
* @deftypefun int jit_debugger_is_running (jit_debugger_t @var{dbg}, jit_debugger_thread_id_t @var{thread})
* Determine if a particular thread is currently running (non-zero) or
* stopped (zero).
* @end deftypefun
@*/
int jit_debugger_is_running(jit_debugger_t dbg, jit_debugger_thread_id_t thread)
{
jit_debugger_thread_t th;
int flag = 0;
lock_debugger(dbg);
th = get_specific_thread(dbg, thread);
if(th)
{
flag = (th->run_type != JIT_RUN_TYPE_STOPPED);
}
unlock_debugger(dbg);
return flag;
}
/*@
* @deftypefun void jit_debugger_run (jit_debugger_t @var{dbg}, jit_debugger_thread_id_t @var{thread})
* Start the specified thread running, or continue from the last breakpoint.
*
* This function, and the others that follow, sends a request to the specified
* thread and then returns to the caller immediately.
* @end deftypefun
@*/
libjit/jit/jit-dump.c view on Meta::CPAN
/*@
* @deftypefun void jit_dump_insn (FILE *@var{stream}, jit_function_t @var{func}, jit_value_t @var{value})
* Dump the contents of an instruction to a stdio stream.
* @end deftypefun
@*/
void jit_dump_insn(FILE *stream, jit_function_t func, jit_insn_t insn)
{
const char *name;
const char *infix_name;
int opcode, flags;
jit_nint reg;
/* Bail out if we have insufficient information for the dump */
if(!stream || !func || !insn)
{
return;
}
/* Get the opcode details */
opcode = insn->opcode;
if(opcode < JIT_OP_NOP || opcode >= JIT_OP_NUM_OPCODES)
{
fprintf(stream, "unknown opcode %d\n", opcode);
return;
}
name = jit_opcodes[opcode].name;
flags = jit_opcodes[opcode].flags;
infix_name = 0;
/* Dump branch, call, or register information */
if((flags & JIT_OPCODE_IS_BRANCH) != 0)
{
if(opcode == JIT_OP_BR)
{
fprintf(stream, "goto .L%ld", (long)(jit_insn_get_label(insn)));
return;
}
if(opcode == JIT_OP_CALL_FINALLY || opcode == JIT_OP_CALL_FILTER)
{
fprintf(stream, "%s .L%ld", name, (long)(jit_insn_get_label(insn)));
return;
}
fprintf(stream, "if ");
}
else if((flags & JIT_OPCODE_IS_CALL) != 0)
{
if(insn->value1)
fprintf(stream, "%s %s", name, (const char *)(insn->value1));
else
fprintf(stream, "%s 0x08%lx", name, (long)(jit_nuint)(insn->dest));
return;
}
else if((flags & JIT_OPCODE_IS_CALL_EXTERNAL) != 0)
{
if(insn->value1)
fprintf(stream, "%s %s (0x%08lx)", name,
(const char *)(insn->value1),
(long)(jit_nuint)(insn->dest));
else
fprintf(stream, "%s 0x08%lx", name,
(long)(jit_nuint)(insn->dest));
return;
}
else if((flags & JIT_OPCODE_IS_REG) != 0)
{
reg = jit_value_get_nint_constant(jit_insn_get_value2(insn));
fputs(name, stream);
putc('(', stream);
jit_dump_value(stream, func, jit_insn_get_value1(insn), 0);
fputs(", ", stream);
fputs(jit_reg_name(reg), stream);
putc(')', stream);
return;
}
else if((flags & JIT_OPCODE_IS_ADDROF_LABEL) != 0)
{
dump_value(stream, func, jit_insn_get_dest(insn), flags & JIT_OPCODE_DEST_MASK);
fprintf(stream, " = ");
fprintf(stream, "address_of_label .L%ld",
(long)(jit_insn_get_label(insn)));
return;
}
else if((flags & JIT_OPCODE_IS_JUMP_TABLE) != 0)
{
jit_label_t *labels;
jit_nint num_labels, label;
labels = (jit_label_t *)jit_value_get_nint_constant(jit_insn_get_value1(insn));
num_labels = jit_value_get_nint_constant(jit_insn_get_value2(insn));
fprintf(stream, "%s ", name);
dump_value(stream, func, jit_insn_get_dest(insn), flags & JIT_OPCODE_DEST_MASK);
printf(" : {");
for(label = 0; label < num_labels; label++)
{
printf(" .L%ld", (long) labels[label]);
}
printf(" }");
return;
}
/* Output the destination information */
if((flags & JIT_OPCODE_DEST_MASK) != JIT_OPCODE_DEST_EMPTY &&
!jit_insn_dest_is_value(insn))
{
dump_value(stream, func, jit_insn_get_dest(insn),
flags & JIT_OPCODE_DEST_MASK);
fprintf(stream, " = ");
}
/* Dump the details of the operation */
switch(flags & JIT_OPCODE_OPER_MASK)
{
case JIT_OPCODE_OPER_ADD: infix_name = " + "; break;
case JIT_OPCODE_OPER_SUB: infix_name = " - "; break;
case JIT_OPCODE_OPER_MUL: infix_name = " * "; break;
case JIT_OPCODE_OPER_DIV: infix_name = " / "; break;
case JIT_OPCODE_OPER_REM: infix_name = " % "; break;
case JIT_OPCODE_OPER_NEG: infix_name = "-"; break;
case JIT_OPCODE_OPER_AND: infix_name = " & "; break;
case JIT_OPCODE_OPER_OR: infix_name = " | "; break;
case JIT_OPCODE_OPER_XOR: infix_name = " ^ "; break;
libjit/jit/jit-dump.c view on Meta::CPAN
case JIT_OPCODE_OPER_GT: infix_name = " > "; break;
case JIT_OPCODE_OPER_GE: infix_name = " >= "; break;
case JIT_OPCODE_OPER_SHL: infix_name = " << "; break;
case JIT_OPCODE_OPER_SHR: infix_name = " >> "; break;
case JIT_OPCODE_OPER_SHR_UN: infix_name = " >>> "; break;
case JIT_OPCODE_OPER_COPY: infix_name = ""; break;
case JIT_OPCODE_OPER_ADDRESS_OF: infix_name = "&"; break;
}
if(infix_name)
{
if((flags & JIT_OPCODE_SRC2_MASK) != 0)
{
/* Binary operation with a special operator name */
dump_value(stream, func, jit_insn_get_value1(insn),
flags & JIT_OPCODE_SRC1_MASK);
fputs(infix_name, stream);
dump_value(stream, func, jit_insn_get_value2(insn),
flags & JIT_OPCODE_SRC2_MASK);
}
else
{
/* Unary operation with a special operator name */
fputs(infix_name, stream);
dump_value(stream, func, jit_insn_get_value1(insn),
flags & JIT_OPCODE_SRC1_MASK);
}
}
else
{
/* Not a special operator, so use the opcode name */
if(!jit_strncmp(name, "br_", 3))
{
name += 3;
}
fputs(name, stream);
if((flags & (JIT_OPCODE_SRC1_MASK | JIT_OPCODE_SRC2_MASK)) != 0)
{
putc('(', stream);
if(jit_insn_dest_is_value(insn))
{
dump_value(stream, func, jit_insn_get_dest(insn),
flags & JIT_OPCODE_DEST_MASK);
fputs(", ", stream);
}
dump_value(stream, func, jit_insn_get_value1(insn),
flags & JIT_OPCODE_SRC1_MASK);
if((flags & JIT_OPCODE_SRC2_MASK) != 0)
{
fputs(", ", stream);
dump_value(stream, func, jit_insn_get_value2(insn),
flags & JIT_OPCODE_SRC2_MASK);
}
putc(')', stream);
}
}
/* Dump the "then" information on a conditional branch */
if((flags & JIT_OPCODE_IS_BRANCH) != 0)
{
fprintf(stream, " then goto .L%ld", (long)(jit_insn_get_label(insn)));
}
}
#if defined(JIT_BACKEND_INTERP)
/*
* Dump the interpreted bytecode representation of a function.
*/
libjit/jit/jit-dump.c view on Meta::CPAN
}
else
{
info = &(_jit_interp_opcodes[opcode - JIT_OP_NUM_OPCODES]);
}
/* Dump the name of the opcode */
fputs(info->name, stream);
/* Dump additional parameters from the opcode stream */
switch(info->flags & JIT_OPCODE_INTERP_ARGS_MASK)
{
case JIT_OPCODE_NINT_ARG:
{
fprintf(stream, " %ld", (long)(jit_nint)(*pc));
++pc;
}
break;
case JIT_OPCODE_NINT_ARG_TWO:
{
libjit/jit/jit-dump.c view on Meta::CPAN
case JIT_OPCODE_CALL_INDIRECT_ARGS:
{
fprintf(stream, " %ld", (long)(jit_nint)(pc[1]));
pc += 2;
}
break;
default:
{
if((info->flags & (JIT_OPCODE_IS_BRANCH |
JIT_OPCODE_IS_ADDROF_LABEL)) != 0)
{
fprintf(stream, " %08lX",
(long)(jit_nint)((pc - 1) + (jit_nint)(*pc)));
++pc;
}
else if((info->flags & JIT_OPCODE_IS_CALL) != 0)
{
fprintf(stream, " 0x%lX", (long)(jit_nint)(*pc));
++pc;
}
else if((info->flags & JIT_OPCODE_IS_CALL_EXTERNAL) != 0)
{
fprintf(stream, " 0x%lX, %ld",
(long)(jit_nint)(pc[1]), (long)(jit_nint)(pc[2]));
pc += 3;
}
else if((info->flags & JIT_OPCODE_IS_JUMP_TABLE) != 0)
{
jit_nint label, num_labels;
num_labels = (jit_nint)pc[0];
for(label = 1; label <= num_labels; label++)
{
fprintf(stream, " %lX",
(long)(jit_nint)pc[label]);
}
pc += 1 + num_labels;
}
libjit/jit/jit-dump.c view on Meta::CPAN
*/
static void dump_object_code(FILE *stream, void *start, void *end)
{
char cmdline[BUFSIZ];
unsigned char *pc = (unsigned char *)start;
FILE *file;
int ch;
#if JIT_WIN32_PLATFORM
/*
* NOTE: If libjit is compiled on cygwin with -mno-cygwin flag then
* fopen("/tmp/foo.s", ...) will use the root folder of the current
* drive. That is the full file name will be like "c:/tmp/foo". But
* the ``as'' and ``objdump'' utilities still use the cygwin's root.
* So "as /tmp/foo.s" will look for "c:/cygwin/tmp/foo.s". To avoid
* this ambiguity the file name has to contian the drive spec (e.g.
* fopen("c:/tmp/foo.s", ...) and "as c;/tmp/foo.s"). Here we assume
* that the TMP or TEMP environment variables always contain it.
*/
char s_path[BUFSIZ];
char o_path[BUFSIZ];
libjit/jit/jit-elf-defs.h view on Meta::CPAN
typedef struct
{
unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
Elf32_Half e_type; /* Object file type */
Elf32_Half e_machine; /* Architecture */
Elf32_Word e_version; /* Object file version */
Elf32_Addr e_entry; /* Entry point virtual address */
Elf32_Off e_phoff; /* Program header table file offset */
Elf32_Off e_shoff; /* Section header table file offset */
Elf32_Word e_flags; /* Processor-specific flags */
Elf32_Half e_ehsize; /* ELF header size in bytes */
Elf32_Half e_phentsize; /* Program header table entry size */
Elf32_Half e_phnum; /* Program header table entry count */
Elf32_Half e_shentsize; /* Section header table entry size */
Elf32_Half e_shnum; /* Section header table entry count */
Elf32_Half e_shstrndx; /* Section header string table index */
} Elf32_Ehdr;
typedef struct
{
unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
Elf64_Half e_type; /* Object file type */
Elf64_Half e_machine; /* Architecture */
Elf64_Word e_version; /* Object file version */
Elf64_Addr e_entry; /* Entry point virtual address */
Elf64_Off e_phoff; /* Program header table file offset */
Elf64_Off e_shoff; /* Section header table file offset */
Elf64_Word e_flags; /* Processor-specific flags */
Elf64_Half e_ehsize; /* ELF header size in bytes */
Elf64_Half e_phentsize; /* Program header table entry size */
Elf64_Half e_phnum; /* Program header table entry count */
Elf64_Half e_shentsize; /* Section header table entry size */
Elf64_Half e_shnum; /* Section header table entry count */
Elf64_Half e_shstrndx; /* Section header string table index */
} Elf64_Ehdr;
/* Fields in the e_ident array. The EI_* macros are indices into the
array. The macros under each EI_* macro are the values the byte
libjit/jit/jit-elf-defs.h view on Meta::CPAN
#define EV_NONE 0 /* Invalid ELF version */
#define EV_CURRENT 1 /* Current version */
#define EV_NUM 2
/* Section header. */
typedef struct
{
Elf32_Word sh_name; /* Section name (string tbl index) */
Elf32_Word sh_type; /* Section type */
Elf32_Word sh_flags; /* Section flags */
Elf32_Addr sh_addr; /* Section virtual addr at execution */
Elf32_Off sh_offset; /* Section file offset */
Elf32_Word sh_size; /* Section size in bytes */
Elf32_Word sh_link; /* Link to another section */
Elf32_Word sh_info; /* Additional section information */
Elf32_Word sh_addralign; /* Section alignment */
Elf32_Word sh_entsize; /* Entry size if section holds table */
} Elf32_Shdr;
typedef struct
{
Elf64_Word sh_name; /* Section name (string tbl index) */
Elf64_Word sh_type; /* Section type */
Elf64_Xword sh_flags; /* Section flags */
Elf64_Addr sh_addr; /* Section virtual addr at execution */
Elf64_Off sh_offset; /* Section file offset */
Elf64_Xword sh_size; /* Section size in bytes */
Elf64_Word sh_link; /* Link to another section */
Elf64_Word sh_info; /* Additional section information */
Elf64_Xword sh_addralign; /* Section alignment */
Elf64_Xword sh_entsize; /* Entry size if section holds table */
} Elf64_Shdr;
/* Special section indices. */
libjit/jit/jit-elf-defs.h view on Meta::CPAN
#define SHT_GNU_verdef 0x6ffffffd /* Version definition section. */
#define SHT_GNU_verneed 0x6ffffffe /* Version needs section. */
#define SHT_GNU_versym 0x6fffffff /* Version symbol table. */
#define SHT_HISUNW 0x6fffffff /* Sun-specific high bound. */
#define SHT_HIOS 0x6fffffff /* End OS-specific type */
#define SHT_LOPROC 0x70000000 /* Start of processor-specific */
#define SHT_HIPROC 0x7fffffff /* End of processor-specific */
#define SHT_LOUSER 0x80000000 /* Start of application-specific */
#define SHT_HIUSER 0x8fffffff /* End of application-specific */
/* Legal values for sh_flags (section flags). */
#define SHF_WRITE (1 << 0) /* Writable */
#define SHF_ALLOC (1 << 1) /* Occupies memory during execution */
#define SHF_EXECINSTR (1 << 2) /* Executable */
#define SHF_MERGE (1 << 4) /* Might be merged */
#define SHF_STRINGS (1 << 5) /* Contains nul-terminated strings */
#define SHF_INFO_LINK (1 << 6) /* `sh_info' contains SHT index */
#define SHF_LINK_ORDER (1 << 7) /* Preserve order after combining */
#define SHF_OS_NONCONFORMING (1 << 8) /* Non-standard OS specific handling
required */
libjit/jit/jit-elf-defs.h view on Meta::CPAN
Elf64_Addr st_value; /* Symbol value */
Elf64_Xword st_size; /* Symbol size */
} Elf64_Sym;
/* The syminfo section if available contains additional information about
every dynamic symbol. */
typedef struct
{
Elf32_Half si_boundto; /* Direct bindings, symbol bound to */
Elf32_Half si_flags; /* Per symbol flags */
} 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
#define SYMINFO_CURRENT 1
#define SYMINFO_NUM 2
libjit/jit/jit-elf-defs.h view on Meta::CPAN
/* Program segment header. */
typedef struct
{
Elf32_Word p_type; /* Segment type */
Elf32_Off p_offset; /* Segment file offset */
Elf32_Addr p_vaddr; /* Segment virtual address */
Elf32_Addr p_paddr; /* Segment physical address */
Elf32_Word p_filesz; /* Segment size in file */
Elf32_Word p_memsz; /* Segment size in memory */
Elf32_Word p_flags; /* Segment flags */
Elf32_Word p_align; /* Segment alignment */
} Elf32_Phdr;
typedef struct
{
Elf64_Word p_type; /* Segment type */
Elf64_Word p_flags; /* Segment flags */
Elf64_Off p_offset; /* Segment file offset */
Elf64_Addr p_vaddr; /* Segment virtual address */
Elf64_Addr p_paddr; /* Segment physical address */
Elf64_Xword p_filesz; /* Segment size in file */
Elf64_Xword p_memsz; /* Segment size in memory */
Elf64_Xword p_align; /* Segment alignment */
} Elf64_Phdr;
/* Legal values for p_type (segment type). */
libjit/jit/jit-elf-defs.h view on Meta::CPAN
#define PT_SHLIB 5 /* Reserved */
#define PT_PHDR 6 /* Entry for header table itself */
#define PT_TLS 7 /* Thread-local storage segment */
#define PT_NUM 8 /* Number of defined types */
#define PT_LOOS 0x60000000 /* Start of OS-specific */
#define PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */
#define PT_HIOS 0x6fffffff /* End of OS-specific */
#define PT_LOPROC 0x70000000 /* Start of processor-specific */
#define PT_HIPROC 0x7fffffff /* End of processor-specific */
/* Legal values for p_flags (segment flags). */
#define PF_X (1 << 0) /* Segment is executable */
#define PF_W (1 << 1) /* Segment is writable */
#define PF_R (1 << 2) /* Segment is readable */
#define PF_MASKOS 0x0ff00000 /* OS-specific */
#define PF_MASKPROC 0xf0000000 /* Processor-specific */
/* Legal values for note segment descriptor types for core files. */
#define NT_PRSTATUS 1 /* Contains copy of prstatus struct */
libjit/jit/jit-elf-defs.h view on Meta::CPAN
#define DT_ADDRRNGHI 0x6ffffeff
/* The versioning entry types. The next are defined as part of the
GNU extension. */
#define DT_VERSYM 0x6ffffff0
#define DT_RELACOUNT 0x6ffffff9
#define DT_RELCOUNT 0x6ffffffa
/* These were chosen by Sun. */
#define DT_FLAGS_1 0x6ffffffb /* State flags, see DF_1_* below. */
#define DT_VERDEF 0x6ffffffc /* Address of version definition
table */
#define DT_VERDEFNUM 0x6ffffffd /* Number of version definitions */
#define DT_VERNEED 0x6ffffffe /* Address of table with needed
versions */
#define DT_VERNEEDNUM 0x6fffffff /* Number of needed versions */
#define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */
#define DT_VERSIONTAGNUM 16
/* Sun added these machine-independent extensions in the "processor-specific"
libjit/jit/jit-elf-defs.h view on Meta::CPAN
#define DT_FILTER 0x7fffffff /* Shared object to get values from */
#define DT_EXTRATAGIDX(tag) ((Elf32_Word)-((Elf32_Sword) (tag) <<1>>1)-1)
#define DT_EXTRANUM 3
/* Values of `d_un.d_val' in the DT_FLAGS entry. */
#define DF_ORIGIN 0x00000001 /* Object may use DF_ORIGIN */
#define DF_SYMBOLIC 0x00000002 /* Symbol resolutions starts here */
#define DF_TEXTREL 0x00000004 /* Object contains text relocations */
#define DF_BIND_NOW 0x00000008 /* No lazy binding for this object */
/* State flags selectable in the `d_un.d_val' element of the DT_FLAGS_1
entry in the dynamic section. */
#define DF_1_NOW 0x00000001 /* Set RTLD_NOW for this object. */
#define DF_1_GLOBAL 0x00000002 /* Set RTLD_GLOBAL for this object. */
#define DF_1_GROUP 0x00000004 /* Set RTLD_GROUP for this object. */
#define DF_1_NODELETE 0x00000008 /* Set RTLD_NODELETE for this object.*/
#define DF_1_LOADFLTR 0x00000010 /* Trigger filtee loading at runtime.*/
#define DF_1_INITFIRST 0x00000020 /* Set RTLD_INITFIRST for this object*/
#define DF_1_NOOPEN 0x00000040 /* Set RTLD_NOOPEN for this object. */
#define DF_1_ORIGIN 0x00000080 /* $ORIGIN must be handled. */
#define DF_1_DIRECT 0x00000100 /* Direct binding enabled. */
libjit/jit/jit-elf-defs.h view on Meta::CPAN
/* Flags in the DT_POSFLAG_1 entry effecting only the next DT_* entry. */
#define DF_P1_LAZYLOAD 0x00000001 /* Lazyload following object. */
#define DF_P1_GROUPPERM 0x00000002 /* Symbols from next object are not
generally available. */
/* Version definition sections. */
typedef struct
{
Elf32_Half vd_version; /* Version revision */
Elf32_Half vd_flags; /* Version information */
Elf32_Half vd_ndx; /* Version Index */
Elf32_Half vd_cnt; /* Number of associated aux entries */
Elf32_Word vd_hash; /* Version name hash value */
Elf32_Word vd_aux; /* Offset in bytes to verdaux array */
Elf32_Word vd_next; /* Offset in bytes to next verdef
entry */
} Elf32_Verdef;
typedef struct
{
Elf64_Half vd_version; /* Version revision */
Elf64_Half vd_flags; /* Version information */
Elf64_Half vd_ndx; /* Version Index */
Elf64_Half vd_cnt; /* Number of associated aux entries */
Elf64_Word vd_hash; /* Version name hash value */
Elf64_Word vd_aux; /* Offset in bytes to verdaux array */
Elf64_Word vd_next; /* Offset in bytes to next verdef
entry */
} Elf64_Verdef;
/* Legal values for vd_version (version revision). */
#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. */
libjit/jit/jit-elf-defs.h view on Meta::CPAN
/* Legal values for vn_version (version revision). */
#define VER_NEED_NONE 0 /* No version */
#define VER_NEED_CURRENT 1 /* Current version */
#define VER_NEED_NUM 2 /* Given version number */
/* Auxiliary needed version information. */
typedef struct
{
Elf32_Word vna_hash; /* Hash value of dependency name */
Elf32_Half vna_flags; /* Dependency specific information */
Elf32_Half vna_other; /* Unused */
Elf32_Word vna_name; /* Dependency name string offset */
Elf32_Word vna_next; /* Offset in bytes to next vernaux
entry */
} Elf32_Vernaux;
typedef struct
{
Elf64_Word vna_hash; /* Hash value of dependency name */
Elf64_Half vna_flags; /* Dependency specific information */
Elf64_Half vna_other; /* Unused */
Elf64_Word vna_name; /* Dependency name string offset */
Elf64_Word vna_next; /* Offset in bytes to next vernaux
entry */
} Elf64_Vernaux;
/* Legal values for vna_flags. */
#define VER_FLG_WEAK 0x2 /* Weak version identifier */
/* Auxiliary vector. */
/* This vector is normally only used by the program interpreter. The
usual definition in an ABI supplement uses the name auxv_t. The
vector is not usually defined in a standard <elf.h> file, but it
can't hurt. We rename it to avoid conflicts. The sizes of these
types are an arrangement between the exec server and the program
libjit/jit/jit-elf-defs.h view on Meta::CPAN
#define ELF32_M_SIZE(info) ((unsigned char) (info))
#define ELF32_M_INFO(sym, size) (((sym) << 8) + (unsigned char) (size))
#define ELF64_M_SYM(info) ELF32_M_SYM (info)
#define ELF64_M_SIZE(info) ELF32_M_SIZE (info)
#define ELF64_M_INFO(sym, size) ELF32_M_INFO (sym, size)
/* Motorola 68k specific definitions. */
/* Values for Elf32_Ehdr.e_flags. */
#define EF_CPU32 0x00810000
/* m68k relocs. */
#define R_68K_NONE 0 /* No reloc */
#define R_68K_32 1 /* Direct 32 bit */
#define R_68K_16 2 /* Direct 16 bit */
#define R_68K_8 3 /* Direct 8 bit */
#define R_68K_PC32 4 /* PC relative 32 bit */
#define R_68K_PC16 5 /* PC relative 16 bit */
libjit/jit/jit-elf-defs.h view on Meta::CPAN
#define R_386_GOTPC 10 /* 32 bit PC relative offset to GOT */
/* Keep this the last entry. */
#define R_386_NUM 11
/* SUN SPARC specific definitions. */
/* Legal values for ST_TYPE subfield of st_info (symbol type). */
#define STT_REGISTER 13 /* Global register reserved to app. */
/* Values for Elf64_Ehdr.e_flags. */
#define EF_SPARCV9_MM 3
#define EF_SPARCV9_TSO 0
#define EF_SPARCV9_PSO 1
#define EF_SPARCV9_RMO 2
#define EF_SPARC_LEDATA 0x800000 /* little endian data */
#define EF_SPARC_EXT_MASK 0xFFFF00
#define EF_SPARC_32PLUS 0x000100 /* generic V8+ features */
#define EF_SPARC_SUN_US1 0x000200 /* Sun UltraSPARC1 extensions */
#define EF_SPARC_HAL_R1 0x000400 /* HAL R1 extensions */
libjit/jit/jit-elf-defs.h view on Meta::CPAN
#define HWCAP_SPARC_FLUSH 1 /* The cpu supports flush insn. */
#define HWCAP_SPARC_STBAR 2
#define HWCAP_SPARC_SWAP 4
#define HWCAP_SPARC_MULDIV 8
#define HWCAP_SPARC_V9 16 /* The cpu is v9, so v8plus is ok. */
#define HWCAP_SPARC_ULTRA3 32
/* MIPS R3000 specific definitions. */
/* Legal values for e_flags field of Elf32_Ehdr. */
#define EF_MIPS_NOREORDER 1 /* A .noreorder directive was used */
#define EF_MIPS_PIC 2 /* Contains PIC code */
#define EF_MIPS_CPIC 4 /* Uses PIC calling sequence */
#define EF_MIPS_XGOT 8
#define EF_MIPS_64BIT_WHIRL 16
#define EF_MIPS_ABI2 32
#define EF_MIPS_ABI_ON32 64
#define EF_MIPS_ARCH 0xf0000000 /* MIPS architecture level */
libjit/jit/jit-elf-defs.h view on Meta::CPAN
#define SHT_MIPS_EVENTS 0x70000021 /* Event section. */
#define SHT_MIPS_TRANSLATE 0x70000022
#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
libjit/jit/jit-elf-defs.h view on Meta::CPAN
#define OHW_R5KCVTL 0x8 /* R5000 cvt.[ds].l bug. clean=1. */
#define OPAD_PREFIX 0x1
#define OPAD_POSTFIX 0x2
#define OPAD_SYMBOL 0x4
/* Entry found in `.options' section. */
typedef struct
{
Elf32_Word hwp_flags1; /* Extra flags. */
Elf32_Word hwp_flags2; /* Extra flags. */
} Elf_Options_Hw;
/* Masks for `info' in ElfOptions for ODK_HWAND and ODK_HWOR entries. */
#define OHWA0_R4KEOP_CHECKED 0x00000001
#define OHWA1_R4KEOP_CLEAN 0x00000002
/* MIPS relocs. */
#define R_MIPS_NONE 0 /* No reloc */
libjit/jit/jit-elf-defs.h view on Meta::CPAN
function stored in GOT. */
#define DT_MIPS_PERF_SUFFIX 0x7000002e /* Default suffix of dso to be added
by rld on dlopen() calls. */
#define DT_MIPS_COMPACT_SIZE 0x7000002f /* (O32)Size of compact rel section. */
#define DT_MIPS_GP_VALUE 0x70000030 /* GP value for aux GOTs. */
#define DT_MIPS_AUX_DYNAMIC 0x70000031 /* Address of aux .dynamic. */
#define DT_MIPS_NUM 0x32
/* Legal values for DT_MIPS_FLAGS Elf32_Dyn entry. */
#define RHF_NONE 0 /* No flags */
#define RHF_QUICKSTART (1 << 0) /* Use quickstart */
#define RHF_NOTPOT (1 << 1) /* Hash size not power of 2 */
#define RHF_NO_LIBRARY_REPLACEMENT (1 << 2) /* Ignore LD_LIBRARY_PATH */
#define RHF_NO_MOVE (1 << 3)
#define RHF_SGI_ONLY (1 << 4)
#define RHF_GUARANTEE_INIT (1 << 5)
#define RHF_DELTA_C_PLUS_PLUS (1 << 6)
#define RHF_GUARANTEE_START_INIT (1 << 7)
#define RHF_PIXIE (1 << 8)
#define RHF_DEFAULT_DELAY_LOAD (1 << 9)
libjit/jit/jit-elf-defs.h view on Meta::CPAN
#define RHF_RLD_ORDER_SAFE (1 << 14)
/* Entries found in sections of type SHT_MIPS_LIBLIST. */
typedef struct
{
Elf32_Word l_name; /* Name (string table index) */
Elf32_Word l_time_stamp; /* Timestamp */
Elf32_Word l_checksum; /* Checksum */
Elf32_Word l_version; /* Interface version */
Elf32_Word l_flags; /* Flags */
} Elf32_Lib;
typedef struct
{
Elf64_Word l_name; /* Name (string table index) */
Elf64_Word l_time_stamp; /* Timestamp */
Elf64_Word l_checksum; /* Checksum */
Elf64_Word l_version; /* Interface version */
Elf64_Word l_flags; /* Flags */
} Elf64_Lib;
/* Legal values for l_flags. */
#define LL_NONE 0
#define LL_EXACT_MATCH (1 << 0) /* Require exact match */
#define LL_IGNORE_INT_VER (1 << 1) /* Ignore interface version */
#define LL_REQUIRE_MINOR (1 << 2)
#define LL_EXPORTS (1 << 3)
#define LL_DELAY_LOAD (1 << 4)
#define LL_DELTA (1 << 5)
/* Entries found in sections of type SHT_MIPS_CONFLICT. */
typedef Elf32_Addr Elf32_Conflict;
/* HPPA specific definitions. */
/* Legal values for e_flags field of Elf32_Ehdr. */
#define EF_PARISC_TRAPNIL 0x00010000 /* Trap nil pointer dereference. */
#define EF_PARISC_EXT 0x00020000 /* Program uses arch. extensions. */
#define EF_PARISC_LSB 0x00040000 /* Program expects little endian. */
#define EF_PARISC_WIDE 0x00080000 /* Program expects wide mode. */
#define EF_PARISC_NO_KABP 0x00100000 /* No kernel assisted branch
prediction. */
#define EF_PARISC_LAZYSWAP 0x00400000 /* Allow lazy swapping. */
#define EF_PARISC_ARCH 0x0000ffff /* Architecture version. */
/* Defined values for `e_flags & EF_PARISC_ARCH' are: */
#define EFA_PARISC_1_0 0x020b /* PA-RISC 1.0 big-endian. */
#define EFA_PARISC_1_1 0x0210 /* PA-RISC 1.1 big-endian. */
#define EFA_PARISC_2_0 0x0214 /* PA-RISC 2.0 big-endian. */
/* Additional section indeces. */
#define SHN_PARISC_ANSI_COMMON 0xff00 /* Section for tenatively declared
symbols in ANSI C. */
#define SHN_PARISC_HUGE_COMMON 0xff01 /* Common blocks in huge model. */
/* Legal values for sh_type field of Elf32_Shdr. */
#define SHT_PARISC_EXT 0x70000000 /* Contains product specific ext. */
#define SHT_PARISC_UNWIND 0x70000001 /* Unwind information. */
#define SHT_PARISC_DOC 0x70000002 /* Debug info for optimized code. */
/* Legal values for sh_flags field of Elf32_Shdr. */
#define SHF_PARISC_SHORT 0x20000000 /* Section with short addressing. */
#define SHF_PARISC_HUGE 0x40000000 /* Section far from gp. */
#define SHF_PARISC_SBP 0x80000000 /* Static branch prediction code. */
/* Legal values for ST_TYPE subfield of st_info (symbol type). */
#define STT_PARISC_MILLICODE 13 /* Millicode function entry point. */
#define STT_HP_OPAQUE (STT_LOOS + 0x1)
libjit/jit/jit-elf-defs.h view on Meta::CPAN
#define PT_HP_CORE_MMF (PT_LOOS + 0x9)
#define PT_HP_PARALLEL (PT_LOOS + 0x10)
#define PT_HP_FASTBIND (PT_LOOS + 0x11)
#define PT_HP_OPT_ANNOT (PT_LOOS + 0x12)
#define PT_HP_HSL_ANNOT (PT_LOOS + 0x13)
#define PT_HP_STACK (PT_LOOS + 0x14)
#define PT_PARISC_ARCHEXT 0x70000000
#define PT_PARISC_UNWIND 0x70000001
/* Legal values for p_flags field of Elf32_Phdr/Elf64_Phdr. */
#define PF_PARISC_SBP 0x08000000
#define PF_HP_PAGE_SIZE 0x00100000
#define PF_HP_FAR_SHARED 0x00200000
#define PF_HP_NEAR_SHARED 0x00400000
#define PF_HP_CODE 0x01000000
#define PF_HP_MODIFY 0x02000000
#define PF_HP_LAZYSWAP 0x04000000
#define PF_HP_SBP 0x08000000
/* Alpha specific definitions. */
/* Legal values for e_flags field of Elf64_Ehdr. */
#define EF_ALPHA_32BIT 1 /* All addresses must be < 2GB. */
#define EF_ALPHA_CANRELAX 2 /* Relocations for relaxing exist. */
/* Legal values for sh_type field of Elf64_Shdr. */
/* These two are primerily concerned with ECOFF debugging info. */
#define SHT_ALPHA_DEBUG 0x70000001
#define SHT_ALPHA_REGINFO 0x70000002
/* Legal values for sh_flags field of Elf64_Shdr. */
#define SHF_ALPHA_GPREL 0x10000000
/* Legal values for st_other field of Elf64_Sym. */
#define STO_ALPHA_NOPV 0x80 /* No PV required. */
#define STO_ALPHA_STD_GPLOAD 0x88 /* PV only used for initial ldgp. */
/* Alpha relocs. */
#define R_ALPHA_NONE 0 /* No reloc */
libjit/jit/jit-elf-defs.h view on Meta::CPAN
#define R_ALPHA_COPY 24 /* Copy symbol at runtime */
#define R_ALPHA_GLOB_DAT 25 /* Create GOT entry */
#define R_ALPHA_JMP_SLOT 26 /* Create PLT entry */
#define R_ALPHA_RELATIVE 27 /* Adjust by program base */
/* Keep this the last entry. */
#define R_ALPHA_NUM 28
/* PowerPC specific declarations */
/* Values for Elf32/64_Ehdr.e_flags. */
#define EF_PPC_EMB 0x80000000 /* PowerPC embedded flag */
/* Cygnus local bits below */
#define EF_PPC_RELOCATABLE 0x00010000 /* PowerPC -mrelocatable flag*/
#define EF_PPC_RELOCATABLE_LIB 0x00008000 /* PowerPC -mrelocatable-lib
flag */
/* PowerPC relocations defined by the ABIs */
#define R_PPC_NONE 0
#define R_PPC_ADDR32 1 /* 32bit absolute address */
#define R_PPC_ADDR24 2 /* 26bit address, 2 bits ignored. */
#define R_PPC_ADDR16 3 /* 16bit absolute address */
#define R_PPC_ADDR16_LO 4 /* lower 16bit of absolute address */
#define R_PPC_ADDR16_HI 5 /* high 16bit of absolute address */
#define R_PPC_ADDR16_HA 6 /* adjusted high 16bit */
#define R_PPC_ADDR14 7 /* 16bit address, 2 bits ignored */
libjit/jit/jit-elf-defs.h view on Meta::CPAN
#define R_PPC_DIAB_RELSDA_HI 184 /* like EMB_RELSDA, but high 16 bit */
#define R_PPC_DIAB_RELSDA_HA 185 /* like EMB_RELSDA, adjusted high 16 */
/* This is a phony reloc to handle any old fashioned TOC16 references
that may still be in object files. */
#define R_PPC_TOC16 255
/* ARM specific declarations */
/* Processor specific flags for the ELF header e_flags field. */
#define EF_ARM_RELEXEC 0x01
#define EF_ARM_HASENTRY 0x02
#define EF_ARM_INTERWORK 0x04
#define EF_ARM_APCS_26 0x08
#define EF_ARM_APCS_FLOAT 0x10
#define EF_ARM_PIC 0x20
#define EF_ARM_ALIGN8 0x40 /* 8-bit structure alignment is in use */
#define EF_ARM_NEW_ABI 0x80
#define EF_ARM_OLD_ABI 0x100
/* Other constants defined in the ARM ELF spec. version B-01. */
/* NB. These conflict with values defined above. */
#define EF_ARM_SYMSARESORTED 0x04
#define EF_ARM_DYNSYMSUSESEGIDX 0x08
#define EF_ARM_MAPSYMSFIRST 0x10
#define EF_ARM_EABIMASK 0XFF000000
#define EF_ARM_EABI_VERSION(flags) ((flags) & EF_ARM_EABIMASK)
#define EF_ARM_EABI_UNKNOWN 0x00000000
#define EF_ARM_EABI_VER1 0x01000000
#define EF_ARM_EABI_VER2 0x02000000
/* Additional symbol types for Thumb */
#define STT_ARM_TFUNC 0xd
/* ARM-specific values for sh_flags */
#define SHF_ARM_ENTRYSECT 0x10000000 /* Section contains an entry point */
#define SHF_ARM_COMDEF 0x80000000 /* Section may be multiply defined
in the input to a link step */
/* ARM-specific program header flags */
#define PF_ARM_SB 0x10000000 /* Segment contains the location
addressed by the static base */
/* ARM relocs. */
#define R_ARM_NONE 0 /* No reloc */
#define R_ARM_PC24 1 /* PC relative 26 bit branch */
#define R_ARM_ABS32 2 /* Direct 32 bit */
#define R_ARM_REL32 3 /* PC relative 32 bit */
#define R_ARM_PC13 4
#define R_ARM_ABS16 5 /* Direct 16 bit */
libjit/jit/jit-elf-defs.h view on Meta::CPAN
#define R_ARM_THM_RPC22 251
#define R_ARM_RREL32 252
#define R_ARM_RABS22 253
#define R_ARM_RPC24 254
#define R_ARM_RBASE 255
/* Keep this the last entry. */
#define R_ARM_NUM 256
/* IA-64 specific declarations. */
/* Processor specific flags for the Ehdr e_flags field. */
#define EF_IA_64_MASKOS 0x0000000f /* os-specific flags */
#define EF_IA_64_ABI64 0x00000010 /* 64-bit ABI */
#define EF_IA_64_ARCH 0xff000000 /* arch. version mask */
/* Processor specific values for the Phdr p_type field. */
#define PT_IA_64_ARCHEXT (PT_LOPROC + 0) /* arch extension bits */
#define PT_IA_64_UNWIND (PT_LOPROC + 1) /* ia64 unwind bits */
/* Processor specific flags for the Phdr p_flags field. */
#define PF_IA_64_NORECOV 0x80000000 /* spec insns w/o recovery */
/* Processor specific values for the Shdr sh_type field. */
#define SHT_IA_64_EXT (SHT_LOPROC + 0) /* extension bits */
#define SHT_IA_64_UNWIND (SHT_LOPROC + 1) /* unwind bits */
/* Processor specific flags for the Shdr sh_flags field. */
#define SHF_IA_64_SHORT 0x10000000 /* section near gp */
#define SHF_IA_64_NORECOV 0x20000000 /* spec insns w/o recovery */
/* Processor specific values for the Dyn d_tag field. */
#define DT_IA_64_PLT_RESERVE (DT_LOPROC + 0)
#define DT_IA_64_NUM 1
/* IA-64 relocations. */
#define R_IA64_NONE 0x00 /* none */
#define R_IA64_IMM14 0x21 /* symbol + addend, add imm14 */
libjit/jit/jit-elf-read.c view on Meta::CPAN
{
temp_end += page_size - (temp_end % page_size);
}
start = phdr->p_vaddr;
start -= (start % page_size);
if(temp_start < temp_end)
{
segment_address =
((unsigned char *)base_address) + (jit_nuint)start;
prot = 0;
if((phdr->p_flags & PF_X) != 0)
{
prot |= PROT_EXEC;
}
if((phdr->p_flags & PF_W) != 0)
{
prot |= PROT_WRITE;
}
if((phdr->p_flags & PF_R) != 0)
{
prot |= PROT_READ;
}
if(mmap(segment_address, (size_t)(temp_end - temp_start),
prot, MAP_COPY | MAP_FILE | MAP_FIXED, fd,
(off_t)temp_start) == (void *)(jit_nint)(-1))
{
munmap(base_address, (size_t)end);
base_address = 0;
goto failed_mmap;
libjit/jit/jit-elf-read.c view on Meta::CPAN
if(start != 0)
{
segment_address =
((unsigned char *)base_address) +
(jit_nuint)temp_start;
mprotect(segment_address, (size_t)page_size,
PROT_READ | PROT_WRITE);
jit_memzero(segment_address + (jit_nuint)start,
(unsigned int)(page_size - start));
prot = 0;
if((phdr->p_flags & PF_X) != 0)
{
prot |= PROT_EXEC;
}
if((phdr->p_flags & PF_W) != 0)
{
prot |= PROT_WRITE;
}
if((phdr->p_flags & PF_R) != 0)
{
prot |= PROT_READ;
}
mprotect(segment_address, (size_t)page_size, prot);
}
}
}
}
failed_mmap:
#endif /* JIT_USE_MMAP_TO_LOAD */
libjit/jit/jit-elf-read.c view on Meta::CPAN
readelf->map_address = base_address;
readelf->map_size = memory_size;
return 1;
}
/*
* Map an auxillary section into memory and return its base address.
* Returns NULL if we ran out of memory.
*/
static void *map_section(int fd, Elf_Off offset, Elf_Xword file_size,
Elf_Xword memory_size, Elf_Word flags)
{
void *address;
if(memory_size < file_size)
{
memory_size = file_size;
}
address = _jit_malloc_exec(memory_size);
if(!address)
{
return 0;
libjit/jit/jit-elf-read.c view on Meta::CPAN
_jit_free_exec(address, memory_size);
return 0;
}
return address;
}
/*
* Unmap an auxillary section from memory.
*/
static void unmap_section(void *address, Elf_Xword file_size,
Elf_Xword memory_size, Elf_Word flags)
{
if(memory_size < file_size)
{
memory_size = file_size;
}
if((flags & JIT_ELF_IS_MALLOCED) != 0)
{
_jit_free_exec(address, (unsigned int)memory_size);
}
}
/*
* Iterate over the contents of the ".dynamic" section.
*/
typedef struct
{
libjit/jit/jit-elf-read.c view on Meta::CPAN
}
return 1;
}
}
return 0;
}
/*
* Load interesting values from the ".dynamic" section, for quicker lookups.
*/
static void load_dynamic_section(jit_readelf_t readelf, int flags)
{
Elf_Addr value;
Elf_Addr value2;
jit_dynamic_iter_t iter;
jit_uint type;
jit_nuint size;
/* Get the position and size of the dynamic string table */
if(dynamic_for_type(readelf, DT_STRTAB, &value) &&
dynamic_for_type(readelf, DT_STRSZ, &value2))
libjit/jit/jit-elf-read.c view on Meta::CPAN
}
}
}
else
{
readelf->symbol_table = 0;
}
}
/* Bail out if we don't need to print debugging information */
if((flags & JIT_READELF_FLAG_DEBUG) == 0)
{
return;
}
/* Iterate through the ".dynamic" section, dumping all that we find */
dynamic_iter_init(&iter, readelf);
while(dynamic_iter_next(&iter, &type, &value))
{
switch(type)
{
libjit/jit/jit-elf-read.c view on Meta::CPAN
*
* @vindex JIT_READELF_BAD_FORMAT
* @item JIT_READELF_BAD_FORMAT
* The file is an ELF binary, but the format is corrupted in some fashion.
*
* @vindex JIT_READELF_MEMORY
* @item JIT_READELF_MEMORY
* There is insufficient memory to open the ELF binary.
* @end table
*
* The following flags may be supplied to alter the manner in which
* the ELF binary is loaded:
*
* @table @code
* @vindex JIT_READELF_FLAG_FORCE
* @item JIT_READELF_FLAG_FORCE
* Force @code{jit_readelf_open} to open the ELF binary, even if
* the architecture does not match this machine. Useful for debugging.
*
* @vindex JIT_READELF_FLAG_DEBUG
* @item JIT_READELF_FLAG_DEBUG
* Print additional debug information to stdout.
* @end table
* @end deftypefun
@*/
int jit_readelf_open(jit_readelf_t *_readelf, const char *filename, int flags)
{
int fd;
Elf_Ehdr ehdr;
Elf_Phdr *phdr;
Elf_Shdr *shdr;
jit_elf_info_t elf_info;
jit_readelf_t readelf;
unsigned int phdr_size;
unsigned int shdr_size;
unsigned int index;
libjit/jit/jit-elf-read.c view on Meta::CPAN
{
sys_close(fd);
return JIT_READELF_BAD_FORMAT;
}
if(ehdr.e_type != ET_DYN)
{
/* We can only load files that are marked as dynamic shared objects */
sys_close(fd);
return JIT_READELF_WRONG_ARCH;
}
if((flags & JIT_READELF_FLAG_FORCE) == 0)
{
if(ehdr.e_machine != elf_info.machine ||
ehdr.e_ident[EI_OSABI] != elf_info.abi ||
ehdr.e_ident[EI_ABIVERSION] != elf_info.abi_version)
{
/* The ELF binary does not pertain to this machine or ABI type */
sys_close(fd);
return JIT_READELF_WRONG_ARCH;
}
}
libjit/jit/jit-elf-read.c view on Meta::CPAN
/* Load the auxillary sections */
if(shdr_size > 0)
{
for(index = 0; index < ehdr.e_shnum; ++index)
{
shdr = get_shdr(readelf, index);
if(!shdr)
{
continue;
}
if((shdr->sh_flags & SHF_ALLOC) != 0 || shdr->sh_addr != 0)
{
/* This may be mapped inside one of the program segments.
If so, we don't want to load a second copy of it */
address = jit_readelf_map_vaddr(readelf, shdr->sh_addr);
if(address)
{
continue;
}
}
if(shdr->sh_size == 0)
{
/* Ignore zero-sized segments */
continue;
}
address = map_section
(fd, shdr->sh_offset, shdr->sh_size, shdr->sh_size,
((shdr->sh_flags & SHF_WRITE) != 0 ? (PF_W | PF_R) : PF_R));
if(!address)
{
jit_readelf_close(readelf);
sys_close(fd);
return JIT_READELF_MEMORY;
}
shdr->sh_offset = (Elf_Off)(jit_nuint)address;
shdr->sh_flags |= JIT_ELF_IS_MALLOCED;
}
}
/* Close the file descriptor because we don't need it any more */
sys_close(fd);
/* Find the regular string table */
shdr = get_shdr(readelf, ehdr.e_shstrndx);
if(shdr)
{
if((shdr->sh_flags & JIT_ELF_IS_MALLOCED) != 0)
{
readelf->regular_strings = (char *)(jit_nuint)(shdr->sh_offset);
}
else
{
readelf->regular_strings =
(char *)jit_readelf_map_vaddr(readelf, shdr->sh_addr);
}
if(readelf->regular_strings)
{
readelf->regular_strings_size = (jit_nuint)(shdr->sh_size);
}
}
/* Dump debug information about the program segments and sections */
if((flags & JIT_READELF_FLAG_DEBUG) != 0)
{
printf("header: machine=%d, abi=%d, abi_version=%d\n",
(int)(ehdr.e_machine), (int)(ehdr.e_ident[EI_OSABI]),
(int)(ehdr.e_ident[EI_ABIVERSION]));
for(index = 0; index < ehdr.e_phnum; ++index)
{
phdr = get_phdr(readelf, index);
if(phdr)
{
printf("program segment: type=%d, flags=0x%x, "
"vaddr=0x%lx, file_size=%ld, memory_size=%ld\n",
(int)(phdr->p_type),
(int)(phdr->p_flags & ~JIT_ELF_IS_MALLOCED),
(long)(phdr->p_vaddr),
(long)(phdr->p_filesz),
(long)(phdr->p_memsz));
}
}
for(index = 0; index < ehdr.e_shnum; ++index)
{
shdr = get_shdr(readelf, index);
if(shdr)
{
printf("section %2d: name=\"%s\", type=%d, flags=0x%x, "
"vaddr=0x%lx, size=%ld\n",
index,
get_string(readelf, shdr->sh_name),
(int)(shdr->sh_type),
(int)(shdr->sh_flags & ~JIT_ELF_IS_MALLOCED),
(long)(shdr->sh_addr),
(long)(shdr->sh_size));
}
}
}
/* Get the relocation function for this machine type */
readelf->reloc_func = get_reloc((unsigned int)(ehdr.e_machine));
/* Load useful values from the dynamic section that we want to cache */
load_dynamic_section(readelf, flags);
/* The ELF binary is loaded and ready to go */
*_readelf = readelf;
return JIT_READELF_OK;
}
/*@
* @deftypefun void jit_readelf_close (jit_readelf_t @var{readelf})
* Close an ELF reader, reclaiming all of the memory that was used.
* @end deftypefun
libjit/jit/jit-elf-read.c view on Meta::CPAN
munmap(readelf->map_address, (size_t)(readelf->map_size));
}
else
#endif
{
_jit_free_exec(readelf->map_address, readelf->map_size);
}
for(index = 0; index < readelf->ehdr.e_shnum; ++index)
{
shdr = get_shdr(readelf, index);
if(shdr && (shdr->sh_flags & JIT_ELF_IS_MALLOCED) != 0)
{
unmap_section
((void *)(jit_nuint)(shdr->sh_offset),
shdr->sh_size, shdr->sh_size, shdr->sh_flags);
}
}
jit_free(readelf->phdrs);
jit_free(readelf->shdrs);
jit_free(readelf);
}
/*@
* @deftypefun {const char *} jit_readelf_get_name (jit_readelf_t @var{readelf})
* Get the library name that is embedded inside an ELF binary.
libjit/jit/jit-elf-read.c view on Meta::CPAN
shdr = get_shdr(readelf, index);
if(shdr)
{
temp_name = get_string(readelf, shdr->sh_name);
if(temp_name && !jit_strcmp(name, temp_name))
{
if(size)
{
*size = (jit_nuint)(shdr->sh_size);
}
if((shdr->sh_flags & JIT_ELF_IS_MALLOCED) != 0)
{
return (void *)(jit_nuint)(shdr->sh_offset);
}
else
{
return jit_readelf_map_vaddr
(readelf, (jit_nuint)(shdr->sh_addr));
}
}
}
libjit/jit/jit-elf-read.c view on Meta::CPAN
}
for(index = 0; index < readelf->ehdr.e_shnum; ++index)
{
shdr = get_shdr(readelf, index);
if(shdr && type == (jit_int)(shdr->sh_type))
{
if(size)
{
*size = (jit_nuint)(shdr->sh_size);
}
if((shdr->sh_flags & JIT_ELF_IS_MALLOCED) != 0)
{
return (void *)(jit_nuint)(shdr->sh_offset);
}
else
{
return jit_readelf_map_vaddr
(readelf, (jit_nuint)(shdr->sh_addr));
}
}
}
libjit/jit/jit-elf-write.c view on Meta::CPAN
index = (Elf_Word)(section->data_len);
section->data_len += name_len;
return index;
}
/*
* Get or add a section.
*/
static jit_section_t get_section
(jit_writeelf_t writeelf, const char *name, jit_int type,
Elf_Word flags, Elf_Word entry_size, Elf_Word alignment)
{
int index;
jit_section_t section;
/* Search the section table for an existing section by this name */
for(index = 0; index < writeelf->num_sections; ++index)
{
section = &(writeelf->sections[index]);
if(!jit_strcmp(get_string(writeelf, section->shdr.sh_name), name))
{
libjit/jit/jit-elf-write.c view on Meta::CPAN
{
section->shdr.sh_name = add_string(writeelf, name);
if(!(section->shdr.sh_name))
{
return 0;
}
}
/* Set the other section properties */
section->shdr.sh_type = (Elf_Word)type;
section->shdr.sh_flags = flags;
section->shdr.sh_entsize = entry_size;
section->shdr.sh_addralign = alignment;
/* Increase the section count and return */
++(writeelf->num_sections);
return section;
}
/*
* Append data to a section.
libjit/jit/jit-function.c view on Meta::CPAN
/*@
* @deftypefun int jit_function_set_recompilable (jit_function_t @var{func})
* Mark this function as a candidate for recompilation. That is,
* it is possible that we may call @code{jit_function_compile}
* more than once, to re-optimize an existing function.
*
* It is very important that this be called before the first time that
* you call @code{jit_function_compile}. Functions that are recompilable
* are invoked in a slightly different way to non-recompilable functions.
* If you don't set this flag, then existing invocations of the function
* may continue to be sent to the original compiled version, not the new
* version.
* @end deftypefun
@*/
void jit_function_set_recompilable(jit_function_t func)
{
if(func)
{
func->is_recompilable = 1;
}
}
/*@
* @deftypefun void jit_function_clear_recompilable (jit_function_t @var{func})
* Clear the recompilable flag on this function. Normally you would use
* this once you have decided that the function has been optimized enough,
* and that you no longer intend to call @code{jit_function_compile} again.
*
* Future uses of the function with @code{jit_insn_call} will output a
* direct call to the function, which is more efficient than calling
* its recompilable version. Pre-existing calls to the function may still
* use redirection stubs, and will remain so until the pre-existing
* functions are themselves recompiled.
* @end deftypefun
@*/
libjit/jit/jit-gen-x86.h view on Meta::CPAN
do { \
*(inst)++ = (((unsigned char)(opc)) << 3) + 3; \
x86_reg_emit ((inst), (dreg), (reg)); \
} while (0)
/**
* @x86_alu_reg8_reg8:
* Supports ALU operations between two 8-bit registers.
* dreg := dreg opc reg
* X86_Reg_No enum is used to specify the registers.
* Additionally is_*_h flags are used to specify what part
* of a given 32-bit register is used - high (TRUE) or low (FALSE).
* For example: dreg = X86_EAX, is_dreg_h = TRUE -> use AH
*/
#define x86_alu_reg8_reg8(inst,opc,dreg,reg,is_dreg_h,is_reg_h) \
do { \
*(inst)++ = (((unsigned char)(opc)) << 3) + 2; \
x86_reg8_emit ((inst), (dreg), (reg), (is_dreg_h), (is_reg_h)); \
} while (0)
#define x86_alu_reg_mem(inst,opc,reg,mem) \
libjit/jit/jit-insn.c view on Meta::CPAN
}
insn = _jit_block_add_insn(func->builder->current_block);
if(!insn)
{
return 0;
}
jit_value_ref(func, value1);
jit_value_ref(func, value2);
jit_value_ref(func, value3);
insn->opcode = (short)oper;
insn->flags = JIT_INSN_DEST_IS_VALUE;
insn->dest = value1;
insn->value1 = value2;
insn->value2 = value3;
return 1;
}
/*
* Create a note instruction, which doesn't have a result.
*/
static int create_note
libjit/jit/jit-insn.c view on Meta::CPAN
}
/*@
* @deftypefun jit_value_t jit_insn_get_dest (jit_insn_t @var{insn})
* Get the destination value that is associated with an instruction.
* Returns NULL if the instruction does not have a destination.
* @end deftypefun
@*/
jit_value_t jit_insn_get_dest(jit_insn_t insn)
{
if(insn && (insn->flags & JIT_INSN_DEST_OTHER_FLAGS) == 0)
{
return insn->dest;
}
else
{
return 0;
}
}
/*@
* @deftypefun jit_value_t jit_insn_get_value1 (jit_insn_t @var{insn})
* Get the first argument value that is associated with an instruction.
* Returns NULL if the instruction does not have a first argument value.
* @end deftypefun
@*/
jit_value_t jit_insn_get_value1(jit_insn_t insn)
{
if(insn && (insn->flags & JIT_INSN_VALUE1_OTHER_FLAGS) == 0)
{
return insn->value1;
}
else
{
return 0;
}
}
/*@
* @deftypefun jit_value_t jit_insn_get_value2 (jit_insn_t @var{insn})
* Get the second argument value that is associated with an instruction.
* Returns NULL if the instruction does not have a second argument value.
* @end deftypefun
@*/
jit_value_t jit_insn_get_value2(jit_insn_t insn)
{
if(insn && (insn->flags & JIT_INSN_VALUE2_OTHER_FLAGS) == 0)
{
return insn->value2;
}
else
{
return 0;
}
}
/*@
* @deftypefun jit_label_t jit_insn_get_label (jit_insn_t @var{insn})
* Get the label for a branch target from an instruction.
* Returns NULL if the instruction does not have a branch target.
* @end deftypefun
@*/
jit_label_t jit_insn_get_label(jit_insn_t insn)
{
if(insn && (insn->flags & JIT_INSN_DEST_IS_LABEL) != 0)
{
return (jit_label_t)(insn->dest);
}
else if(insn && (insn->flags & JIT_INSN_VALUE1_IS_LABEL) != 0)
{
/* "address_of_label" instruction */
return (jit_label_t)(insn->value1);
}
else
{
return 0;
}
}
/*@
* @deftypefun jit_function_t jit_insn_get_function (jit_insn_t @var{insn})
* Get the function for a call instruction. Returns NULL if the
* instruction does not refer to a called function.
* @end deftypefun
@*/
jit_function_t jit_insn_get_function(jit_insn_t insn)
{
if(insn && (insn->flags & JIT_INSN_DEST_IS_FUNCTION) != 0)
{
return (jit_function_t)(insn->dest);
}
else
{
return 0;
}
}
/*@
* @deftypefun {void *} jit_insn_get_native (jit_insn_t @var{insn})
* Get the function pointer for a native call instruction.
* Returns NULL if the instruction does not refer to a native
* function call.
* @end deftypefun
@*/
void *jit_insn_get_native(jit_insn_t insn)
{
if(insn && (insn->flags & JIT_INSN_DEST_IS_NATIVE) != 0)
{
return (void *)(insn->dest);
}
else
{
return 0;
}
}
/*@
* @deftypefun {const char *} jit_insn_get_name (jit_insn_t @var{insn})
* Get the diagnostic name for a function call. Returns NULL
* if the instruction does not have a diagnostic name.
* @end deftypefun
@*/
const char *jit_insn_get_name(jit_insn_t insn)
{
if(insn && (insn->flags & JIT_INSN_VALUE1_IS_NAME) != 0)
{
return (const char *)(insn->value1);
}
else
{
return 0;
}
}
/*@
* @deftypefun jit_type_t jit_insn_get_signature (jit_insn_t @var{insn})
* Get the signature for a function call instruction. Returns NULL
* if the instruction is not a function call.
* @end deftypefun
@*/
jit_type_t jit_insn_get_signature(jit_insn_t insn)
{
if(insn && (insn->flags & JIT_INSN_VALUE2_IS_SIGNATURE) != 0)
{
return (jit_type_t)(insn->value2);
}
else
{
return 0;
}
}
/*@
* @deftypefun int jit_insn_dest_is_value (jit_insn_t @var{insn})
* Returns a non-zero value if the destination for @var{insn} is
* actually a source value. This can happen with instructions
* such as @code{jit_insn_store_relative} where the instruction
* needs three source operands, and the real destination is a
* side-effect on one of the sources.
* @end deftypefun
@*/
int jit_insn_dest_is_value(jit_insn_t insn)
{
if(insn && (insn->flags & JIT_INSN_DEST_IS_VALUE) != 0)
{
return 1;
}
else
{
return 0;
}
}
/*@
libjit/jit/jit-insn.c view on Meta::CPAN
}
/* Scan forwards to ensure that "insn->value1"
is not modified anywhere in the instructions
that follow */
iter2 = iter;
jit_insn_iter_next(&iter2);
while((insn2 = jit_insn_iter_next(&iter2)) != 0)
{
if(insn2->dest == value
&& (insn2->flags & JIT_INSN_DEST_IS_VALUE) == 0)
{
return 0;
}
}
*plast = last;
return insn;
}
/* Oops. This instruction modifies "value" and blocks
any previous address_of or add_relative instructions */
if((insn->flags & JIT_INSN_DEST_IS_VALUE) == 0)
{
break;
}
}
/* We are to check instructions that preceed the last one */
last = 0;
}
return 0;
}
libjit/jit/jit-insn.c view on Meta::CPAN
return 0;
}
insn = _jit_block_add_insn(func->builder->current_block);
if(!insn)
{
return 0;
}
jit_value_ref(func, dest);
jit_value_ref(func, value);
insn->opcode = (short)_jit_store_opcode(JIT_OP_STORE_RELATIVE_BYTE, 0, value->type);
insn->flags = JIT_INSN_DEST_IS_VALUE;
insn->dest = dest;
insn->value1 = value;
insn->value2 = offset_value;
return 1;
}
/*@
* @deftypefun jit_value_t jit_insn_add_relative (jit_function_t @var{func}, jit_value_t @var{value}, jit_nint @var{offset})
* Add the constant @var{offset} to the specified pointer @var{value}.
* This is functionally identical to calling @code{jit_insn_add}, but
libjit/jit/jit-insn.c view on Meta::CPAN
insn = _jit_block_add_insn(func->builder->current_block);
if(!insn)
{
return 0;
}
if(*label == jit_label_undefined)
{
*label = (func->builder->next_label)++;
}
insn->opcode = (short)JIT_OP_BR;
insn->flags = JIT_INSN_DEST_IS_LABEL;
insn->dest = (jit_value_t)(*label);
func->builder->current_block->ends_in_dead = 1;
return jit_insn_new_block(func);
}
/*@
* @deftypefun int jit_insn_branch_if (jit_function_t @var{func}, jit_value_t @var{value}, jit_label_t *@var{label})
* Terminate the current block by branching to a specific label if
* the specified value is non-zero. Returns zero if out of memory.
*
libjit/jit/jit-insn.c view on Meta::CPAN
value2 = prev->value2;
insn = _jit_block_add_insn(func->builder->current_block);
if(!insn)
{
return 0;
}
jit_value_ref(func, value1);
jit_value_ref(func, value2);
insn->opcode = (short)opcode;
insn->flags = JIT_INSN_DEST_IS_LABEL;
insn->dest = (jit_value_t)(*label);
insn->value1 = value1;
insn->value2 = value2;
goto add_block;
}
}
/* Coerce the result to something comparable and determine the opcode */
type = jit_type_promote_int(jit_type_normalize(value->type));
if(type == jit_type_int || type == jit_type_uint)
libjit/jit/jit-insn.c view on Meta::CPAN
/* Add a new branch instruction */
insn = _jit_block_add_insn(func->builder->current_block);
if(!insn)
{
return 0;
}
jit_value_ref(func, value);
jit_value_ref(func, value2);
insn->opcode = (short)opcode;
insn->flags = JIT_INSN_DEST_IS_LABEL;
insn->dest = (jit_value_t)(*label);
insn->value1 = value;
insn->value2 = value2;
add_block:
/* Add a new block for the fall-through case */
return jit_insn_new_block(func);
}
/*@
libjit/jit/jit-insn.c view on Meta::CPAN
value2 = prev->value2;
insn = _jit_block_add_insn(func->builder->current_block);
if(!insn)
{
return 0;
}
jit_value_ref(func, value1);
jit_value_ref(func, value2);
insn->opcode = (short)opcode;
insn->flags = JIT_INSN_DEST_IS_LABEL;
insn->dest = (jit_value_t)(*label);
insn->value1 = value1;
insn->value2 = value2;
goto add_block;
}
}
/* Coerce the result to something comparable and determine the opcode */
type = jit_type_promote_int(jit_type_normalize(value->type));
if(type == jit_type_int || type == jit_type_uint)
libjit/jit/jit-insn.c view on Meta::CPAN
/* Add a new branch instruction */
insn = _jit_block_add_insn(func->builder->current_block);
if(!insn)
{
return 0;
}
jit_value_ref(func, value);
jit_value_ref(func, value2);
insn->opcode = (short)opcode;
insn->flags = JIT_INSN_DEST_IS_LABEL;
insn->dest = (jit_value_t)(*label);
insn->value1 = value;
insn->value2 = value2;
add_block:
/* Add a new block for the fall-through case */
return jit_insn_new_block(func);
}
/*@
libjit/jit/jit-insn.c view on Meta::CPAN
/* Add a new branch instruction */
insn = _jit_block_add_insn(func->builder->current_block);
if(!insn)
{
return 0;
}
jit_value_ref(func, value);
insn->opcode = JIT_OP_JUMP_TABLE;
insn->flags = JIT_INSN_DEST_IS_VALUE;
insn->dest = value;
insn->value1 = value_labels;
insn->value2 = value_num_labels;
/* Add a new block for the fall-through case */
return jit_insn_new_block(func);
}
/*@
* @deftypefun jit_value_t jit_insn_address_of (jit_function_t @var{func}, jit_value_t @var{value1})
libjit/jit/jit-insn.c view on Meta::CPAN
jit_value_t dest;
jit_insn_t insn;
if(!_jit_function_ensure_builder(func) || !label)
{
return 0;
}
if(*label == jit_label_undefined)
{
*label = (func->builder->next_label)++;
}
if(!_jit_block_record_label_flags(func, *label, JIT_LABEL_ADDRESS_OF))
{
return 0;
}
insn = _jit_block_add_insn(func->builder->current_block);
if(!insn)
{
return 0;
}
dest = jit_value_create(func, jit_type_void_ptr);
if(!dest)
{
return 0;
}
insn->opcode = (short)JIT_OP_ADDRESS_OF_LABEL;
insn->flags = JIT_INSN_VALUE1_IS_LABEL;
insn->dest = dest;
insn->value1 = (jit_value_t)(*label);
return dest;
}
/*
* Information about the opcodes for a particular conversion.
*/
typedef struct jit_convert_info
{
libjit/jit/jit-insn.c view on Meta::CPAN
CVT_INTRINSIC(jit_float64_to_nfloat, float64, nfloat)
};
/*
* Apply a unary conversion operator.
*/
static jit_value_t apply_unary_conversion
(jit_function_t func, int oper, jit_value_t value1,
jit_type_t result_type)
{
/* Set the "may_throw" flag if the conversion may throw an exception */
if(convert_intrinsics[oper - 1].descr.ptr_result_type)
{
func->builder->may_throw = 1;
}
/* Bail out early if the conversion opcode is supported by the back end */
if(_jit_opcode_is_supported(oper))
{
return apply_unary(func, oper, value1, result_type);
}
libjit/jit/jit-insn.c view on Meta::CPAN
new_args[param] = jit_insn_convert
(func, args[param],
jit_type_get_param(signature, param), 0);
}
return 1;
}
/*
* Set up the exception frame information before a function call out.
*/
static int setup_eh_frame_for_call(jit_function_t func, int flags)
{
#if !defined(JIT_BACKEND_INTERP)
jit_type_t type;
jit_value_t args[2];
jit_insn_t insn;
/* If "tail" is set, then we need to pop the "setjmp" context */
if((flags & JIT_CALL_TAIL) != 0 && func->has_try)
{
type = jit_type_create_signature
(jit_abi_cdecl, jit_type_void, 0, 0, 1);
if(!type)
{
return 0;
}
jit_insn_call_native
(func, "_jit_unwind_pop_setjmp",
(void *)_jit_unwind_pop_setjmp, type, 0, 0, JIT_CALL_NOTHROW);
jit_type_free(type);
}
/* If "nothrow" or "tail" is set, then there is no more to do */
if((flags & (JIT_CALL_NOTHROW | JIT_CALL_TAIL)) != 0)
{
return 1;
}
/* This function may throw an exception */
func->builder->may_throw = 1;
#if JIT_APPLY_BROKEN_FRAME_BUILTINS != 0
{
jit_value_t eh_frame_info;
libjit/jit/jit-insn.c view on Meta::CPAN
jit_jmp_catch_pc_offset, args[0]))
{
return 0;
}
}
/* We are now ready to make the actual function call */
return 1;
#else /* JIT_BACKEND_INTERP */
/* The interpreter handles exception frames for us */
if((flags & (JIT_CALL_NOTHROW | JIT_CALL_TAIL)) == 0)
{
func->builder->may_throw = 1;
}
return 1;
#endif
}
/*
* Restore the exception handling frame after a function call.
*/
static int restore_eh_frame_after_call(jit_function_t func, int flags)
{
#if !defined(JIT_BACKEND_INTERP)
jit_value_t value;
/* If the "nothrow", "noreturn", or "tail" flags are set, then we
don't need to worry about this */
if((flags & (JIT_CALL_NOTHROW | JIT_CALL_NORETURN | JIT_CALL_TAIL)) != 0)
{
return 1;
}
#if JIT_APPLY_BROKEN_FRAME_BUILTINS != 0
{
jit_type_t type;
/* Create the signature prototype "void (void)" */
type = jit_type_create_signature
libjit/jit/jit-insn.c view on Meta::CPAN
/* If we get here, then the types are compatible */
return 1;
}
/*
* Create call setup instructions, taking tail calls into effect.
*/
static int create_call_setup_insns
(jit_function_t func, jit_function_t callee, jit_type_t signature,
jit_value_t *args, unsigned int num_args,
int is_nested, int nesting_level, jit_value_t *struct_return, int flags)
{
jit_value_t *new_args;
jit_value_t value;
unsigned int arg_num;
/* If we are performing a tail call, then duplicate the argument
values so that we don't accidentally destroy parameters in
situations like func(x, y) -> func(y, x) */
if((flags & JIT_CALL_TAIL) != 0 && num_args > 0)
{
new_args = (jit_value_t *)alloca(sizeof(jit_value_t) * num_args);
for(arg_num = 0; arg_num < num_args; ++arg_num)
{
value = args[arg_num];
if(value && value->is_parameter)
{
value = jit_insn_dup(func, value);
if(!value)
{
return 0;
}
}
new_args[arg_num] = value;
}
args = new_args;
}
/* If we are performing a tail call, then store back to our own parameters */
if((flags & JIT_CALL_TAIL) != 0)
{
for(arg_num = 0; arg_num < num_args; ++arg_num)
{
if(!jit_insn_store(func, jit_value_get_param(func, arg_num),
args[arg_num]))
{
return 0;
}
}
*struct_return = 0;
return 1;
}
/* Let the back end do the work */
return _jit_create_call_setup_insns
(func, signature, args, num_args,
is_nested, nesting_level, struct_return, flags);
}
static jit_value_t
handle_return(jit_function_t func,
jit_type_t signature,
int flags, int is_nested,
jit_value_t *args, unsigned int num_args,
jit_value_t return_value)
{
/* If the function does not return, then end the current block.
The next block does not have "entered_via_top" set so that
it will be eliminated during later code generation */
if((flags & (JIT_CALL_NORETURN | JIT_CALL_TAIL)) != 0)
{
func->builder->current_block->ends_in_dead = 1;
}
/* If the function may throw an exceptions then end the current
basic block to account for exceptional control flow */
if((flags & JIT_CALL_NOTHROW) == 0)
{
if(!jit_insn_new_block(func))
{
return 0;
}
}
/* Create space for the return value, if we don't already have one */
if(!return_value)
{
return_value = jit_value_create(func, jit_type_get_return(signature));
if(!return_value)
{
return 0;
}
}
/* Create the instructions necessary to move the return value into place */
if((flags & JIT_CALL_TAIL) == 0)
{
if(!_jit_create_call_return_insns(func,
signature,
args, num_args,
return_value,
is_nested))
{
return 0;
}
}
/* Restore exception frame information after the call */
if(!restore_eh_frame_after_call(func, flags))
{
return 0;
}
/* Return the value containing the result to the caller */
return return_value;
}
/*@
* @deftypefun jit_value_t jit_insn_call (jit_function_t @var{func}, const char *@var{name}, jit_function_t @var{jit_func}, jit_type_t @var{signature}, jit_value_t *@var{args}, unsigned int @var{num_args}, int @var{flags})
* Call the function @var{jit_func}, which may or may not be translated yet.
* The @var{name} is for diagnostic purposes only, and can be NULL.
*
* If @var{signature} is NULL, then the actual signature of @var{jit_func}
* is used in its place. This is the usual case. However, if the function
* takes a variable number of arguments, then you may need to construct
* an explicit signature for the non-fixed argument values.
*
* The @var{flags} parameter specifies additional information about the
* type of call to perform:
*
* @table @code
* @vindex JIT_CALL_NOTHROW
* @item JIT_CALL_NOTHROW
* The function never throws exceptions.
*
* @vindex JIT_CALL_NORETURN
* @item JIT_CALL_NORETURN
* The function will never return directly to its caller. It may however
libjit/jit/jit-insn.c view on Meta::CPAN
* @vindex JIT_CALL_TAIL
* @item JIT_CALL_TAIL
* Apply tail call optimizations, as the result of this function
* call will be immediately returned from the containing function.
* Tail calls are only appropriate when the signature of the called
* function matches the callee, and none of the parameters point
* to local variables.
* @end table
*
* If @var{jit_func} has already been compiled, then @code{jit_insn_call}
* may be able to intuit some of the above flags for itself. Otherwise
* it is up to the caller to determine when the flags may be appropriate.
* @end deftypefun
@*/
jit_value_t jit_insn_call
(jit_function_t func, const char *name, jit_function_t jit_func,
jit_type_t signature, jit_value_t *args, unsigned int num_args, int flags)
{
int is_nested;
int nesting_level;
jit_function_t temp_func;
jit_value_t *new_args;
jit_value_t return_value;
jit_insn_t insn;
jit_label_t entry_point;
jit_label_t label_end;
libjit/jit/jit-insn.c view on Meta::CPAN
return 0;
}
/* 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 */
libjit/jit/jit-insn.c view on Meta::CPAN
if(!convert_call_parameters(func, signature, args, num_args, new_args))
{
return 0;
}
}
else
{
new_args = args;
}
/* Intuit additional flags from "jit_func" if it was already compiled */
if(func->no_throw)
{
flags |= JIT_CALL_NOTHROW;
}
if(func->no_return)
{
flags |= JIT_CALL_NORETURN;
}
/* Set up exception frame information for the call */
if(!setup_eh_frame_for_call(func, flags))
{
return 0;
}
/* Create the instructions to push the parameters onto the stack */
if(!create_call_setup_insns
(func, jit_func, signature, new_args, num_args,
is_nested, nesting_level, &return_value, flags))
{
return 0;
}
/* Output the "call" instruction */
if((flags & JIT_CALL_TAIL) != 0 && func == jit_func)
{
/* We are performing a tail call to ourselves, which we can
turn into an unconditional branch back to our entry point */
entry_point = jit_label_undefined;
label_end = jit_label_undefined;
if(!jit_insn_branch(func, &entry_point))
{
return 0;
}
if(!jit_insn_label(func, &entry_point))
libjit/jit/jit-insn.c view on Meta::CPAN
{
/* Functions that call out are not leaves */
func->builder->non_leaf = 1;
/* Performing a regular call, or a tail call to someone else */
insn = _jit_block_add_insn(func->builder->current_block);
if(!insn)
{
return 0;
}
if((flags & JIT_CALL_TAIL) != 0)
{
func->builder->has_tail_call = 1;
insn->opcode = JIT_OP_CALL_TAIL;
}
else
{
insn->opcode = JIT_OP_CALL;
}
insn->flags = JIT_INSN_DEST_IS_FUNCTION | JIT_INSN_VALUE1_IS_NAME;
insn->dest = (jit_value_t)jit_func;
insn->value1 = (jit_value_t)name;
}
/* Handle return to the caller */
return handle_return(func, signature, flags, is_nested,
new_args, num_args, return_value);
}
/*@
* @deftypefun jit_value_t jit_insn_call_indirect (jit_function_t @var{func}, jit_value_t @var{value}, jit_type_t @var{signature}, jit_value_t *@var{args}, unsigned int @var{num_args}, int @var{flags})
* Call a function via an indirect pointer.
* @end deftypefun
@*/
jit_value_t jit_insn_call_indirect
(jit_function_t func, jit_value_t value, jit_type_t signature,
jit_value_t *args, unsigned int num_args, int flags)
{
jit_value_t *new_args;
jit_value_t return_value;
jit_insn_t insn;
/* 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 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
/* We are making a native call */
flags |= JIT_CALL_NATIVE;
/* Convert the arguments to the actual parameter types */
if(num_args > 0)
{
new_args = (jit_value_t *)alloca(sizeof(jit_value_t) * num_args);
if(!convert_call_parameters(func, signature, args, num_args, new_args))
{
return 0;
}
}
else
{
new_args = args;
}
/* Set up exception frame information for the call */
if(!setup_eh_frame_for_call(func, flags))
{
return 0;
}
/* Create the instructions to push the parameters onto the stack */
if(!create_call_setup_insns
(func, 0, signature, new_args, num_args, 0, 0, &return_value, flags))
{
return 0;
}
/* Move the indirect pointer value into an appropriate register */
if(!_jit_setup_indirect_pointer(func, value))
{
return 0;
}
/* Functions that call out are not leaves */
func->builder->non_leaf = 1;
/* Output the "call_indirect" instruction */
insn = _jit_block_add_insn(func->builder->current_block);
if(!insn)
{
return 0;
}
jit_value_ref(func, value);
if((flags & JIT_CALL_TAIL) != 0)
{
func->builder->has_tail_call = 1;
insn->opcode = JIT_OP_CALL_INDIRECT_TAIL;
}
else
{
insn->opcode = JIT_OP_CALL_INDIRECT;
}
insn->flags = JIT_INSN_VALUE2_IS_SIGNATURE;
insn->value1 = value;
insn->value2 = (jit_value_t)jit_type_copy(signature);
/* Handle return to the caller */
return handle_return(func, signature, flags, 0,
new_args, num_args, return_value);
}
/*@
* @deftypefun jit_value_t jit_insn_call_indirect_vtable (jit_function_t @var{func}, jit_value_t @var{value}, jit_type_t @var{signature}, jit_value_t *@var{args}, unsigned int @var{num_args}, int @var{flags})
* Call a function via an indirect pointer. This version differs from
* @code{jit_insn_call_indirect} in that we assume that @var{value}
* contains a pointer that resulted from calling
* @code{jit_function_to_vtable_pointer}. Indirect vtable pointer
* calls may be more efficient on some platforms than regular indirect calls.
* @end deftypefun
@*/
jit_value_t jit_insn_call_indirect_vtable
(jit_function_t func, jit_value_t value, jit_type_t signature,
jit_value_t *args, unsigned int num_args, int flags)
{
jit_value_t *new_args;
jit_value_t return_value;
jit_insn_t insn;
/* 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 */
if(num_args > 0)
{
new_args = (jit_value_t *)alloca(sizeof(jit_value_t) * num_args);
if(!convert_call_parameters(func, signature, args, num_args, new_args))
{
return 0;
}
}
else
{
new_args = args;
}
/* Set up exception frame information for the call */
if(!setup_eh_frame_for_call(func, flags))
{
return 0;
}
/* Create the instructions to push the parameters onto the stack */
if(!create_call_setup_insns
(func, 0, signature, new_args, num_args, 0, 0, &return_value, flags))
{
return 0;
}
/* Move the indirect pointer value into an appropriate register */
if(!_jit_setup_indirect_pointer(func, value))
{
return 0;
}
/* Functions that call out are not leaves */
func->builder->non_leaf = 1;
/* Output the "call_vtable_ptr" instruction */
insn = _jit_block_add_insn(func->builder->current_block);
if(!insn)
{
return 0;
}
jit_value_ref(func, value);
if((flags & JIT_CALL_TAIL) != 0)
{
func->builder->has_tail_call = 1;
insn->opcode = JIT_OP_CALL_VTABLE_PTR_TAIL;
}
else
{
insn->opcode = JIT_OP_CALL_VTABLE_PTR;
}
insn->value1 = value;
/* Handle return to the caller */
return handle_return(func, signature, flags, 0,
new_args, num_args, return_value);
}
/*@
* @deftypefun jit_value_t jit_insn_call_native (jit_function_t @var{func}, const char *@var{name}, void *@var{native_func}, jit_type_t @var{signature}, jit_value_t *@var{args}, unsigned int @var{num_args}, int @var{exception_return}, int @var{flags}...
* Output an instruction that calls an external native function.
* The @var{name} is for diagnostic purposes only, and can be NULL.
* @end deftypefun
@*/
jit_value_t jit_insn_call_native
(jit_function_t func, const char *name, void *native_func,
jit_type_t signature, jit_value_t *args, unsigned int num_args, int flags)
{
jit_value_t *new_args;
jit_value_t return_value;
jit_insn_t insn;
jit_type_t return_type;
/* Bail out if there is something wrong with the parameters */
if(!_jit_function_ensure_builder(func) || !native_func || !signature)
{
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
/* We are making a native call */
flags |= JIT_CALL_NATIVE;
/* Convert the arguments to the actual parameter types */
if(num_args > 0)
{
new_args = (jit_value_t *)alloca(sizeof(jit_value_t) * num_args);
if(!convert_call_parameters(func, signature, args, num_args, new_args))
{
return 0;
}
}
else
{
new_args = args;
}
/* Set up exception frame information for the call */
if(!setup_eh_frame_for_call(func, flags))
{
return 0;
}
/* Create the instructions to push the parameters onto the stack */
if(!create_call_setup_insns
(func, 0, signature, new_args, num_args, 0, 0, &return_value, flags))
{
return 0;
}
/* Functions that call out are not leaves */
func->builder->non_leaf = 1;
/* Output the "call_external" instruction */
insn = _jit_block_add_insn(func->builder->current_block);
if(!insn)
{
return 0;
}
if((flags & JIT_CALL_TAIL) != 0)
{
func->builder->has_tail_call = 1;
insn->opcode = JIT_OP_CALL_EXTERNAL_TAIL;
}
else
{
insn->opcode = JIT_OP_CALL_EXTERNAL;
}
insn->flags = JIT_INSN_DEST_IS_NATIVE | JIT_INSN_VALUE1_IS_NAME;
insn->dest = (jit_value_t)native_func;
insn->value1 = (jit_value_t)name;
#ifdef JIT_BACKEND_INTERP
insn->flags |= JIT_INSN_VALUE2_IS_SIGNATURE;
insn->value2 = (jit_value_t)jit_type_copy(signature);
#endif
/* Handle return to the caller */
return_value = handle_return(func, signature, flags, 0,
new_args, num_args, return_value);
/* Make sure that returned byte / short values get zero / sign extended */
return_type = jit_type_normalize(return_value->type);
switch(return_type->kind)
{
case JIT_TYPE_SBYTE:
/* Force sbyte sign extension to int */
return_value = apply_unary_conversion(func, JIT_OP_TRUNC_SBYTE,
return_value, return_type);
libjit/jit/jit-insn.c view on Meta::CPAN
* _jit_unwind_pop_and_rethrow();
* }
* }
*
* The field "jbuf.catch_pc" will be set to the address of the relevant
* "catch" block just before a subroutine call that may involve exceptions.
* It will be reset to NULL after such subroutine calls.
*
* Native back ends are responsible for outputting a call to the function
* "_jit_unwind_pop_setjmp()" just before "return" instructions if the
* "has_try" flag is set on the function.
*/
static int initialize_setjmp_block(jit_function_t func)
{
#if !defined(JIT_BACKEND_INTERP)
jit_label_t start_label = jit_label_undefined;
jit_label_t end_label = jit_label_undefined;
jit_label_t code_label = jit_label_undefined;
jit_label_t rethrow_label = jit_label_undefined;
jit_type_t type;
jit_value_t args[2];
libjit/jit/jit-insn.c view on Meta::CPAN
we may need to do a native "call" to invoke the handler */
func->builder->non_leaf = 1;
/* Add a new branch instruction to branch to the finally handler */
insn = _jit_block_add_insn(func->builder->current_block);
if(!insn)
{
return 0;
}
insn->opcode = (short)JIT_OP_CALL_FINALLY;
insn->flags = JIT_INSN_DEST_IS_LABEL;
insn->dest = (jit_value_t)(*finally_label);
/* Create a new block for the following code */
return jit_insn_new_block(func);
}
/*@
* @deftypefun jit_value_t jit_insn_start_filter (jit_function_t @var{func}, jit_label_t *@var{label}, jit_type_t @var{type})
* Define the start of a filter. Filters are embedded subroutines within
* functions that are used to filter exceptions in @code{catch} blocks.
libjit/jit/jit-insn.c view on Meta::CPAN
func->builder->non_leaf = 1;
/* Add a new branch instruction to branch to the filter */
insn = _jit_block_add_insn(func->builder->current_block);
if(!insn)
{
return 0;
}
jit_value_ref(func, value);
insn->opcode = (short)JIT_OP_CALL_FILTER;
insn->flags = JIT_INSN_DEST_IS_LABEL;
insn->dest = (jit_value_t)(*label);
insn->value1 = value;
/* Create a new block, and add the filter return logic to it */
if(!jit_insn_new_block(func))
{
return 0;
}
return create_dest_note(func, JIT_OP_CALL_FILTER_RETURN, type);
}
libjit/jit/jit-internal.h view on Meta::CPAN
*/
typedef struct _jit_edge *_jit_edge_t;
struct _jit_edge
{
/* Source node of the edge */
jit_block_t src;
/* Destination node of the edge */
jit_block_t dst;
/* Edge flags */
int flags;
};
#define _JIT_EDGE_FALLTHRU 0
#define _JIT_EDGE_BRANCH 1
#define _JIT_EDGE_RETURN 2
#define _JIT_EDGE_EXCEPT 3
/*
* Internal structure of a basic block.
*/
libjit/jit/jit-internal.h view on Meta::CPAN
jit_block_t prev;
/* Edges to successor blocks in control flow graph */
_jit_edge_t *succs;
int num_succs;
/* Edges to predecessor blocks in control flow graph */
_jit_edge_t *preds;
int num_preds;
/* Control flow flags */
unsigned visited : 1;
unsigned ends_in_dead : 1;
unsigned address_of : 1;
/* Metadata */
jit_meta_t meta;
/* Code generation data */
void *address;
void *fixup_list;
libjit/jit/jit-internal.h view on Meta::CPAN
* "jit_insn_move_blocks_to_start" instruction.
*/
void _jit_value_ref_params(jit_function_t func);
/*
* Internal structure of an instruction.
*/
struct _jit_insn
{
short opcode;
short flags;
jit_value_t dest;
jit_value_t value1;
jit_value_t value2;
};
/*
* Instruction flags.
*/
#define JIT_INSN_DEST_LIVE 0x0001
#define JIT_INSN_DEST_NEXT_USE 0x0002
#define JIT_INSN_VALUE1_LIVE 0x0004
#define JIT_INSN_VALUE1_NEXT_USE 0x0008
#define JIT_INSN_VALUE2_LIVE 0x0010
#define JIT_INSN_VALUE2_NEXT_USE 0x0020
#define JIT_INSN_LIVENESS_FLAGS 0x003F
#define JIT_INSN_DEST_IS_LABEL 0x0040
#define JIT_INSN_DEST_IS_FUNCTION 0x0080
libjit/jit/jit-internal.h view on Meta::CPAN
*/
typedef struct _jit_label_info _jit_label_info_t;
struct _jit_label_info
{
/* Block the label assigned to */
jit_block_t block;
/* Next label that might belong to the same block */
jit_label_t alias;
/* Label flags */
int flags;
};
#define JIT_LABEL_ADDRESS_OF 0x0001
/*
* Information that is associated with a function for building
* the instructions and values. This structure can be discarded
* once the function has been fully compiled.
*/
libjit/jit/jit-internal.h view on Meta::CPAN
* Attach blocks to a function before a specific position.
*/
void _jit_block_attach_before(jit_block_t block, jit_block_t first, jit_block_t last);
/*
* Record the label mapping for a block.
*/
int _jit_block_record_label(jit_block_t block, jit_label_t label);
/*
* Record the label flags.
*/
int _jit_block_record_label_flags(jit_function_t func, jit_label_t label, int flags);
/*
* Add an instruction to a block.
*/
jit_insn_t _jit_block_add_insn(jit_block_t block);
/*
* Get the last instruction in a block. NULL if the block is empty.
*/
jit_insn_t _jit_block_get_last(jit_block_t block);
libjit/jit/jit-internal.h view on Meta::CPAN
jit_type_t type;
jit_nuint offset;
char *name;
};
struct _jit_type
{
unsigned int ref_count;
int kind : 19;
int abi : 8;
int is_fixed : 1;
int layout_flags : 4;
jit_nuint size;
jit_nuint alignment;
jit_type_t sub_type;
unsigned int num_components;
struct jit_component components[1];
};
struct jit_tagged_type
{
struct _jit_type type;
void *data;
libjit/jit/jit-internal.h view on Meta::CPAN
/*
* Flags for the intrinsic info.
*/
#define _JIT_INTRINSIC_FLAG_NONE 0x0000
#define _JIT_INTRINSIC_FLAG_BRANCH 0x8000
#define _JIT_INTRINSIC_FLAG_BRANCH_UNARY 0xC000
#define _JIT_INTRINSIC_FLAG_NOT 0x4000
#define _JIT_INTRINSIC_FLAG_MASK 0xC000
/*
* Additional intrinsic flags for the unary branches.
*/
#define _JIT_INTRINSIC_FLAG_IFALSE 0x0000
#define _JIT_INTRINSIC_FLAG_ITRUE 0x0001
#define _JIT_INTRINSIC_FLAG_LFALSE 0x0002
#define _JIT_INTRINSIC_FLAG_LTRUE 0x0003
/*
* Description for the implementation of an opcode by an intrinsic.
*/
typedef struct _jit_intrinsic_info _jit_intrinsic_info_t;
struct _jit_intrinsic_info
{
jit_short flags;
jit_short signature;
void *intrinsic;
};
extern _jit_intrinsic_info_t const _jit_intrinsics[JIT_OP_NUM_OPCODES];
/*
* Apply an opcode to one or two constant values.
* Returns the constant result value on success and NULL otherwise.
* NOTE: dest_type MUST be either the correct destination type for the
* opcode or a tagged type of the correct destination type.
*/
jit_value_t
_jit_opcode_apply(jit_function_t func, jit_uint opcode, jit_type_t dest_type,
jit_value_t value1, jit_value_t value2);
/*
* Extra call flags for internal use.
*/
#define JIT_CALL_NATIVE (1 << 14)
#ifdef JIT_USE_SIGNALS
/*
* Initialize the signal handlers.
*/
void _jit_signal_init(void);
libjit/jit/jit-interp-opcodes.ops view on Meta::CPAN
/*
* Opcode version. Should be increased whenever new opcodes
* are added to this list or the public list in "jit-opcode.h".
* This value is written to ELF binaries, to ensure that code
* for one version of libjit is not inadvertantly used in another.
*/
#define JIT_OPCODE_VERSION 0
/*
* Additional opcode definition flags.
*/
#define JIT_OPCODE_INTERP_ARGS_MASK 0x7E000000
#define JIT_OPCODE_NINT_ARG 0x02000000
#define JIT_OPCODE_NINT_ARG_TWO 0x04000000
#define JIT_OPCODE_CONST_LONG 0x06000000
#define JIT_OPCODE_CONST_FLOAT32 0x08000000
#define JIT_OPCODE_CONST_FLOAT64 0x0A000000
#define JIT_OPCODE_CONST_NFLOAT 0x0C000000
#define JIT_OPCODE_CALL_INDIRECT_ARGS 0x0E000000
libjit/jit/jit-live.c view on Meta::CPAN
* Compute liveness information for a basic block.
*/
static void
compute_liveness_for_block(jit_block_t block)
{
jit_insn_iter_t iter;
jit_insn_t insn;
jit_value_t dest;
jit_value_t value1;
jit_value_t value2;
int flags;
/* Scan backwards to compute the liveness flags */
jit_insn_iter_init_last(&iter, block);
while((insn = jit_insn_iter_previous(&iter)) != 0)
{
/* Skip NOP instructions, which may have arguments left
over from when the instruction was replaced, but which
are not relevant to our liveness analysis */
if(insn->opcode == JIT_OP_NOP)
{
continue;
}
/* Fetch the value parameters to this instruction */
flags = insn->flags;
if((flags & JIT_INSN_DEST_OTHER_FLAGS) == 0)
{
dest = insn->dest;
if(dest && dest->is_constant)
{
dest = 0;
}
}
else
{
dest = 0;
}
if((flags & JIT_INSN_VALUE1_OTHER_FLAGS) == 0)
{
value1 = insn->value1;
if(value1 && value1->is_constant)
{
value1 = 0;
}
}
else
{
value1 = 0;
}
if((flags & JIT_INSN_VALUE2_OTHER_FLAGS) == 0)
{
value2 = insn->value2;
if(value2 && value2->is_constant)
{
value2 = 0;
}
}
else
{
value2 = 0;
}
/* Record the liveness information in the instruction flags */
flags &= ~JIT_INSN_LIVENESS_FLAGS;
if(dest)
{
if(dest->live)
{
flags |= JIT_INSN_DEST_LIVE;
}
if(dest->next_use)
{
flags |= JIT_INSN_DEST_NEXT_USE;
}
}
if(value1)
{
if(value1->live)
{
flags |= JIT_INSN_VALUE1_LIVE;
}
if(value1->next_use)
{
flags |= JIT_INSN_VALUE1_NEXT_USE;
}
}
if(value2)
{
if(value2->live)
{
flags |= JIT_INSN_VALUE2_LIVE;
}
if(value2->next_use)
{
flags |= JIT_INSN_VALUE2_NEXT_USE;
}
}
insn->flags = (short)flags;
/* Set the destination to "not live, no next use" */
if(dest)
{
if((flags & JIT_INSN_DEST_IS_VALUE) == 0)
{
if(!(dest->next_use) && !(dest->live))
{
/* There is no next use of this value and it is not
live on exit from the block. So we can discard
the entire instruction as it will have no effect */
#ifdef _JIT_COMPILE_DEBUG
printf("liveness analysis: optimize away instruction '");
jit_dump_insn(stdout, block->func, insn);
printf("'\n");
libjit/jit/jit-live.c view on Meta::CPAN
* The propagation stops as soon as either "t" or "x" are changed (used as a
* dest in a different instruction).
*/
static int
forward_propagation(jit_block_t block)
{
int optimized;
jit_insn_iter_t iter, iter2;
jit_insn_t insn, insn2;
jit_value_t dest, value;
int flags2;
optimized = 0;
jit_insn_iter_init(&iter, block);
while((insn = jit_insn_iter_next(&iter)) != 0)
{
if(!is_copy_insn(insn))
{
continue;
}
libjit/jit/jit-live.c view on Meta::CPAN
while((insn2 = jit_insn_iter_next(&iter2)) != 0)
{
/* Skip NOP instructions, which may have arguments left
over from when the instruction was replaced, but which
are not relevant to our analysis */
if(insn->opcode == JIT_OP_NOP)
{
continue;
}
flags2 = insn2->flags;
if((flags2 & JIT_INSN_DEST_OTHER_FLAGS) == 0)
{
if((flags2 & JIT_INSN_DEST_IS_VALUE) == 0)
{
if(insn2->dest == dest || insn2->dest == value)
{
break;
}
}
else if(insn2->dest == dest)
{
#ifdef _JIT_COMPILE_DEBUG
printf("forward copy propagation: in '");
libjit/jit/jit-live.c view on Meta::CPAN
printf("' replace ");
jit_dump_value(stdout, block->func, insn2->dest, 0);
printf(" with ");
jit_dump_value(stdout, block->func, value, 0);
printf("'\n");
#endif
insn2->dest = value;
optimized = 1;
}
}
if((flags2 & JIT_INSN_VALUE1_OTHER_FLAGS) == 0)
{
if(insn2->value1 == dest)
{
#ifdef _JIT_COMPILE_DEBUG
printf("forward copy propagation: in '");
jit_dump_insn(stdout, block->func, insn2);
printf("' replace ");
jit_dump_value(stdout, block->func, insn2->value1, 0);
printf(" with ");
jit_dump_value(stdout, block->func, value, 0);
printf("'\n");
#endif
insn2->value1 = value;
optimized = 1;
}
}
if((flags2 & JIT_INSN_VALUE2_OTHER_FLAGS) == 0)
{
if(insn2->value2 == dest)
{
#ifdef _JIT_COMPILE_DEBUG
printf("forward copy propagation: in '");
jit_dump_insn(stdout, block->func, insn2);
printf("' replace ");
jit_dump_value(stdout, block->func, insn2->value2, 0);
printf(" with ");
jit_dump_value(stdout, block->func, value, 0);
libjit/jit/jit-live.c view on Meta::CPAN
* This is only allowed if "t" is used only in the instructions "i" and "j"
* and "y" is not used between "i" and "j" (but can be used after "j").
*/
static int
backward_propagation(jit_block_t block)
{
int optimized;
jit_insn_iter_t iter, iter2;
jit_insn_t insn, insn2;
jit_value_t dest, value;
int flags2;
optimized = 0;
jit_insn_iter_init_last(&iter, block);
while((insn = jit_insn_iter_previous(&iter)) != 0)
{
if(!is_copy_insn(insn))
{
continue;
}
libjit/jit/jit-live.c view on Meta::CPAN
printf("backward copy propagation: optimize away copy to itself in '");
jit_dump_insn(stdout, block->func, insn);
printf("'\n");
#endif
insn->opcode = (short)JIT_OP_NOP;
optimized = 1;
continue;
}
/* "value" is used afterwards so we cannot eliminate it here */
if((insn->flags & (JIT_INSN_VALUE1_LIVE | JIT_INSN_VALUE1_NEXT_USE)) != 0)
{
continue;
}
if(dest->is_addressable || dest->is_volatile)
{
continue;
}
if(value->is_addressable || value->is_volatile)
{
libjit/jit/jit-live.c view on Meta::CPAN
while((insn2 = jit_insn_iter_previous(&iter2)) != 0)
{
/* Skip NOP instructions, which may have arguments left
over from when the instruction was replaced, but which
are not relevant to our analysis */
if(insn->opcode == JIT_OP_NOP)
{
continue;
}
flags2 = insn2->flags;
if((flags2 & JIT_INSN_DEST_OTHER_FLAGS) == 0)
{
if(insn2->dest == dest)
{
break;
}
if(insn2->dest == value)
{
if((flags2 & JIT_INSN_DEST_IS_VALUE) == 0)
{
#ifdef _JIT_COMPILE_DEBUG
printf("backward copy propagation: in '");
jit_dump_insn(stdout, block->func, insn2);
printf("' replace ");
jit_dump_value(stdout, block->func, insn2->dest, 0);
printf(" with ");
jit_dump_value(stdout, block->func, dest, 0);
printf(" and optimize away '");
jit_dump_insn(stdout, block->func, insn);
printf("'\n");
#endif
insn->opcode = (short)JIT_OP_NOP;
insn2->dest = dest;
optimized = 1;
}
break;
}
}
if((flags2 & JIT_INSN_VALUE1_OTHER_FLAGS) == 0)
{
if(insn2->value1 == dest || insn2->value1 == value)
{
break;
}
}
if((flags2 & JIT_INSN_VALUE2_OTHER_FLAGS) == 0)
{
if(insn2->value2 == dest || insn2->value1 == value)
{
break;
}
}
}
}
return optimized;
}
#endif
/* Reset value liveness flags. */
static void
reset_value_liveness(jit_value_t value)
{
if(value)
{
if (!value->is_constant && !value->is_temporary)
{
value->live = 1;
}
else
{
value->live = 0;
}
value->next_use = 0;
}
}
/*
* Re-scan the block to reset the liveness flags on all non-temporaries
* because we need them in the original state for the next block.
*/
static void
reset_liveness_flags(jit_block_t block, int reset_all)
{
jit_insn_iter_t iter;
jit_insn_t insn;
int flags;
jit_insn_iter_init(&iter, block);
while((insn = jit_insn_iter_next(&iter)) != 0)
{
flags = insn->flags;
if((flags & JIT_INSN_DEST_OTHER_FLAGS) == 0)
{
reset_value_liveness(insn->dest);
}
if((flags & JIT_INSN_VALUE1_OTHER_FLAGS) == 0)
{
reset_value_liveness(insn->value1);
}
if((flags & JIT_INSN_VALUE2_OTHER_FLAGS) == 0)
{
reset_value_liveness(insn->value2);
}
if(reset_all)
{
flags &= ~(JIT_INSN_DEST_LIVE | JIT_INSN_DEST_NEXT_USE
|JIT_INSN_VALUE1_LIVE | JIT_INSN_VALUE1_NEXT_USE
|JIT_INSN_VALUE2_LIVE | JIT_INSN_VALUE2_NEXT_USE);
}
}
}
void _jit_function_compute_liveness(jit_function_t func)
{
jit_block_t block = func->builder->entry_block;
while(block != 0)
{
#ifdef USE_FORWARD_PROPAGATION
/* Perform forward copy propagation for the block */
forward_propagation(block);
#endif
/* Reset the liveness flags for the next block */
reset_liveness_flags(block, 0);
/* Compute the liveness flags for the block */
compute_liveness_for_block(block);
#ifdef USE_BACKWARD_PROPAGATION
/* Perform backward copy propagation for the block */
if(backward_propagation(block))
{
/* Reset the liveness flags and compute them again */
reset_liveness_flags(block, 1);
compute_liveness_for_block(block);
}
#endif
/* Move on to the next block in the function */
block = block->next;
}
}
libjit/jit/jit-objmodel.c view on Meta::CPAN
}
/*@
* @deftypefun int jitom_class_get_modifiers (jit_objmodel_t @var{model}, jitom_class_t @var{klass})
* Get the access modifiers for a particular class. The following lists
* all access modifiers, for classes, fields and methods:
*
* @table @code
* @vindex JITOM_MODIFIER_ACCESS_MASK
* @item JITOM_MODIFIER_ACCESS_MASK
* Mask to strip out just the public, private, etc access flags.
*
* @vindex JITOM_MODIFIER_PUBLIC
* @vindex JITOM_MODIFIER_PRIVATE
* @vindex JITOM_MODIFIER_PROTECTED
* @vindex JITOM_MODIFIER_PACKAGE
* @vindex JITOM_MODIFIER_PACKAGE_OR_PROTECTED
* @vindex JITOM_MODIFIER_PACKAGE_AND_PROTECTED
* @vindex JITOM_MODIFIER_OTHER1
* @vindex JITOM_MODIFIER_OTHER2
* @item JITOM_MODIFIER_PUBLIC
libjit/jit/jit-objmodel.c view on Meta::CPAN
* @vindex JITOM_MODIFIER_ABSTRACT
* @item JITOM_MODIFIER_ABSTRACT
* When used on a class, this indicates that the class contains abstract
* methods. When used on a method, this indicates that the method does
* not have any associated code in its defining class. It is not possible
* to invoke such a method with @code{jitom_method_invoke}, only
* @code{jitom_method_invoke_virtual}.
*
* @vindex JITOM_MODIFIER_LITERAL
* @item JITOM_MODIFIER_LITERAL
* A hint flag, used on fields, to indicate that the field has a constant
* value associated with it and does not occupy any real space. If the
* @code{jitom_field_load} function is used on such a field, it will load
* the constant value.
*
* @vindex JITOM_MODIFIER_CTOR
* @item JITOM_MODIFIER_CTOR
* A hint flag that indicates that the method is an instance constructor.
*
* @vindex JITOM_MODIFIER_STATIC_CTOR
* @item JITOM_MODIFIER_STATIC_CTOR
* A hint flag that indicates that the method is a static constructor.
* The object model handler is normally responsible for outputting calls to
* static constructors; the caller shouldn't need to perform any
* special handling.
*
* @vindex JITOM_MODIFIER_DTOR
* @item JITOM_MODIFIER_DTOR
* A hint flag that indicates that the method is an instance destructor.
* The class should also have the @code{JITOM_MODIFIER_DELETE} flag.
* Note: do not use this for object models that support automatic
* garbage collection and finalization.
*
* @vindex JITOM_MODIFIER_INTERFACE
* @item JITOM_MODIFIER_INTERFACE
* The class is an interface.
*
* @vindex JITOM_MODIFIER_VALUE
* @item JITOM_MODIFIER_VALUE
* Instances of this class can be stored inline on the stack.
libjit/jit/jit-objmodel.c view on Meta::CPAN
* Use @code{jit_free} to free the return array.
* @end deftypefun
@*/
jitom_method_t *jitom_class_get_methods
(jit_objmodel_t model, jitom_class_t klass, unsigned int *num)
{
return (*(model->class_get_methods))(model, klass, num);
}
/*@
* @deftypefun jit_value_t jitom_class_new (jit_objmodel_t @var{model}, jitom_class_t @var{klass}, jitom_method_t @var{ctor}, jit_function_t @var{func}, jit_value_t *@var{args}, unsigned int @var{num_args}, int @var{flags})
* Add instructions to @var{func} to create a new instance of the
* specified class. If @var{ctor} is not NULL, then it indicates a
* constructor that should be invoked with the arguments in @var{args}.
* If @var{ctor} is NULL, then memory should be allocated, but no
* constructor should be invoked. Returns a JIT value representing
* the newly allocated object. The type of the value will be the same
* as the the result from @code{jitom_class_get_type}.
* @end deftypefun
@*/
jit_value_t jitom_class_new
(jit_objmodel_t model, jitom_class_t klass,
jitom_method_t ctor, jit_function_t func,
jit_value_t *args, unsigned int num_args, int flags)
{
return (*(model->class_new))
(model, klass, ctor, func, args, num_args, flags);
}
/*@
* @deftypefun jit_value_t jitom_class_new_value (jit_objmodel_t @var{model}, jitom_class_t @var{klass}, jitom_method_t @var{ctor}, jit_function_t @var{func}, jit_value_t *@var{args}, unsigned int @var{num_args}, int @var{flags})
* Add instructions to @var{func} to create a new instance of the
* specified class, inline on the stack. If @var{ctor} is not NULL, then
* it indicates a constructor that should be invoked with the arguments
* in @var{args}. If @var{ctor} is NULL, then stack space should be
* allocated, but no constructor should be invoked. Returns a JIT
* value representing the newly allocated stack space. The type of the
* value will be the same as the the result from
* @code{jitom_class_get_value_type}.
* @end deftypefun
@*/
jit_value_t jitom_class_new_value
(jit_objmodel_t model, jitom_class_t klass,
jitom_method_t ctor, jit_function_t func,
jit_value_t *args, unsigned int num_args, int flags)
{
return (*(model->class_new_value))
(model, klass, ctor, func, args, num_args, flags);
}
/*@
* @deftypefun int jitom_class_delete (jit_objmodel_t @var{model}, jitom_class_t @var{klass}, jit_value_t @var{obj_value})
* Delete an instance of a particular class, calling the destructor if
* necessary. The @var{obj_value} may be an inline stack value,
* in which case the destructor is called, but the memory is not freed.
* Ignored if the class does not have the @code{JITOM_MODIFIER_DELETE}
* modifier.
*
libjit/jit/jit-objmodel.c view on Meta::CPAN
* Get the access modifiers for an object model method.
* @end deftypefun
@*/
int jitom_method_get_modifiers
(jit_objmodel_t model, jitom_class_t klass, jitom_method_t method)
{
return (*(model->method_get_modifiers))(model, klass, method);
}
/*@
* @deftypefun jit_value_t jitom_method_invoke (jit_objmodel_t @var{model}, jitom_class_t @var{klass}, jitom_method_t @var{method}, jit_function_t @var{func}, jit_value_t *@var{args}, unsigned int @var{num_args}, int @var{flags})
* Create instructions within @var{func} to invoke a static or
* instance method. If an instance method is virtual, then this will
* ignore the virtual property to invoke the designated method directly.
* The first element in @var{args} should be the @code{this} pointer
* for instance methods.
* @end deftypefun
@*/
jit_value_t jitom_method_invoke
(jit_objmodel_t model, jitom_class_t klass, jitom_method_t method,
jit_function_t func, jit_value_t *args, unsigned int num_args, int flags)
{
return (*(model->method_invoke))
(model, klass, method, func, args, num_args, flags);
}
/*@
* @deftypefun jit_value_t jitom_method_invoke_virtual (jit_objmodel_t @var{model}, jitom_class_t @var{klass}, jitom_method_t @var{method}, jit_function_t @var{func}, jit_value_t *@var{args}, unsigned int @var{num_args}, int @var{flags})
* Create instructions within @var{func} to invoke a virtual or interface
* method. The first element in @var{args} should be the @code{this}
* pointer for the call.
* @end deftypefun
@*/
jit_value_t jitom_method_invoke_virtual
(jit_objmodel_t model, jitom_class_t klass, jitom_method_t method,
jit_function_t func, jit_value_t *args, unsigned int num_args, int flags)
{
return (*(model->method_invoke_virtual))
(model, klass, method, func, args, num_args, flags);
}
/*
* Information that is stored for class-tagged types.
*/
typedef struct
{
jit_objmodel_t model;
jitom_class_t klass;
libjit/jit/jit-opcode-apply.c view on Meta::CPAN
{
return 0;
}
if((value1 == 0) || !value1->is_constant)
{
return 0;
}
opcode_info = &_jit_intrinsics[opcode];
if((opcode_info->flags & _JIT_INTRINSIC_FLAG_MASK) == _JIT_INTRINSIC_FLAG_NONE)
{
return apply_opcode(func, opcode_info, dest_type, value1, value2);
}
if((opcode_info->flags & _JIT_INTRINSIC_FLAG_MASK) == _JIT_INTRINSIC_FLAG_NOT)
{
jit_value_t value;
opcode = opcode_info->flags & ~_JIT_INTRINSIC_FLAG_MASK;
if(opcode >= JIT_OP_NUM_OPCODES)
{
return 0;
}
opcode_info = &(_jit_intrinsics[opcode]);
value = apply_opcode(func, opcode_info, dest_type, value1, value2);
if(value)
{
/*