remove some unneeded files

thought i removed these in previous commits, apparently not
This commit is contained in:
CasualPokePlayer 2024-05-27 22:04:44 -07:00
parent 0f603840e3
commit 2b986c17d4
26 changed files with 0 additions and 20956 deletions

View File

@ -1,2 +0,0 @@
bin
taring

View File

@ -1,99 +0,0 @@
ifdef CROSS_COMPILER
CC = $(CROSS_COMPILER)
else
ifndef CC
# default compiler
CC = gcc
endif
endif
ifndef EXTRA_CPPFLAGS
EXTRA_CPPFLAGS=
endif
ifndef EXTRA_LDFLAGS
EXTRA_LDFLAGS=
endif
CPPFLAGS = $(EXTRA_CPPFLAGS) -Isljit_src
CFLAGS += -O2 -Wall -Wextra -Wconversion -Wsign-compare -Werror
REGEX_CFLAGS += $(CFLAGS) -fshort-wchar
LDFLAGS = $(EXTRA_LDFLAGS)
BINDIR = bin
SRCDIR = sljit_src
TESTDIR = test_src
REGEXDIR = regex_src
EXAMPLEDIR = doc/tutorial
TARGET = $(BINDIR)/sljit_test $(BINDIR)/regex_test
EXAMPLE_TARGET = $(BINDIR)/func_call $(BINDIR)/first_program $(BINDIR)/branch $(BINDIR)/loop $(BINDIR)/array_access $(BINDIR)/func_call $(BINDIR)/struct_access $(BINDIR)/temp_var $(BINDIR)/brainfuck
SLJIT_HEADERS = $(SRCDIR)/sljitLir.h $(SRCDIR)/sljitConfig.h $(SRCDIR)/sljitConfigInternal.h
SLJIT_LIR_FILES = $(SRCDIR)/sljitLir.c $(SRCDIR)/sljitUtils.c \
$(SRCDIR)/allocator_src/sljitExecAllocatorCore.c $(SRCDIR)/allocator_src/sljitExecAllocatorApple.c \
$(SRCDIR)/allocator_src/sljitExecAllocatorPosix.c $(SRCDIR)/allocator_src/sljitExecAllocatorWindows.c \
$(SRCDIR)/allocator_src/sljitProtExecAllocatorNetBSD.c $(SRCDIR)/allocator_src/sljitProtExecAllocatorPosix.c \
$(SRCDIR)/allocator_src/sljitWXExecAllocatorPosix.c $(SRCDIR)/allocator_src/sljitWXExecAllocatorWindows.c \
$(SRCDIR)/sljitNativeARM_32.c $(SRCDIR)/sljitNativeARM_T2_32.c $(SRCDIR)/sljitNativeARM_64.c \
$(SRCDIR)/sljitNativeMIPS_common.c $(SRCDIR)/sljitNativeMIPS_32.c $(SRCDIR)/sljitNativeMIPS_64.c \
$(SRCDIR)/sljitNativePPC_common.c $(SRCDIR)/sljitNativePPC_32.c $(SRCDIR)/sljitNativePPC_64.c \
$(SRCDIR)/sljitNativeRISCV_common.c $(SRCDIR)/sljitNativeRISCV_32.c $(SRCDIR)/sljitNativeRISCV_64.c \
$(SRCDIR)/sljitNativeS390X.c \
$(SRCDIR)/sljitNativeX86_common.c $(SRCDIR)/sljitNativeX86_32.c $(SRCDIR)/sljitNativeX86_64.c
.PHONY: all clean examples
all: $(TARGET)
clean:
-$(RM) $(BINDIR)/*.o $(BINDIR)/sljit_test $(BINDIR)/regex_test $(EXAMPLE_TARGET)
$(BINDIR)/.keep :
mkdir -p $(BINDIR)
@touch $@
$(BINDIR)/sljitLir.o : $(BINDIR)/.keep $(SLJIT_LIR_FILES) $(SLJIT_HEADERS)
$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(SRCDIR)/sljitLir.c
$(BINDIR)/sljitMain.o : $(TESTDIR)/sljitMain.c $(BINDIR)/.keep $(SLJIT_HEADERS)
$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(TESTDIR)/sljitMain.c
$(BINDIR)/regexMain.o : $(REGEXDIR)/regexMain.c $(BINDIR)/.keep $(SLJIT_HEADERS)
$(CC) $(CPPFLAGS) $(REGEX_CFLAGS) -c -o $@ $(REGEXDIR)/regexMain.c
$(BINDIR)/regexJIT.o : $(REGEXDIR)/regexJIT.c $(BINDIR)/.keep $(SLJIT_HEADERS) $(REGEXDIR)/regexJIT.h
$(CC) $(CPPFLAGS) $(REGEX_CFLAGS) -c -o $@ $(REGEXDIR)/regexJIT.c
$(BINDIR)/sljit_test: $(BINDIR)/.keep $(BINDIR)/sljitMain.o $(TESTDIR)/sljitTest.c $(SRCDIR)/sljitLir.c $(SLJIT_LIR_FILES) $(SLJIT_HEADERS) $(TESTDIR)/sljitConfigPre.h $(TESTDIR)/sljitConfigPost.h
$(CC) $(CPPFLAGS) -DSLJIT_HAVE_CONFIG_PRE=1 -I$(TESTDIR) $(CFLAGS) $(LDFLAGS) $(BINDIR)/sljitMain.o $(TESTDIR)/sljitTest.c $(SRCDIR)/sljitLir.c -o $@ -lm -lpthread
$(BINDIR)/regex_test: $(BINDIR)/.keep $(BINDIR)/regexMain.o $(BINDIR)/regexJIT.o $(BINDIR)/sljitLir.o
$(CC) $(CFLAGS) $(LDFLAGS) $(BINDIR)/regexMain.o $(BINDIR)/regexJIT.o $(BINDIR)/sljitLir.o -o $@ -lm -lpthread
examples: $(EXAMPLE_TARGET)
$(BINDIR)/first_program: $(EXAMPLEDIR)/first_program.c $(BINDIR)/.keep $(BINDIR)/sljitLir.o
$(CC) $(CPPFLAGS) $(LDFLAGS) $(EXAMPLEDIR)/first_program.c $(BINDIR)/sljitLir.o -o $@ -lm -lpthread
$(BINDIR)/branch: $(EXAMPLEDIR)/branch.c $(BINDIR)/.keep $(BINDIR)/sljitLir.o
$(CC) $(CPPFLAGS) $(LDFLAGS) $(EXAMPLEDIR)/branch.c $(BINDIR)/sljitLir.o -o $@ -lm -lpthread
$(BINDIR)/loop: $(EXAMPLEDIR)/loop.c $(BINDIR)/.keep $(BINDIR)/sljitLir.o
$(CC) $(CPPFLAGS) $(LDFLAGS) $(EXAMPLEDIR)/loop.c $(BINDIR)/sljitLir.o -o $@ -lm -lpthread
$(BINDIR)/array_access: $(EXAMPLEDIR)/array_access.c $(BINDIR)/.keep $(BINDIR)/sljitLir.o
$(CC) $(CPPFLAGS) $(LDFLAGS) $(EXAMPLEDIR)/array_access.c $(BINDIR)/sljitLir.o -o $@ -lm -lpthread
$(BINDIR)/func_call: $(EXAMPLEDIR)/func_call.c $(BINDIR)/.keep $(BINDIR)/sljitLir.o
$(CC) $(CPPFLAGS) $(LDFLAGS) $(EXAMPLEDIR)/func_call.c $(BINDIR)/sljitLir.o -o $@ -lm -lpthread
$(BINDIR)/struct_access: $(EXAMPLEDIR)/struct_access.c $(BINDIR)/.keep $(BINDIR)/sljitLir.o
$(CC) $(CPPFLAGS) $(LDFLAGS) $(EXAMPLEDIR)/struct_access.c $(BINDIR)/sljitLir.o -o $@ -lm -lpthread
$(BINDIR)/temp_var: $(EXAMPLEDIR)/temp_var.c $(BINDIR)/.keep $(BINDIR)/sljitLir.o
$(CC) $(CPPFLAGS) $(LDFLAGS) $(EXAMPLEDIR)/temp_var.c $(BINDIR)/sljitLir.o -o $@ -lm -lpthread
$(BINDIR)/brainfuck: $(EXAMPLEDIR)/brainfuck.c $(BINDIR)/.keep $(BINDIR)/sljitLir.o
$(CC) $(CPPFLAGS) $(LDFLAGS) $(EXAMPLEDIR)/brainfuck.c $(BINDIR)/sljitLir.o -o $@ -lm -lpthread

View File

@ -1,226 +0,0 @@
The following text is a brief overview of those key
principles which are useful to know when generating code
with SLJIT. Further details can be found in sljitLir.h.
----------------------------------------------------------------
What is SLJIT?
----------------------------------------------------------------
SLJIT is a platform independent assembler which
- provides access to common CPU features
- can be easily ported to wide-spread CPU
architectures (e.g. x86, ARM, POWER, MIPS, s390x, LoongArch)
The key challenge of this project is finding a common
subset of CPU features which
- covers traditional assembly level programming
- can be translated to machine code efficiently
This aim is achieved by selecting those instructions / CPU
features which are either available on all platforms or
simulating them has a low performance overhead.
For example, some SLJIT instructions support base register
pre-update when [base+offs] memory accessing mode is used.
Although this feature is only available on ARM and POWER
CPUs, the simulation overhead is low on other CPUs.
----------------------------------------------------------------
The generic CPU model of SLJIT
----------------------------------------------------------------
The CPU has
- integer registers, which can store either an
int32_t (4 byte) or intptr_t (4 or 8 byte) value
- floating point registers, which can store either a
single (4 byte) or double (8 byte) precision value
- boolean status flags
*** Integer registers:
The most important rule is: when a source operand of
an instruction is a register, the data type of the
register must match the data type expected by an
instruction.
For example, the following code snippet
is a valid instruction sequence:
sljit_emit_op1(compiler, SLJIT_MOV32,
SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R1), 0);
// An int32_t value is loaded into SLJIT_R0
sljit_emit_op1(compiler, SLJIT_REV32,
SLJIT_R0, 0, SLJIT_R0, 0);
// the int32_t value in SLJIT_R0 is byte swapped
// and the type of the result is still int32_t
The next code snippet is not allowed:
sljit_emit_op1(compiler, SLJIT_MOV,
SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R1), 0);
// An intptr_t value is loaded into SLJIT_R0
sljit_emit_op1(compiler, SLJIT_REV32,
SLJIT_R0, 0, SLJIT_R0, 0);
// The result of the instruction is undefined.
// Even crash is possible for some instructions
// (e.g. on MIPS-64).
However, it is always allowed to overwrite a
register regardless of its previous value:
sljit_emit_op1(compiler, SLJIT_MOV,
SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R1), 0);
// An intptr_t value is loaded into SLJIT_R0
sljit_emit_op1(compiler, SLJIT_MOV32,
SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R2), 0);
// From now on SLJIT_R0 contains an int32_t
// value. The previous value is discarded.
Type conversion instructions are provided to convert an
int32_t value to an intptr_t value and vice versa. In
certain architectures these conversions are nops (no
instructions are emitted).
Memory accessing:
Registers arguments of SLJIT_MEM1 / SLJIT_MEM2 addressing
modes must contain intptr_t data.
Signed / unsigned values:
Most operations are executed in the same way regardless
the value is signed or unsigned. These operations have
only one instruction form (e.g. SLJIT_ADD / SLJIT_MUL).
Instructions where the result depends on the sign have
two forms (e.g. integer division, long multiply).
*** Floating point registers
Floating point registers can either contain a single
or double precision value. Similar to integer registers,
the data type of the value stored in a source register
must match the data type expected by the instruction.
Otherwise the result is undefined (even crash is possible).
Rounding:
Similar to standard C, floating point computation
results are rounded toward zero.
*** Boolean status flags:
Conditional branches usually depend on the value
of CPU status flags. These status flags are boolean
values and can be set by certain instructions.
To achive maximum efficiency and portability, the
following rules were introduced:
- Most instructions can freely modify these status
flags except if SLJIT_KEEP_FLAGS is passed.
- The SLJIT_KEEP_FLAGS option may have a performance
overhead, so it should only be used when necessary.
- The SLJIT_SET_E, SLJIT_SET_U, etc. options can
force an instruction to correctly set the
specified status flags. However, all other
status flags are undefined. This rule must
always be kept in mind!
- Status flags cannot be controlled directly
(there are no set/clear/invert operations)
The last two rules allows efficient mapping of status flags.
For example the arithmetic and multiply overflow flag is
mapped to the same overflow flag bit on x86. This is allowed,
since no instruction can set both of these flags. When
either of them is set by an instruction, the other can
have any value (this satisfies the "all other flags are
undefined" rule). Therefore mapping two SLJIT flags to the
same CPU flag is possible. Even though SLJIT supports
a dozen status flags, they can be efficiently mapped
to CPUs with only 4 status flags (e.g. ARM or SPARC).
----------------------------------------------------------------
Complex instructions
----------------------------------------------------------------
We noticed, that introducing complex instructions for common
tasks can improve performance. For example, compare and
branch instruction sequences can be optimized if certain
conditions apply, but these conditions depend on the target
CPU. SLJIT can do these optimizations, but it needs to
understand the "purpose" of the generated code. Static
instruction analysis has a large performance overhead
however, so we choose another approach: we introduced
complex instruction forms for certain non-atomic tasks.
SLJIT can optimize these "instructions" more efficiently
since the "purpose" is known to the compiler. These complex
instruction forms can often be assembled from other SLJIT
instructions, but we recommended to use them since the
compiler can optimize them on certain CPUs.
----------------------------------------------------------------
Generating functions
----------------------------------------------------------------
SLJIT is often used for generating function bodies which are
called from C. SLJIT provides two complex instructions for
generating function entry and return: sljit_emit_enter and
sljit_emit_return. The sljit_emit_enter also initializes the
"compiling context" which specify the current register mapping,
local space size, etc. configurations. The sljit_set_context
can also set this context without emitting any machine
instructions.
This context is important since it affects the compiler, so
the first instruction after a compiler is created must be
either sljit_emit_enter or sljit_set_context. The context can
be changed by calling sljit_emit_enter or sljit_set_context
again.
----------------------------------------------------------------
All-in-one building
----------------------------------------------------------------
Instead of using a separate library, the whole SLJIT
compiler infrastructure can be directly included:
#define SLJIT_CONFIG_STATIC 1
#include "sljitLir.c"
This approach is useful for single file compilers.
Advantages:
- Everything provided by SLJIT is available
(no need to include anything else).
- Configuring SLJIT is easy
(e.g. redefining SLJIT_MALLOC / SLJIT_FREE).
- The SLJIT compiler API is hidden from the
world which improves securtity.
- The C compiler can optimize the SLJIT code
generator (e.g. removing unused functions).
----------------------------------------------------------------
Types and macros
----------------------------------------------------------------
The sljitConfig.h contains those defines, which controls
the compiler. The beginning of sljitConfigInternal.h
lists architecture specific types and macros provided
by SLJIT. Some of these macros:
SLJIT_DEBUG : enabled by default
Enables assertions. Should be disabled in release mode.
SLJIT_VERBOSE : enabled by default
When this macro is enabled, the sljit_compiler_verbose
function can be used to dump SLJIT instructions.
Otherwise this function is not available. Should be
disabled in release mode.
SLJIT_SINGLE_THREADED : disabled by default
Single threaded programs can define this flag which
eliminates the pthread dependency.
sljit_sw, sljit_uw, etc. :
It is recommended to use these types instead of long,
intptr_t, etc. Improves readability / portability of
the code.

View File

@ -1,247 +0,0 @@
##########################
###
### Severely updated version!
### (now says "1 bottle" and
### contains no extra "0" verse)
###
##########################
### 99 Bottles of Beer ###
### coded in Brainfuck ###
### with explanations ###
##########################
#
# This Bottles of Beer program
# was written by Andrew Paczkowski
# Coder Alias: thepacz
# three_halves_plus_one@yahoo.com
#####
> 0 in the zeroth cell
+++++++>++++++++++[<+++++>-] 57 in the first cell or "9"
+++++++>++++++++++[<+++++>-] 57 in second cell or "9"
++++++++++ 10 in third cell
>+++++++++ 9 in fourth cell
##########################################
### create ASCII chars in higher cells ###
##########################################
>>++++++++[<++++>-] " "
>++++++++++++++[<+++++++>-] b
+>+++++++++++[<++++++++++>-] o
++>+++++++++++++++++++[<++++++>-] t
++>+++++++++++++++++++[<++++++>-] t
>++++++++++++[<+++++++++>-] l
+>++++++++++[<++++++++++>-] e
+>+++++++++++++++++++[<++++++>-] s
>++++++++[<++++>-] " "
+>+++++++++++[<++++++++++>-] o
++>++++++++++[<++++++++++>-] f
>++++++++[<++++>-] " "
>++++++++++++++[<+++++++>-] b
+>++++++++++[<++++++++++>-] e
+>++++++++++[<++++++++++>-] e
>+++++++++++++++++++[<++++++>-] r
>++++++++[<++++>-] " "
+>+++++++++++[<++++++++++>-] o
>+++++++++++[<++++++++++>-] n
>++++++++[<++++>-] " "
++>+++++++++++++++++++[<++++++>-] t
++++>++++++++++[<++++++++++>-] h
+>++++++++++[<++++++++++>-] e
>++++++++[<++++>-] " "
++>+++++++++++++[<+++++++++>-] w
+>++++++++++++[<++++++++>-] a
>++++++++++++[<+++++++++>-] l
>++++++++++++[<+++++++++>-] l
>+++++[<++>-] LF
++>+++++++++++++++++++[<++++++>-] t
+>++++++++++++[<++++++++>-] a
+++>+++++++++++++[<++++++++>-] k
+>++++++++++[<++++++++++>-] e
>++++++++[<++++>-] " "
+>+++++++++++[<++++++++++>-] o
>+++++++++++[<++++++++++>-] n
+>++++++++++[<++++++++++>-] e
>++++++++[<++++>-] " "
>++++++++++[<++++++++++>-] d
+>+++++++++++[<++++++++++>-] o
++>+++++++++++++[<+++++++++>-] w
>+++++++++++[<++++++++++>-] n
>++++++++[<++++>-] " "
+>++++++++++++[<++++++++>-] a
>+++++++++++[<++++++++++>-] n
>++++++++++[<++++++++++>-] d
>++++++++[<++++>-] " "
++>+++++++++++[<++++++++++>-] p
+>++++++++++++[<++++++++>-] a
+>+++++++++++++++++++[<++++++>-] s
+>+++++++++++++++++++[<++++++>-] s
>++++++++[<++++>-] " "
+>+++++++++++++[<++++++++>-] i
++>+++++++++++++++++++[<++++++>-] t
>++++++++[<++++>-] " "
+>++++++++++++[<++++++++>-] a
>+++++++++++++++++++[<++++++>-] r
+>+++++++++++[<++++++++++>-] o
>+++++++++++++[<+++++++++>-] u
>+++++++++++[<++++++++++>-] n
>++++++++++[<++++++++++>-] d
>+++++[<++>-] LF
+++++++++++++ CR
[<]>>>> go back to fourth cell
#################################
### initiate the display loop ###
#################################
[ loop
< back to cell 3
[ loop
[>]<< go to last cell and back to LF
.. output 2 newlines
[<]> go to first cell
###################################
#### begin display of characters###
###################################
#
#.>.>>>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>
#X X b o t t l e s o f b e e r
#.>.>.>.>.>.>.>.>.>.>.>.
#o n t h e w a l l N
#[<]> go to first cell
#.>.>>>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>>>>>>>>>>>>>.>
#X X b o t t l e s o f b e e r N
#.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>
#t a k e o n e d o w n a n d p a s s
#.>.>.>.>.>.>.>.>.>.
#i t a r o u n d N
#####
[<]>> go to cell 2
- subtract 1 from cell 2
< go to cell 1
########################
### display last line ##
########################
#
#.>.>>>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>
#X X b o t t l e s o f b e e r
#.>.>.>.>.>.>.>.>.>.>.
#o n t h e w a l l
#####
[<]>>>- go to cell 3/subtract 1
] end loop when cell 3 is 0
++++++++++ add 10 to cell 3
<++++++++++ back to cell 2/add 10
<- back to cell 1/subtract 1
[>]<. go to last line/carriage return
[<]> go to first line
########################
### correct last line ##
########################
#
#.>.>>>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>
#X X b o t t l e s o f b e e r
#.>.>.>.>.>.>.>.>.>.>.
#o n t h e w a l l
#####
[<]>>>>- go to cell 4/subtract 1
] end loop when cell 4 is 0
##############################################################
### By this point verses 9910 are displayed but to work ###
### with the lower numbered verses in a more readable way ###
### we initiate a new loop for verses 9{CODE} that will not ###
### use the fourth cell at all ###
##############################################################
+ add 1 to cell four (to keep it nonzero)
<-- back to cell 3/subtract 2
[ loop
[>]<< go to last cell and back to LF
.. output 2 newlines
[<]> go to first cell
###################################
#### begin display of characters###
###################################
#
#>.>>>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>
# X b o t t l e s o f b e e r
#.>.>.>.>.>.>.>.>.>.>.>.
#o n t h e w a l l N
#[<]> go to first cell
#>.>>>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>>>>>>>>>>>>>.>
# X b o t t l e s o f b e e r N
#.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>
#t a k e o n e d o w n a n d p a s s
#.>.>.>.>.>.>.>.>.>.
#i t a r o u n d N
#####
[<]>> go to cell 2
- subtract 1 from cell 2
########################
### display last line ##
########################
#
#.>>>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>
#X b o t t l e s o f b e e r
#.>.>.>.>.>.>.>.>.>.>.
#o n t h e w a l l
#####
[<]>>>- go to cell 3/subtract 1
] end loop when cell 3 is 0
+ add 1 to cell 3 to keep it nonzero
[>]<. go to last line/carriage return
[<]> go to first line
########################
### correct last line ##
########################
#
#>.>>>.>.>.>.>.>.>.>>.>.>.>.>.>.>.>.>.>
# X b o t t l e o f b e e r
#.>.>.>.>.>.>.>.>.>.>.<<<<.
#o n t h e w a l l
#####
[>]<< go to last cell and back to LF
.. output 2 newlines
[<]> go to first line
#########################
### the final verse ##
#########################
#
#>.>>>.>.>.>.>.>.>.>>.>.>.>.>.>.>.>.>.>
# X b o t t l e o f b e e r
#.>.>.>.>.>.>.>.>.>.>.>.
#o n t h e w a l l N
#[<]> go to first cell
#>.>>>.>.>.>.>.>.>.>>.>.>.>.>.>.>.>.>>>>>>>>>>>>>.>
# X b o t t l e o f b e e r N
#.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>
#t a k e o n e d o w n a n d p a s s
#.>.>.>.>.>.>.>.>.>.
#i t a r o u n d N
#[>]< go to last line
#<<<.<<.<<<.
# n o
#[<]>>>> go to fourth cell
#>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>
# b o t t l e s o f b e e r
#.>.>.>.>.>.>.>.>.>.>.>.
#o n t h e w a l l N
#####fin##

View File

@ -1,3 +0,0 @@
These files were contributed by Wen Xichang.
Copyright 2015 Wen Xichang (wenxichang@163.com). All rights reserved.

View File

@ -1,90 +0,0 @@
#include "sljitLir.h"
#include <stdio.h>
#include <stdlib.h>
typedef long (SLJIT_FUNC *func_arr_t)(long *arr, long narr);
static void SLJIT_FUNC print_num(long a)
{
printf("num = %ld\n", a);
}
/*
This example, we generate a function like this:
long func(long *array, long narray)
{
long i;
for (i = 0; i < narray; ++i)
print_num(array[i]);
return narray;
}
*/
static int array_access(long *arr, long narr)
{
void *code;
size_t len;
func_arr_t func;
struct sljit_label *loopstart;
struct sljit_jump *out;
/* Create a SLJIT compiler */
struct sljit_compiler *C = sljit_create_compiler(NULL, NULL);
sljit_emit_enter(C, 0, SLJIT_ARGS2(W, P, W), 1, 3, 0, 0, 0);
/* opt arg R S FR FS local_size */
/* S2 = 0 */
sljit_emit_op2(C, SLJIT_XOR, SLJIT_S2, 0, SLJIT_S2, 0, SLJIT_S2, 0);
/* S1 = narr */
sljit_emit_op1(C, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, narr);
/* loopstart: */
loopstart = sljit_emit_label(C);
/* S2 >= narr --> jumo out */
out = sljit_emit_cmp(C, SLJIT_GREATER_EQUAL, SLJIT_S2, 0, SLJIT_S1, 0);
/* R0 = (long *)S0[S2]; */
sljit_emit_op1(C, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM2(SLJIT_S0, SLJIT_S2), SLJIT_WORD_SHIFT);
/* print_num(R0) */
sljit_emit_icall(C, SLJIT_CALL, SLJIT_ARGS1V(W), SLJIT_IMM, SLJIT_FUNC_ADDR(print_num));
/* S2 += 1 */
sljit_emit_op2(C, SLJIT_ADD, SLJIT_S2, 0, SLJIT_S2, 0, SLJIT_IMM, 1);
/* jump loopstart */
sljit_set_label(sljit_emit_jump(C, SLJIT_JUMP), loopstart);
/* out: */
sljit_set_label(out, sljit_emit_label(C));
/* return S1 */
sljit_emit_return(C, SLJIT_MOV, SLJIT_S1, 0);
/* Generate machine code */
code = sljit_generate_code(C);
len = sljit_get_generated_code_size(C);
/* Execute code */
func = (func_arr_t)code;
printf("func return %ld\n", func(arr, narr));
/* dump_code(code, len); */
/* Clean up */
sljit_free_compiler(C);
sljit_free_code(code, NULL);
return 0;
}
int main(void)
{
long arr[8] = { 3, -10, 4, 6, 8, 12, 2000, 0 };
return array_access(arr, 8);
}

View File

@ -1,262 +0,0 @@
/*
* Brainfuck interpreter with SLJIT
*
* Copyright 2015 Wen Xichang (wenxichang@163.com). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "sljitLir.h"
#include <stdio.h>
#include <stdlib.h>
#define BF_CELL_SIZE 3000
#define BF_LOOP_LEVEL 256
static int readvalid(FILE *src)
{
int chr;
while ((chr = fgetc(src)) != EOF) {
switch (chr) {
case '+':
case '-':
case '>':
case '<':
case '.':
case ',':
case '[':
case ']':
return chr;
}
}
return chr;
}
/* reading same instruction, and count, for optimization */
/* ++++ -> '+', 4 */
static int gettoken(FILE *src, int *ntok)
{
int chr = readvalid(src);
int chr2;
int cnt = 1;
if (chr == EOF)
return EOF;
if (chr == '.' || chr == ',' || chr == '[' || chr == ']') {
*ntok = 1;
return chr;
}
while ((chr2 = readvalid(src)) == chr)
cnt++;
if (chr2 != EOF)
ungetc(chr2, src);
*ntok = cnt;
return chr;
}
/* maintaining loop matched [] */
struct loop_node_st {
struct sljit_label *loop_start;
struct sljit_jump *loop_end;
};
/* stack of loops */
static struct loop_node_st loop_stack[BF_LOOP_LEVEL];
static int loop_sp;
static int loop_push(struct sljit_label *loop_start, struct sljit_jump *loop_end)
{
if (loop_sp >= BF_LOOP_LEVEL)
return -1;
loop_stack[loop_sp].loop_start = loop_start;
loop_stack[loop_sp].loop_end = loop_end;
loop_sp++;
return 0;
}
static int loop_pop(struct sljit_label **loop_start, struct sljit_jump **loop_end)
{
if (loop_sp <= 0)
return -1;
loop_sp--;
*loop_start = loop_stack[loop_sp].loop_start;
*loop_end = loop_stack[loop_sp].loop_end;
return 0;
}
static void *SLJIT_FUNC my_alloc(size_t size, size_t n)
{
return calloc(size, n);
}
static void SLJIT_FUNC my_putchar(long c)
{
putchar(c);
}
static long SLJIT_FUNC my_getchar(void)
{
return getchar();
}
static void SLJIT_FUNC my_free(void *mem)
{
free(mem);
}
#define loop_empty() (loop_sp == 0)
/* compile bf source to a void func() */
static void *compile(FILE *src, unsigned long *lcode)
{
void *code = NULL;
int chr;
int nchr;
struct sljit_compiler *C = sljit_create_compiler(NULL, NULL);
struct sljit_jump *end;
struct sljit_label *loop_start;
struct sljit_jump *loop_end;
int SP = SLJIT_S0; /* bf SP */
int CELLS = SLJIT_S1; /* bf array */
sljit_emit_enter(C, 0, SLJIT_ARGS2V(W, W), 2, 2, 0, 0, 0);
/* opt arg R S FR FS local_size */
/* SP = 0 */
sljit_emit_op2(C, SLJIT_XOR, SP, 0, SP, 0, SP, 0);
sljit_emit_op1(C, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, BF_CELL_SIZE);
sljit_emit_op1(C, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 1);
sljit_emit_icall(C, SLJIT_CALL, SLJIT_ARGS2(P, W, W), SLJIT_IMM, SLJIT_FUNC_ADDR(my_alloc));/* calloc(BF_CELL_SIZE, 1) => R0 */
end = sljit_emit_cmp(C, SLJIT_EQUAL, SLJIT_R0, 0, SLJIT_IMM, 0); /* R0 == 0 --> jump end */
sljit_emit_op1(C, SLJIT_MOV, CELLS, 0, SLJIT_R0, 0); /* CELLS = R0 */
while ((chr = gettoken(src, &nchr)) != EOF) {
switch (chr) {
case '+':
case '-':
sljit_emit_op1(C, SLJIT_MOV_U8, SLJIT_R0, 0, SLJIT_MEM2(CELLS, SP), 0); /* R0 = CELLS[SP] */
sljit_emit_op2(C, chr == '+' ? SLJIT_ADD : SLJIT_SUB,
SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, nchr); /* R0 ?= nchr */
sljit_emit_op1(C, SLJIT_MOV_U8, SLJIT_MEM2(CELLS, SP), 0, SLJIT_R0, 0); /* CELLS[SP] = R0 */
break;
case '>':
case '<':
sljit_emit_op2(C, chr == '>' ? SLJIT_ADD : SLJIT_SUB,
SP, 0, SP, 0, SLJIT_IMM, nchr); /* SP ?= nchr */
break;
case '.':
sljit_emit_op1(C, SLJIT_MOV_U8, SLJIT_R0, 0, SLJIT_MEM2(CELLS, SP), 0); /* R0 = CELLS[SP] */
sljit_emit_icall(C, SLJIT_CALL, SLJIT_ARGS1(W, W), SLJIT_IMM, SLJIT_FUNC_ADDR(my_putchar)); /* putchar(R0) */
break;
case ',':
sljit_emit_icall(C, SLJIT_CALL, SLJIT_ARGS0(W), SLJIT_IMM, SLJIT_FUNC_ADDR(my_getchar)); /* R0 = getchar() */
sljit_emit_op1(C, SLJIT_MOV_U8, SLJIT_MEM2(CELLS, SP), 0, SLJIT_R0, 0); /* CELLS[SP] = R0 */
break;
case '[':
loop_start = sljit_emit_label(C); /* loop_start: */
sljit_emit_op1(C, SLJIT_MOV_U8, SLJIT_R0, 0, SLJIT_MEM2(CELLS, SP), 0); /* R0 = CELLS[SP] */
loop_end = sljit_emit_cmp(C, SLJIT_EQUAL, SLJIT_R0, 0, SLJIT_IMM, 0); /* IF R0 == 0 goto loop_end */
if (loop_push(loop_start, loop_end)) {
fprintf(stderr, "Too many loop level\n");
goto compile_failed;
}
break;
case ']':
if (loop_pop(&loop_start, &loop_end)) {
fprintf(stderr, "Unmatch loop ]\n");
goto compile_failed;
}
sljit_set_label(sljit_emit_jump(C, SLJIT_JUMP), loop_start); /* goto loop_start */
sljit_set_label(loop_end, sljit_emit_label(C)); /* loop_end: */
break;
}
}
if (!loop_empty()) {
fprintf(stderr, "Unmatch loop [\n");
goto compile_failed;
}
sljit_emit_op1(C, SLJIT_MOV, SLJIT_R0, 0, CELLS, 0);
sljit_emit_icall(C, SLJIT_CALL, SLJIT_ARGS1(P, P), SLJIT_IMM, SLJIT_FUNC_ADDR(my_free)); /* free(CELLS) */
sljit_set_label(end, sljit_emit_label(C));
sljit_emit_return_void(C);
code = sljit_generate_code(C);
if (lcode)
*lcode = sljit_get_generated_code_size(C);
compile_failed:
sljit_free_compiler(C);
return code;
}
/* function prototype of bf compiled code */
typedef void (*bf_entry_t)(void);
int main(int argc, char **argv)
{
void *code;
bf_entry_t entry;
FILE *fp;
if (argc < 2) {
fprintf(stderr, "Usage: %s <brainfuck program>\n", argv[0]);
return -1;
}
fp = fopen(argv[1], "rb");
if (!fp) {
perror("open");
return -1;
}
code = compile(fp, NULL);
fclose(fp);
if (!code) {
fprintf(stderr, "[Fatal]: Compile failed\n");
return -1;
}
entry = (bf_entry_t)code;
entry();
sljit_free_code(code, NULL);
return 0;
}

View File

@ -1,77 +0,0 @@
#include "sljitLir.h"
#include <stdio.h>
#include <stdlib.h>
typedef long (SLJIT_FUNC *func3_t)(long a, long b, long c);
/*
This example, we generate a function like this:
long func(long a, long b, long c)
{
if ((a & 1) == 0)
return c;
return b;
}
*/
static int branch(long a, long b, long c)
{
void *code;
unsigned long len;
func3_t func;
struct sljit_jump *ret_c;
struct sljit_jump *out;
/* Create a SLJIT compiler */
struct sljit_compiler *C = sljit_create_compiler(NULL, NULL);
/* 3 arg, 1 temp reg, 3 save reg */
sljit_emit_enter(C, 0, SLJIT_ARGS3(W, W, W, W), 1, 3, 0, 0, 0);
/* R0 = a & 1, S0 is argument a */
sljit_emit_op2(C, SLJIT_AND, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_IMM, 1);
/* if R0 == 0 then jump to ret_c, where is ret_c? we assign it later */
ret_c = sljit_emit_cmp(C, SLJIT_EQUAL, SLJIT_R0, 0, SLJIT_IMM, 0);
/* R0 = b, S1 is argument b */
sljit_emit_op1(C, SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_S1, 0);
/* jump to out */
out = sljit_emit_jump(C, SLJIT_JUMP);
/* here is the 'ret_c' should jump, we emit a label and set it to ret_c */
sljit_set_label(ret_c, sljit_emit_label(C));
/* R0 = c, S2 is argument c */
sljit_emit_op1(C, SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_S2, 0);
/* here is the 'out' should jump */
sljit_set_label(out, sljit_emit_label(C));
/* end of function */
sljit_emit_return(C, SLJIT_MOV, SLJIT_RETURN_REG, 0);
/* Generate machine code */
code = sljit_generate_code(C);
len = sljit_get_generated_code_size(C);
/* Execute code */
func = (func3_t)code;
printf("func return %ld\n", func(a, b, c));
/* dump_code(code, len); */
/* Clean up */
sljit_free_compiler(C);
sljit_free_code(code, NULL);
return 0;
}
int main()
{
return branch(4, 5, 6);
}

View File

@ -1,53 +0,0 @@
#include "sljitLir.h"
#include <stdio.h>
#include <stdlib.h>
typedef long (SLJIT_FUNC *func3_t)(long a, long b, long c);
static int add3(long a, long b, long c)
{
void *code;
unsigned long len;
func3_t func;
/* Create a SLJIT compiler */
struct sljit_compiler *C = sljit_create_compiler(NULL, NULL);
/* Start a context(function entry), have 3 arguments, discuss later */
sljit_emit_enter(C, 0, SLJIT_ARGS3(W, W, W, W), 1, 3, 0, 0, 0);
/* The first arguments of function is register SLJIT_S0, 2nd, SLJIT_S1, etc. */
/* R0 = first */
sljit_emit_op1(C, SLJIT_MOV, SLJIT_R0, 0, SLJIT_S0, 0);
/* R0 = R0 + second */
sljit_emit_op2(C, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_S1, 0);
/* R0 = R0 + third */
sljit_emit_op2(C, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_S2, 0);
/* This statement mov R0 to RETURN REG and return */
/* in fact, R0 is RETURN REG itself */
sljit_emit_return(C, SLJIT_MOV, SLJIT_R0, 0);
/* Generate machine code */
code = sljit_generate_code(C);
len = sljit_get_generated_code_size(C);
/* Execute code */
func = (func3_t)code;
printf("func return %ld\n", func(a, b, c));
/* dump_code(code, len); */
/* Clean up */
sljit_free_compiler(C);
sljit_free_code(code, NULL);
return 0;
}
int main()
{
return add3(4, 5, 6);
}

View File

@ -1,80 +0,0 @@
#include "sljitLir.h"
#include <stdio.h>
#include <stdlib.h>
typedef long (SLJIT_FUNC *func3_t)(long a, long b, long c);
static long SLJIT_FUNC print_num(long a)
{
printf("a = %ld\n", a);
return a + 1;
}
/*
This example, we generate a function like this:
long func(long a, long b, long c)
{
if ((a & 1) == 0)
return print_num(c);
return print_num(b);
}
*/
static int func_call(long a, long b, long c)
{
void *code;
unsigned long len;
func3_t func;
struct sljit_jump *out;
struct sljit_jump *print_c;
/* Create a SLJIT compiler */
struct sljit_compiler *C = sljit_create_compiler(NULL, NULL);
sljit_emit_enter(C, 0, SLJIT_ARGS3(W, W, W, W), 3, 3, 0, 0, 0);
/* a & 1 --> R0 */
sljit_emit_op2(C, SLJIT_AND, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_IMM, 1);
/* R0 == 0 --> jump print_c */
print_c = sljit_emit_cmp(C, SLJIT_EQUAL, SLJIT_R0, 0, SLJIT_IMM, 0);
/* R0 = S1; print_num(R0) */
sljit_emit_op1(C, SLJIT_MOV, SLJIT_R0, 0, SLJIT_S1, 0);
sljit_emit_icall(C, SLJIT_CALL, SLJIT_ARGS1(W, W), SLJIT_IMM, SLJIT_FUNC_ADDR(print_num));
/* jump out */
out = sljit_emit_jump(C, SLJIT_JUMP);
/* print_c: */
sljit_set_label(print_c, sljit_emit_label(C));
/* R0 = c; print_num(R0); */
sljit_emit_op1(C, SLJIT_MOV, SLJIT_R0, 0, SLJIT_S2, 0);
sljit_emit_icall(C, SLJIT_CALL, SLJIT_ARGS1(W, W), SLJIT_IMM, SLJIT_FUNC_ADDR(print_num));
/* out: */
sljit_set_label(out, sljit_emit_label(C));
sljit_emit_return(C, SLJIT_MOV, SLJIT_R0, 0);
/* Generate machine code */
code = sljit_generate_code(C);
len = sljit_get_generated_code_size(C);
/* Execute code */
func = (func3_t)code;
printf("func return %ld\n", func(a, b, c));
/* dump_code(code, len); */
/* Clean up */
sljit_free_compiler(C);
sljit_free_code(code, NULL);
return 0;
}
int main()
{
return func_call(4, 5, 6);
}

View File

@ -1,21 +0,0 @@
+++++ +++++ initialize counter (cell #0) to 10\
[ use loop to set the next four cells to 70/100/30/10\
> +++++ ++ add 7 to cell #1\
> +++++ +++++ add 10 to cell #2 \
> +++ add 3 to cell #3\
> + add 1 to cell #4\
<<<< - decrement counter (cell #0)\
]\
> ++ . print 'H'\
> + . print 'e'\
+++++ ++ . print 'l'\
. print 'l'\
+++ . print 'o'\
> ++ . print ' '\
<< +++++ +++++ +++++ . print 'W'\
> . print 'o'\
+++ . print 'r'\
----- - . print 'l'\
----- --- . print 'd'\
> + . print '!'\
> . print '\n'\

View File

@ -1,76 +0,0 @@
#include "sljitLir.h"
#include <stdio.h>
#include <stdlib.h>
typedef long (SLJIT_FUNC *func2_t)(long a, long b);
/*
This example, we generate a function like this:
long func(long a, long b)
{
long i;
long ret = 0;
for (i = 0; i < a; ++i) {
ret += b;
}
return ret;
}
*/
static int loop(long a, long b)
{
void *code;
unsigned long len;
func2_t func;
struct sljit_label *loopstart;
struct sljit_jump *out;
/* Create a SLJIT compiler */
struct sljit_compiler *C = sljit_create_compiler(NULL, NULL);
/* 2 arg, 2 temp reg, 2 saved reg */
sljit_emit_enter(C, 0, SLJIT_ARGS2(W, W, W), 2, 2, 0, 0, 0);
/* R0 = 0 */
sljit_emit_op2(C, SLJIT_XOR, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_R1, 0);
/* RET = 0 */
sljit_emit_op1(C, SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);
/* loopstart: */
loopstart = sljit_emit_label(C);
/* R1 >= a --> jump out */
out = sljit_emit_cmp(C, SLJIT_GREATER_EQUAL, SLJIT_R1, 0, SLJIT_S0, 0);
/* RET += b */
sljit_emit_op2(C, SLJIT_ADD, SLJIT_RETURN_REG, 0, SLJIT_RETURN_REG, 0, SLJIT_S1, 0);
/* R1 += 1 */
sljit_emit_op2(C, SLJIT_ADD, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1);
/* jump loopstart */
sljit_set_label(sljit_emit_jump(C, SLJIT_JUMP), loopstart);
/* out: */
sljit_set_label(out, sljit_emit_label(C));
/* return RET */
sljit_emit_return(C, SLJIT_MOV, SLJIT_RETURN_REG, 0);
/* Generate machine code */
code = sljit_generate_code(C);
len = sljit_get_generated_code_size(C);
/* Execute code */
func = (func2_t)code;
printf("func return %ld\n", func(a, b));
/* dump_code(code, len); */
/* Clean up */
sljit_free_compiler(C);
sljit_free_code(code, NULL);
return 0;
}
int main()
{
return loop(4, 5);
}

View File

@ -1,584 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>SLJIT tutorial</title>
<style type="text/css">
body {
background-color: #707070;
color: #000000;
font-family: "garamond"
}
td.main {
background-color: #ffffff;
color: #000000;
font-family: "garamond"
}
</style>
</head>
<body>
<center>
<table width="760" cellspacing=0 cellpadding=0>
<tr height=20><td width=20 class="main"></td><td width=720 class="main"></td><td width=20 class="main"></td></tr>
<tr><td width=20 class="main"></td><td width=720 class="main">
<center>
<a href="http://sourceforge.net"><img src="http://sflogo.sourceforge.net/sflogo.php?group_id=248047&amp;type=2" width="125" height="37" border="0" alt="SourceForge.net Logo" /></a>
</center>
<h1><center>SLJIT tutorial</center></h1>
<h2>Before started</h2>
<a href="">Download the tutorial sources</a><br>
<br>
SLJIT is a light-weight, platform independent JIT compiler, it's easy to
embed to your own project, as a result of its 'stack-less', SLJIT have
some limit to register usage.<br>
<br>
Here is some other JIT compiler I digged these days, place here if you have interest:<br>
<ul>
<b>Libjit/liblighning:</b> - the backend of GNU.net<br>
<b>Libgccjit:</b> - introduced in GCC5.0, its different from other JIT lib, this
one seems like constructing a C code, it use the backend of GCC.<br>
<b>AsmJIT:</b> - branch from the famous V8 project (JavaScript engine in Chrome),
support only X86/X86_64.<br>
<b>DynASM:</b> - used in LuaJIT.<br>
</ul>
<br>
AsmJIT and DynASM work in the instruction level, look like coding with ASM language,
SLJIT look like ASM also, but it hide the detail of the specific CPU, make it more
common, and become portable, libjit work on higher layer, libgccjit as I mention,
really you are constructing the C code.<br>
<h2>First program</h2>
Usage of SLJIT:
<ul>
1. #include "sljitLir.h" in the head of your C/C++ program<br>
2. Compile with sljit_src/sljitLir.c<br>
</ul>
ALL example can be compile like this:
<ul>
gcc -Wall -Ipath/to/sljit_src -DSLJIT_CONFIG_AUTO=1 \<br>
<ul><b>xxx.c</b> path/to/sljit_src/sljitLir.c -o program</ul>
</ul>
OK, let's take a look at the first program, this program we create a function that
return the sum of 3 arguments.<br>
<br>
<div style='font-family:Courier New;font-size:11px'>
<ul>
#include "sljitLir.h"<br>
<br>
#include &lt;stdio.h&gt;<br>
#include &lt;stdlib.h&gt;<br>
<br>
typedef sljit_sw (*func3_t)(sljit_sw a, sljit_sw b, sljit_sw c);<br>
<br>
static int add3(sljit_sw a, sljit_sw b, sljit_sw c)<br>
{<br>
<ul>
void *code;<br>
sljit_sw len;<br>
func3_t func;<br>
<br>
/* Create a SLJIT compiler */<br>
struct sljit_compiler *C = sljit_create_compiler(NULL, NULL);<br>
<br>
/* Start a context(function entry), has 3 arguments, discuss later */<br>
sljit_emit_enter(C, 0, SLJIT_ARGS3(W, W, W, W), 1, 3, 0, 0, 0);<br>
<br>
/* The first arguments of function is register SLJIT_S0, 2nd, SLJIT_S1, etc. */<br>
/* R0 = first */<br>
sljit_emit_op1(C, SLJIT_MOV, SLJIT_R0, 0, SLJIT_S0, 0);<br>
<br>
/* R0 = R0 + second */<br>
sljit_emit_op2(C, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_S1, 0);<br>
<br>
/* R0 = R0 + third */<br>
sljit_emit_op2(C, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_S2, 0);<br>
<br>
/* This statement mov R0 to RETURN REG and return */<br>
/* in fact, R0 is RETURN REG itself */<br>
sljit_emit_return(C, SLJIT_MOV, SLJIT_R0, 0);<br>
<br>
/* Generate machine code */<br>
code = sljit_generate_code(C);<br>
len = sljit_get_generated_code_size(C);<br>
<br>
/* Execute code */<br>
func = (func3_t)code;<br>
printf("func return %ld\n", func(a, b, c));<br>
<br>
/* dump_code(code, len); */<br>
<br>
/* Clean up */<br>
sljit_free_compiler(C);<br>
sljit_free_code(code, NULL);<br>
return 0;<br>
</ul>
}<br>
<br>
int main()<br>
{<br>
<ul>
return add3(4, 5, 6);<br>
</ul>
}<br>
</ul>
</div>
<br>
The function sljit_emit_enter create a context, save some registers to the stack,
and create a call-frame, sljit_emit_return restore the saved-register and clean-up
the frame. SLJIT is design to embed into other application, the code it generated
has to follow some basic rule.<br>
<br>
The standard called Application Binary Interface, or ABI for short, here is a
document for X86_64 CPU (<a href="http://www.x86-64.org/documentation/abi.pdf">ABI.pdf</a>),
almost all Linux/Unix follow this standard. MS windows has its own, read this for more:
<a href="http://en.wikipedia.org/wiki/X86_calling_conventions">X86_calling_conventions</a><br>
<br>
When reading the doc of sljit_emit_emter, the parameters 'saveds' and 'scratchs' make
me confused. The fact is, the registers in CPU has different functions in the ABI spec,
some of them used to pass arguments, some of them are 'callee-saved', some of them are
'temporary used', take X86_64 for example, RAX, R10, R11 are temporary used, that means,
they may be changed after a call instruction. And RBX, R12-R15 are callee-saved, those
will remain the same values after the call. The rule is, every function should save
those registers before using it.<br>
<br>
Fortunately, SLJIT have done the most for us, SLJIT_S[0-9] represent those 'safe'
registers, SLJIT_R[0-9] however, only for 'temporary used'.<br>
<br>
When a function start, SLJIT move the function arguments to S0, S1, S2 register, it
means function arguments are always 'safe' in the context; a maximum of 4
arguments is supported by SLJIT.<br>
<br>
Sljit_emit_opX is easy to understand, in SLJIT a data value is represented by 2
parameters, it can be a register, an In-memory data, or an immediate number.<br>
<br>
<table align="center" cellspacing="0">
<tr><td>First parameter</td> <td>Second parameter</td> <td>Meaning</td></tr>
<tr><td>SLJIT_R*, SLJIT_S*</td> <td>0</td> <td>Temp/saved registers</td></tr>
<tr><td>SLJIT_IMM</td> <td>Number</td> <td>Immediate number</td></tr>
<tr><td>SLJIT_MEM</td> <td>Address</td> <td>In-mem data with Absolute address</td></tr>
<tr><td>SLJIT_MEM1(r)</td> <td>Offset</td> <td>In-mem data in [R + offset]</td></tr>
<tr><td>SLJIT_MEM2(r1, r2)</td> <td>Shift(size)</td> <td>In-mem array, R1 as base address, R2 as index, <br>
Shift as size(0 for bytes, 1 for shorts, 2 for <br>
4bytes, 3 for 8bytes)</td></tr>
</table>
<h2>Branch</h2>
<div style='font-family:Courier New;font-size:11px'>
<ul>
#include "sljitLir.h"<br>
<br>
#include &lt;stdio.h&gt;<br>
#include &lt;stdlib.h&gt;<br>
<br>
typedef sljit_sw (*func3_t)(sljit_sw a, sljit_sw b, sljit_sw c);<br>
<br>
/*<br>
This example, we generate a function like this:<br>
<br>
sljit_sw func(sljit_sw a, sljit_sw b, sljit_sw c)<br>
{<br>
<ul>
if ((a & 1) == 0)<br>
<ul>
return c;<br>
</ul>
return b;<br>
</ul>
}<br>
<br>
*/<br>
static int branch(sljit_sw a, sljit_sw b, sljit_sw c)<br>
{<br>
<ul>
void *code;<br>
sljit_uw len;<br>
func3_t func;<br>
<br>
struct sljit_jump *ret_c;<br>
struct sljit_jump *out;<br>
<br>
/* Create a SLJIT compiler */<br>
struct sljit_compiler *C = sljit_create_compiler(NULL, NULL);<br>
<br>
/* 3 arg, 1 temp reg, 3 save reg */<br>
sljit_emit_enter(C, 0, SLJIT_ARGS3(W, W, W, W), 1, 3, 0, 0, 0);<br>
<br>
/* R0 = a & 1, S0 is argument a */<br>
sljit_emit_op2(C, SLJIT_AND, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_IMM, 1);<br>
<br>
/* if R0 == 0 then jump to ret_c, where is ret_c? we assign it later */<br>
ret_c = sljit_emit_cmp(C, SLJIT_EQUAL, SLJIT_R0, 0, SLJIT_IMM, 0);<br>
<br>
/* R0 = b, S1 is argument b */<br>
sljit_emit_op1(C, SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_S1, 0);<br>
<br>
/* jump to out */<br>
out = sljit_emit_jump(C, SLJIT_JUMP);<br>
<br>
/* here is the 'ret_c' should jump, we emit a label and set it to ret_c */<br>
sljit_set_label(ret_c, sljit_emit_label(C));<br>
<br>
/* R0 = c, S2 is argument c */<br>
sljit_emit_op1(C, SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_S2, 0);<br>
<br>
/* here is the 'out' should jump */<br>
sljit_set_label(out, sljit_emit_label(C));<br>
<br>
/* end of function */<br>
sljit_emit_return(C, SLJIT_MOV, SLJIT_RETURN_REG, 0);<br>
<br>
/* Generate machine code */<br>
code = sljit_generate_code(C);<br>
len = sljit_get_generated_code_size(C);<br>
<br>
/* Execute code */<br>
func = (func3_t)code;<br>
printf("func return %ld\n", func(a, b, c));<br>
<br>
/* dump_code(code, len); */<br>
<br>
/* Clean up */<br>
sljit_free_compiler(C);<br>
sljit_free_code(code, NULL);<br>
return 0;<br>
</ul>
}<br>
<br>
int main()<br>
{<br>
<ul>
return branch(4, 5, 6);<br>
</ul>
}<br>
</ul>
</div>
The key to implement branch is 'struct sljit_jump' and 'struct sljit_label',
the 'jump' contain a jump instruction, it does not know where to jump unless
you set a label to it, the 'label' is a code address just like label in ASM
language.<br>
<br>
sljit_emit_cmp/sljit_emit_jump generate a conditional/unconditional jump,
take the statement<br>
<ul>
ret_c = sljit_emit_cmp(C, SLJIT_EQUAL, SLJIT_R0, 0, SLJIT_IMM, 0);<br>
</ul>
For example, it create a jump instruction, the condition is R0 equals 0, and
the position of jumping will assign later with the sljit_set_label statement.<br>
<br>
In this example, it creates a branch like this:<br>
<ul>
<ul>
R0 = a & 1;<br>
if R0 == 0 then goto ret_c;<br>
R0 = b;<br>
goto out;<br>
</ul>
ret_c:<br>
<ul>
R0 = c;<br>
</ul>
out:<br>
<ul>
return R0;<br>
</ul>
</ul>
<br>
This is how high-level-language compiler handle branch.<br>
<br>
<h2>Loop</h2>
Loop example is similar with Branch.
<div style='font-family:Courier New;font-size:11px'>
<ul>
/*
This example, we generate a function like this:<br>
<br>
sljit_sw func(sljit_sw a, sljit_sw b)<br>
{<br>
<ul>
sljit_sw i;<br>
sljit_sw ret = 0;<br>
for (i = 0; i &lt; a; ++i) {<br>
<ul>
ret += b;<br>
</ul>
}<br>
return ret;<br>
</ul>
}<br>
*/<br>
<br>
<ul>
/* 2 arg, 2 temp reg, 2 saved reg */<br>
sljit_emit_enter(C, 0, SLJIT_ARGS2(W, W, W), 2, 2, 0, 0, 0);<br>
<br>
/* R0 = 0 */<br>
sljit_emit_op2(C, SLJIT_XOR, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_R1, 0);<br>
/* RET = 0 */<br>
sljit_emit_op1(C, SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);<br>
/* loopstart: */<br>
loopstart = sljit_emit_label(C);<br>
/* R1 &gt;= a --> jump out */<br>
out = sljit_emit_cmp(C, SLJIT_GREATER_EQUAL, SLJIT_R1, 0, SLJIT_S0, 0);<br>
/* RET += b */<br>
sljit_emit_op2(C, SLJIT_ADD, SLJIT_RETURN_REG, 0, SLJIT_RETURN_REG, 0, SLJIT_S1, 0);<br>
/* R1 += 1 */<br>
sljit_emit_op2(C, SLJIT_ADD, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1);<br>
/* jump loopstart */<br>
sljit_set_label(sljit_emit_jump(C, SLJIT_JUMP), loopstart);<br>
/* out: */<br>
sljit_set_label(out, sljit_emit_label(C));<br>
<br>
/* return RET */<br>
sljit_emit_return(C, SLJIT_MOV, SLJIT_RETURN_REG, 0);<br>
</ul>
</ul>
</div>
After this example, you are ready to construct any program that contain complex branch
and loop.<br>
<br>
Here is an interesting fact, 'xor reg, reg' is better than 'mov reg, 0', it save 2 bytes
in X86 machine.<br>
<br>
I will give only the key code in the rest of this tutorial, the full source of each
chapter can be found in the attachment.<br>
<h2>Call external function</h2>
It's easy to call an external function in SLJIT, we use sljit_emit_icall with SLJIT_CALL
operation to do so.<br>
<br>
SLJIT_CALL is use to call a function with N arguments, the number of arguments
and the return type are defined in the third parameter from sljit_emit_icall
just like it is done for SLJIT defined dunctions.<br>
the arguments for the callee function are passed from SLJIT_R0, R1 and R2. Keep in mind to maintain those 'temp registers'.<br>
<br>
Assume that we have an external function:<br>
<ul>
sljit_sw print_num(sljit_sw a);
</ul>
JIT code to call print_num(S1):
<div style='font-family:Courier New;font-size:11px'>
<ul>
/* R0 = S1; */<br>
sljit_emit_op1(C, SLJIT_MOV, SLJIT_R0, 0, SLJIT_S1, 0);<br>
/* print_num(R0) */<br>
sljit_emit_icall(C, SLJIT_CALL, SLJIT_ARGS1(W, W), SLJIT_IMM, SLJIT_FUNC_ADDR(print_num));<br>
</ul>
</div>
<br>
This code call a imm-data(address of print_num), which is linked properly when the
program loaded. There no problem in 1-time compile and execute, but when you planning
to save to file and load/execute next time, that address may not correct as you expect,
in some platform that support PIC, the address of print_num may relocate to another
address in run-time. Check this out:
<a href="http://en.wikipedia.org/wiki/Position-independent_code">PIC</a><br>
<br>
<h2>Structure access</h2>
SLJIT use SLJIT_MEM1 to implement [Reg + offset] memory access.<br>
<div style='font-family:Courier New;font-size:11px'>
<ul>
struct point_st {<br>
<ul>
sljit_sw x;<br>
int y;<br>
short z;<br>
char d;<br>
</ul>
};<br>
<br>
sljit_emit_op1(C, SLJIT_MOV_S32, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0),<br>
<ul>
SLJIT_OFFSETOF(struct point_st, y));<br>
</ul>
</ul>
</div>
In this case, SLJIT_S0 is the address of the point_st structure, offset of member 'y'
is determined in compile time, the important MOV operation always comes with a
'signed/size' postfix, like this one _S32 means 'signed 32bits integer', the postfix
list:<br>
<ul>
<b>U8</b> = unsigned byte (8 bit)<br>
<b>S8</b> = signed byte (8 bit)<br>
<b>U16</b> = unsigned half (16 bit)<br>
<b>S16</b> = signed half (16 bit)<br>
<b>U32</b> = unsigned int (32 bit)<br>
<b>S32</b> = signed int (32 bit)<br>
<b>P</b> = pointer (sljit_p) size<br>
</ul>
<h2>Array accessing</h2>
SLJIT use SLJIT_MEM2 to access arrays, like this:<br>
<div style='font-family:Courier New;font-size:11px'>
<ul>
sljit_emit_op1(C, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM2(SLJIT_S0, SLJIT_S2),<br>
<ul>
SLJIT_WORD_SHIFT);
</ul>
</ul>
</div>
This statement generates a code like this:<br>
<ul>
WORD S0[];<br>
R0 = S0[S2]<br>
</ul>
<br>
The array S0 is declared to be WORD (using SLJIT_WORD_SHIFT), which will be sizeof(sljit_sw) in length.
SLJIT use a 'shift' for length representation: (0 for single byte, 1 for 2
bytes, 2 for 4 bytes, 3 for 8bytes).<br>
<br>
The file array_access.c demonstrate a array-print example, should be easy
to understand.<br>
<h2>Local variables</h2>
SLJIT provide SLJIT_MEM1(SLJIT_SP) to access the reserved space in
sljit_emit_enter's last parameter.<br>
In this example we have to pass the address to print_arr, local variable
is the only choice.<br>
<div style='font-family:Courier New;font-size:11px'>
<ul>
/* reserved space in stack for sljit_sw arr[3] */<br>
sljit_emit_enter(C, 0, SLJIT_ARGS3(W, W, W, W), 2, 3, 0, 0, 3 * sizeof(sljit_sw));<br>
/* opt arg R S FR FS local_size */<br>
<br>
/* arr[0] = S0, SLJIT_SP is the init address of local var */<br>
sljit_emit_op1(C, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_S0, 0);<br>
/* arr[1] = S1 */<br>
sljit_emit_op1(C, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 1 * sizeof(sljit_sw), SLJIT_S1, 0);<br>
/* arr[2] = S2 */<br>
sljit_emit_op1(C, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 2 * sizeof(sljit_sw), SLJIT_S2, 0);<br>
<br>
/* R0 = arr; in fact SLJIT_SP is the address of arr, but can't do so in SLJIT */<br>
sljit_get_local_base(C, SLJIT_R0, 0, 0); /* get the address of local variables */<br>
sljit_emit_op1(C, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 3); /* R1 = 3; */<br>
sljit_emit_icall(C, SLJIT_CALL, SLJIT_ARGS2(W, P, W), SLJIT_IMM, SLJIT_FUNC_ADDR(print_arr));<br>
sljit_emit_return(C, SLJIT_MOV, SLJIT_R0, 0);<br>
</ul>
</div>
<br>
SLJIT_SP can only be used in SLJIT_MEM1(SLJIT_SP). In this case, SP is the
address of 'arr', but we cannot assign it to Reg using SLJIT_MOV opr,
instead, we use sljit_get_local_base, which load the address and offset of
local variable to the target.<br>
<h2>Brainfuck compiler</h2>
Ok, the basic usage of SLJIT ends here, with more detail, I suggest reading
sljitLir.h directly, having fun hacking the wonder of SLJIT!<br>
<br>
The brainfuck machine introduction can be found here:
<a href="http://en.wikipedia.org/wiki/Brainfuck">Brainfuck</a><br>
<br>
<h2>Extra</h2>
1. Dump_code function<br>
SLJIT didn't provide disassemble functional, this is a simple function to do this(X86 only)<br>
<br>
<div style='font-family:Courier New;font-size:11px'>
<ul>
static void dump_code(void *code, sljit_uw len)<br>
{<br>
<ul>
FILE *fp = fopen("/tmp/slj_dump", "wb");<br>
if (!fp)<br>
<ul>
return;<br>
</ul>
fwrite(code, len, 1, fp);<br>
fclose(fp);<br>
</ul>
#if defined(SLJIT_CONFIG_X86_64)<br>
<ul>
system("objdump -b binary -m l1om -D /tmp/slj_dump");<br>
</ul>
#elif defined(SLJIT_CONFIG_X86_32)<br>
<ul>
system("objdump -b binary -m i386 -D /tmp/slj_dump");<br>
</ul>
#endif<br>
}
</ul>
</div>
The branch example disassembling:<br>
<br>
0000000000000000 &lt;.data&gt;:<br>
<ul>
<table>
<tr><td>0:</td><td>53</td><td>push %rbx</td></tr>
<tr><td>1:</td><td>41 57</td><td>push %r15</td></tr>
<tr><td>3:</td><td>41 56</td><td>push %r14</td></tr>
<tr><td>5:</td><td>48 8b df</td><td>mov %rdi,%rbx</td></tr>
<tr><td>8:</td><td>4c 8b fe</td><td>mov %rsi,%r15</td></tr>
<tr><td>b:</td><td>4c 8b f2</td><td>mov %rdx,%r14</td></tr>
<tr><td>e:</td><td>48 83 ec 10</td><td>sub $0x10,%rsp</td></tr>
<tr><td>12:</td><td>48 89 d8</td><td>mov %rbx,%rax</td></tr>
<tr><td>15:</td><td>48 83 e0 01</td><td>and $0x1,%rax</td></tr>
<tr><td>19:</td><td>48 83 f8 00</td><td>cmp $0x0,%rax</td></tr>
<tr><td>1d:</td><td>74 05</td><td>je 0x24</td></tr>
<tr><td>1f:</td><td>4c 89 f8</td><td>mov %r15,%rax</td></tr>
<tr><td>22:</td><td>eb 03</td><td>jmp 0x27</td></tr>
<tr><td>24:</td><td>4c 89 f0</td><td>mov %r14,%rax</td></tr>
<tr><td>27:</td><td>48 83 c4 10</td><td>add $0x10,%rsp</td></tr>
<tr><td>2b:</td><td>41 5e</td><td>pop %r14</td></tr>
<tr><td>2d:</td><td>41 5f</td><td>pop %r15</td></tr>
<tr><td>2f:</td><td>5b</td><td>pop %rbx</td></tr>
<tr><td>30:</td><td>c3</td><td>retq</td></tr>
</table>
</ul>
<br>
with GCC -O2<br>
0000000000000000 &lt;func&gt;:<br>
<ul>
<table>
<tr><td>0:</td><td>48 89 d0</td><td>mov %rdx,%rax</td></tr>
<tr><td>3:</td><td>83 e7 01</td><td>and $0x1,%edi</td></tr>
<tr><td>6:</td><td>48 0f 45 c6</td><td>cmovne %rsi,%rax</td></tr>
<tr><td>a:</td><td>c3</td><td>retq</td></tr>
</table>
</ul>
<br>
Err... Ok, the optimization here may be weak, or, optimization there is crazy... :-)<br>
<table width="100%" cellspacing=0 cellpadding=0>
<tr><td align=right>Originally by wenxichang#163.com, 2015.5.10</td></tr>
</table>
</td><td width=20 class="main"></td></tr>
<tr height=20><td width=20 class="main"></td><td width=720 class="main"></td><td width=20 class="main"></td></tr>
</table>
</center>
</body>
</html>

View File

@ -1,88 +0,0 @@
#include "sljitLir.h"
#include <stdio.h>
#include <stdlib.h>
struct point_st {
long x;
int y;
short z;
char d;
};
typedef long (SLJIT_FUNC *point_func_t)(struct point_st *point);
static long SLJIT_FUNC print_num(long a)
{
printf("a = %ld\n", a);
return a + 1;
}
/*
This example, we generate a function like this:
long func(struct point_st *point)
{
print_num(point->x);
print_num(point->y);
print_num(point->z);
print_num(point->d);
return point->x;
}
*/
static int struct_access()
{
void *code;
unsigned long len;
point_func_t func;
struct point_st point = {
-5, -20, 5, 'a'
};
/* Create a SLJIT compiler */
struct sljit_compiler *C = sljit_create_compiler(NULL, NULL);
sljit_emit_enter(C, 0, SLJIT_ARGS1(W, W), 1, 1, 0, 0, 0);
/* opt arg R S FR FS local_size */
/* S0->x --> R0; print_num(R0) */
sljit_emit_op1(C, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), SLJIT_OFFSETOF(struct point_st, x));
sljit_emit_icall(C, SLJIT_CALL, SLJIT_ARGS1(W, P), SLJIT_IMM, SLJIT_FUNC_ADDR(print_num));
/* S0->y --> R0; print_num(R0) */
sljit_emit_op1(C, SLJIT_MOV_S32, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), SLJIT_OFFSETOF(struct point_st, y));
sljit_emit_icall(C, SLJIT_CALL, SLJIT_ARGS1(W, P), SLJIT_IMM, SLJIT_FUNC_ADDR(print_num));
/* S0->z --> R0; print_num(R0) */
sljit_emit_op1(C, SLJIT_MOV_S16, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), SLJIT_OFFSETOF(struct point_st, z));
sljit_emit_icall(C, SLJIT_CALL, SLJIT_ARGS1(W, P), SLJIT_IMM, SLJIT_FUNC_ADDR(print_num));
/* S0->d --> R0; print_num(R0) */
sljit_emit_op1(C, SLJIT_MOV_S8, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), SLJIT_OFFSETOF(struct point_st, d));
sljit_emit_icall(C, SLJIT_CALL, SLJIT_ARGS1(W, P), SLJIT_IMM, SLJIT_FUNC_ADDR(print_num));
/* return S0->x */
sljit_emit_return(C, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), SLJIT_OFFSETOF(struct point_st, x));
/* Generate machine code */
code = sljit_generate_code(C);
len = sljit_get_generated_code_size(C);
/* Execute code */
func = (point_func_t)code;
printf("func return %ld\n", func(&point));
/* dump_code(code, len); */
/* Clean up */
sljit_free_compiler(C);
sljit_free_code(code, NULL);
return 0;
}
int main()
{
return struct_access();
}

View File

@ -1,74 +0,0 @@
#include "sljitLir.h"
#include <stdio.h>
#include <stdlib.h>
typedef long (SLJIT_FUNC *func3_t)(long a, long b, long c);
static long SLJIT_FUNC print_arr(long *a, long n)
{
long i;
long sum = 0;
for (i = 0; i < n; ++i) {
sum += a[i];
printf("arr[%ld] = %ld\n", i, a[i]);
}
return sum;
}
/*
This example, we generate a function like this:
long func(long a, long b, long c)
{
long arr[3] = { a, b, c };
return print_arr(arr, 3);
}
*/
static int temp_var(long a, long b, long c)
{
void *code;
unsigned long len;
func3_t func;
/* Create a SLJIT compiler */
struct sljit_compiler *C = sljit_create_compiler(NULL, NULL);
/* reserved space in stack for long arr[3] */
sljit_emit_enter(C, 0, SLJIT_ARGS3(W, W, W, W), 2, 3, 0, 0, 3 * sizeof(long));
/* opt arg R S FR FS local_size */
/* arr[0] = S0, SLJIT_SP is the init address of local var */
sljit_emit_op1(C, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_S0, 0);
/* arr[1] = S1 */
sljit_emit_op1(C, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 1 * sizeof(long), SLJIT_S1, 0);
/* arr[2] = S2 */
sljit_emit_op1(C, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 2 * sizeof(long), SLJIT_S2, 0);
/* R0 = arr; in fact SLJIT_SP is the address of arr, but can't do so in SLJIT */
sljit_get_local_base(C, SLJIT_R0, 0, 0); /* get the address of local variables */
sljit_emit_op1(C, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 3); /* R1 = 3; */
sljit_emit_icall(C, SLJIT_CALL, SLJIT_ARGS2(W, P, W), SLJIT_IMM, SLJIT_FUNC_ADDR(print_arr));
sljit_emit_return(C, SLJIT_MOV, SLJIT_R0, 0);
/* Generate machine code */
code = sljit_generate_code(C);
len = sljit_get_generated_code_size(C);
/* Execute code */
func = (func3_t)code;
printf("func return %ld\n", func(a, b, c));
/* dump_code(code, len); */
/* Clean up */
sljit_free_compiler(C);
sljit_free_code(code, NULL);
return 0;
}
int main()
{
return temp_var(7, 8, 9);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,106 +0,0 @@
/*
* Stack-less Just-In-Time compiler
*
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _REGEX_JIT_H_
#define _REGEX_JIT_H_
#ifdef __cplusplus
extern "C" {
#endif
/* Character type config. */
#define REGEX_USE_8BIT_CHARS
#ifdef REGEX_USE_8BIT_CHARS
typedef char regex_char_t;
#else
typedef wchar_t regex_char_t;
#endif
/* Error codes. */
#define REGEX_NO_ERROR 0
#define REGEX_MEMORY_ERROR 1
#define REGEX_INVALID_REGEX 2
/* Note: large, nested {a,b} iterations can blow up the memory consumption
a{n,m} is replaced by aa...aaa?a?a?a?a? (n >= 0, m > 0)
\__n__/\____m___/
a{n,} is replaced by aa...aaa+ (n > 0)
\_n-1_/
*/
/* The value returned by regex_compile. Can be used for multiple matching. */
struct regex_machine;
/* A matching state. */
struct regex_match;
/* Note: REGEX_MATCH_BEGIN and REGEX_MATCH_END does not change the parsing
(Hence ^ and $ are parsed normally).
Force matching to start from begining of the string (same as ^). */
#define REGEX_MATCH_BEGIN 0x01
/* Force matching to continue until the last character (same as $). */
#define REGEX_MATCH_END 0x02
/* Changes . to [^\r\n]
Note: [...] and [^...] are NOT affected at all (as other regex engines do). */
#define REGEX_NEWLINE 0x04
/* Non greedy matching. In case of Thompson (non-recursive) algorithm,
it (usually) does not have a significant speed gain. */
#define REGEX_MATCH_NON_GREEDY 0x08
/* Verbose. This define can be commented out, which disables all verbose features. */
#define REGEX_MATCH_VERBOSE 0x10
/* If error occures the function returns NULL, and the error code returned in error variable.
You can pass NULL to error if you don't care about the error code.
The re_flags argument contains the default REGEX_MATCH flags. See above. */
struct regex_machine* regex_compile(const regex_char_t *regex_string, int length, int re_flags, int *error);
void regex_free_machine(struct regex_machine *machine);
/* Create and init match structure for a given machine. */
struct regex_match* regex_begin_match(struct regex_machine *machine);
void regex_reset_match(struct regex_match *match);
void regex_free_match(struct regex_match *match);
/* Pattern matching.
regex_continue_match does not support REGEX_MATCH_VERBOSE flag. */
void regex_continue_match(struct regex_match *match, const regex_char_t *input_string, int length);
int regex_get_result(struct regex_match *match, int *end, int *id);
/* Returns true, if the best match has already found. */
int regex_is_match_finished(struct regex_match *match);
/* Only exists if VERBOSE is defined in regexJIT.c
Do both sanity check and verbose.
(The latter only if REGEX_MATCH_VERBOSE was passed to regex_compile) */
void regex_continue_match_debug(struct regex_match *match, const regex_char_t *input_string, int length);
/* Misc. */
const char* regex_get_platform_name(void);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif

View File

@ -1,335 +0,0 @@
/*
* Stack-less Just-In-Time compiler
*
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* Must be the first one. Must not depend on any other include. */
#include "sljitLir.h"
#include "regexJIT.h"
#include <stdio.h>
#if defined _WIN32 || defined _WIN64
#define COLOR_RED
#define COLOR_GREEN
#define COLOR_ARCH
#define COLOR_DEFAULT
#else
#define COLOR_RED "\33[31m"
#define COLOR_GREEN "\33[32m"
#define COLOR_ARCH "\33[33m"
#define COLOR_DEFAULT "\33[0m"
#endif
#ifdef REGEX_USE_8BIT_CHARS
#define S(str) str
#else
#define S(str) L##str
#endif
#ifdef REGEX_MATCH_VERBOSE
void verbose_test(regex_char_t *pattern, regex_char_t *string)
{
int error;
regex_char_t *ptr;
struct regex_machine* machine;
struct regex_match* match;
int begin, end, id;
ptr = pattern;
while (*ptr)
ptr++;
printf("Start test '%s' matches to '%s'\n", pattern, string);
machine = regex_compile(pattern, (int)(ptr - pattern), REGEX_MATCH_VERBOSE | REGEX_NEWLINE, &error);
if (error) {
printf("WARNING: Error %d\n", error);
return;
}
if (!machine) {
printf("ERROR: machine must be exists. Report this bug, please\n");
return;
}
match = regex_begin_match(machine);
if (!match) {
printf("WARNING: Not enough memory for matching\n");
regex_free_machine(machine);
return;
}
ptr = string;
while (*ptr)
ptr++;
regex_continue_match_debug(match, string, (int)(ptr - string));
begin = regex_get_result(match, &end, &id);
printf("Math returns: %3d->%3d [%3d]\n", begin, end, id);
regex_free_match(match);
regex_free_machine(machine);
}
#endif
struct test_case {
int begin; /* Expected begin. */
int end; /* Expected end. */
int id; /* Expected id. */
int finished; /* -1 : don't care, 0 : false, 1 : true. */
int flags; /* REGEX_MATCH_* */
const regex_char_t *pattern; /* NULL : use the previous pattern. */
const regex_char_t *string; /* NULL : end of tests. */
};
static void run_tests(struct test_case* test, int verbose, int silent)
{
int error;
const regex_char_t *ptr;
struct regex_machine* machine = NULL;
struct regex_match* match;
int begin, end, id, finished;
int success = 0, fail = 0;
if (!verbose && !silent)
printf("Pass -v to enable verbose, -s to disable this hint.\n\n");
for ( ; test->string ; test++) {
if (verbose)
printf("test: '%s' '%s': ", test->pattern ? test->pattern : "[[REUSE]]", test->string);
fail++;
if (test->pattern) {
if (machine)
regex_free_machine(machine);
ptr = test->pattern;
while (*ptr)
ptr++;
machine = regex_compile(test->pattern, (int)(ptr - test->pattern), test->flags, &error);
if (error) {
if (!verbose)
printf("test: '%s' '%s': ", test->pattern ? test->pattern : "[[REUSE]]", test->string);
printf("ABORT: Error %d\n", error);
return;
}
if (!machine) {
if (!verbose)
printf("test: '%s' '%s': ", test->pattern ? test->pattern : "[[REUSE]]", test->string);
printf("ABORT: machine must be exists. Report this bug, please\n");
return;
}
}
else if (test->flags != 0) {
if (!verbose)
printf("test: '%s' '%s': ", test->pattern ? test->pattern : "[[REUSE]]", test->string);
printf("ABORT: flag must be 0 if no pattern\n");
return;
}
ptr = test->string;
while (*ptr)
ptr++;
match = regex_begin_match(machine);
#ifdef REGEX_MATCH_VERBOSE
if (!match) {
if (!verbose)
printf("test: '%s' '%s': ", test->pattern ? test->pattern : "[[REUSE]]", test->string);
printf("ABORT: Not enough memory for matching\n");
regex_free_machine(machine);
return;
}
regex_continue_match_debug(match, test->string, (int)(ptr - test->string));
begin = regex_get_result(match, &end, &id);
finished = regex_is_match_finished(match);
if (begin != test->begin || end != test->end || id != test->id) {
if (!verbose)
printf("test: '%s' '%s': ", test->pattern ? test->pattern : "[[REUSE]]", test->string);
printf("FAIL A: begin: %d != %d || end: %d != %d || id: %d != %d\n", test->begin, begin, test->end, end, test->id, id);
continue;
}
if (test->finished != -1 && test->finished != !!finished) {
if (!verbose)
printf("test: '%s' '%s': ", test->pattern ? test->pattern : "[[REUSE]]", test->string);
printf("FAIL A: finish check\n");
continue;
}
#endif
regex_reset_match(match);
regex_continue_match(match, test->string, (int)(ptr - test->string));
begin = regex_get_result(match, &end, &id);
finished = regex_is_match_finished(match);
regex_free_match(match);
if (begin != test->begin || end != test->end || id != test->id) {
if (!verbose)
printf("test: '%s' '%s': ", test->pattern ? test->pattern : "[[REUSE]]", test->string);
printf("FAIL B: begin: %d != %d || end: %d != %d || id: %d != %d\n", test->begin, begin, test->end, end, test->id, id);
continue;
}
if (test->finished != -1 && test->finished != !!finished) {
if (!verbose)
printf("test: '%s' '%s': ", test->pattern ? test->pattern : "[[REUSE]]", test->string);
printf("FAIL B: finish check\n");
continue;
}
if (verbose)
printf("SUCCESS\n");
fail--;
success++;
}
if (machine)
regex_free_machine(machine);
printf("REGEX tests: ");
if (fail == 0)
printf("all tests " COLOR_GREEN "PASSED" COLOR_DEFAULT " ");
else
printf(COLOR_RED "%d" COLOR_DEFAULT " (" COLOR_RED "%d%%" COLOR_DEFAULT ") tests failed ", fail, fail * 100 / (success + fail));
printf("on " COLOR_ARCH "%s" COLOR_DEFAULT "\n", regex_get_platform_name());
}
/* Testing. */
static struct test_case tests[] = {
{ 3, 7, 0, -1, 0,
S("text"), S("is textile") },
{ 0, 10, 0, -1, 0,
S("^(ab|c)*?d+(es)?"), S("abccabddeses") },
{ -1, 0, 0, 1, 0,
S("^a+"), S("saaaa") },
{ 3, 6, 0, 0, 0,
S("(a+|b+)$"), S("saabbb") },
{ 1, 6, 0, 0, 0,
S("(a+|b+){,2}$"), S("saabbb") },
{ 1, 6, 0, 1, 0,
S("(abcde|bc)(a+*|(b|c){2}+){0}"), S("babcdeaaaaaaaa") },
{ 1, 6, 0, 1, 0,
S("(abc(aa)?|(cab+){2})"), S("cabcaa") },
{ -1, 0, 0, 1, 0,
S("^(abc(aa)?|(cab+){2})$"), S("cabcaa") },
{ 0, 3, 1, -1, 0,
S("^(ab{001!})?c"), S("abcde") },
{ 1, 15, 2, -1, 0,
S("(c?(a|bb{2!}){2,3}()+d){2,3}"), S("ccabbadbbadcaadcaad") },
{ 2, 9, 0, -1, 0,
NULL, S("cacaadaadaa") },
{ -1, 0, 0, -1, REGEX_MATCH_BEGIN,
S("(((ab?c|d{1})))"), S("ad") },
{ 0, 9, 3, -1, REGEX_MATCH_BEGIN,
S("^((a{1!}|b{2!}|c{3!}){3,6}d)+"), S("cabadbacddaa") },
{ 1, 6, 0, 0, REGEX_MATCH_END,
S("(a+(bb|cc?)?){4,}"), S("maaaac") },
{ 3, 12, 1, 0, REGEX_MATCH_END,
S("(x+x+{02,03}(x+|{1!})){03,06}$"), S("aaaxxxxxxxxx") },
{ 1, 2, 3, -1, 0,
S("((c{1!})?|x+{2!}|{3!})(a|c)"), S("scs") },
{ 1, 4, 2, 1, 0,
NULL, S("sxxaxxxaccacca") },
{ 0, 2, 1, 1, 0,
NULL, S("ccdcdcdddddcdccccd") },
{ 0, 3, 0, -1, REGEX_MATCH_NON_GREEDY,
S("^a+a+a+"), S("aaaaaa") },
{ 2, 5, 0, -1, REGEX_MATCH_NON_GREEDY,
S("a+a+a+"), S("bbaaaaaa") },
{ 1, 4, 0, 1, 0,
S("baa|a+"), S("sbaaaaaa") },
{ 0, 6, 0, 1, 0,
S("baaa|baa|sbaaaa"), S("sbaaaaa") },
{ 1, 4, 0, 1, REGEX_MATCH_NON_GREEDY,
S("baaa|baa"), S("xbaaa") },
{ 0, 0, 3, 1, 0,
S("{3!}"), S("xx") },
{ 0, 0, 1, 1, 0,
S("{1!}(a{2!})*"), S("xx") },
{ 0, 2, 2, 0, 0,
NULL, S("aa") },
{ 0, 0, 1, 1, REGEX_MATCH_NON_GREEDY,
S("{1!}(a{2!})*"), S("aaxx") },
{ 4, 12, 0, 1, 0,
S("(.[]-]){3}[^]-]{2}"), S("ax-xs-[][]lmn") },
{ 3, 7, 1, 1, 0,
S("([ABC]|[abc]{1!}){3,5}"), S("AbSAabbx") },
{ 0, 8, 3, 0, 0,
S("^[x\\-y[\\]]+([[\\]]{3!})*$"), S("x-y[-][]") },
{ 0, 9, 0, 0, 0,
NULL, S("x-y[-][]x") },
{ 2, 8, 0, 1, 0,
S("<(/{1!})?[^>]+>"), S(" <html></html> ") },
{ 2, 9, 1, 1, 0,
NULL, S(" </html><html> ") },
{ 2, 9, 0, 1, 0,
S("[A-Z0-9a-z]+"), S("[(Iden9aA)]") },
{ 1, 4, 0, 1, 0,
S("[^x-y]+[a-c_]{2,3}"), S("x_a_y") },
{ 4, 11, 0, 0, 0,
NULL, S("ssaymmaa_ccl") },
{ 3, 6, 0, 1, REGEX_NEWLINE,
S(".a[^k]"), S("\na\nxa\ns") },
{ 0, 2, 0, 1, REGEX_NEWLINE,
S("^a+"), S("aa\n") },
{ 1, 4, 0, 1, 0 /* =REGEX_NEWLINE */,
NULL, S("\naaa\n") },
{ 2, 3, 0, 1, 0 /* =REGEX_NEWLINE */,
NULL, S("\n\na\n") },
{ 0, 2, 0, 1, REGEX_NEWLINE,
S("a+$"), S("aa\n") },
{ 0, 3, 0, 0, 0 /* =REGEX_NEWLINE */,
NULL, S("aaa") },
{ 2, 4, 1, 1, REGEX_NEWLINE,
S("^a(a{1!})*$"), S("\n\naa\n\n") },
{ 0, 1, 0, 0, 0 /* REGEX_NEWLINE */,
NULL, S("a") },
{ -1, 0, 0, -1, 0 /* REGEX_NEWLINE */,
NULL, S("ab\nba") },
{ -1, 0, 0, 0, 0,
NULL, NULL }
};
int main(int argc, char* argv[])
{
int has_arg = (argc >= 2 && argv[1][0] == '-' && argv[1][2] == '\0');
/* verbose_test("a((b)((c|d))|)c|"); */
/* verbose_test("Xa{009,0010}Xb{,7}Xc{5,}Xd{,}Xe{1,}Xf{,1}X"); */
/* verbose_test("{3!}({3})({0!}){,"); */
/* verbose_test("(s(ab){2,4}t){2,}*S(a*(b)(c()|)d+){3,4}{0,0}*M"); */
/* verbose_test("^a({2!})*b+(a|{1!}b)+d$"); */
/* verbose_test("((a|b|c)*(xy)+)+", "asbcxyxy"); */
run_tests(tests, has_arg && argv[1][1] == 'v', has_arg && argv[1][1] == 's');
#if !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)
sljit_free_unused_memory_exec();
#endif /* !SLJIT_CONFIG_UNSUPPORTED */
return 0;
}

View File

@ -1,33 +0,0 @@
/*
* Stack-less Just-In-Time compiler
*
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SLJIT_CONFIG_POST_H_
#define SLJIT_CONFIG_POST_H_
void *sljit_test_malloc_exec(sljit_uw size, void *exec_allocator_data);
void sljit_test_free_code(void* code, void *exec_allocator_data);
#endif /* SLJIT_CONFIG_POST_H_ */

View File

@ -1,35 +0,0 @@
/*
* Stack-less Just-In-Time compiler
*
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SLJIT_CONFIG_PRE_H_
#define SLJIT_CONFIG_PRE_H_
#define SLJIT_HAVE_CONFIG_POST 1
#define SLJIT_MALLOC_EXEC(size, exec_allocator_data) sljit_test_malloc_exec((size), (exec_allocator_data))
#define SLJIT_FREE_EXEC(ptr, exec_allocator_data) sljit_test_free_code((ptr), (exec_allocator_data))
#endif /* SLJIT_CONFIG_PRE_H_ */

View File

@ -1,84 +0,0 @@
/*
* Stack-less Just-In-Time compiler
*
* Copyright 2009-2010 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "sljitLir.h"
#include <stdio.h>
#include <stdlib.h>
int sljit_test(int argc, char* argv[]);
union executable_code {
void* code;
sljit_sw (SLJIT_FUNC *func)(sljit_sw* a);
};
typedef union executable_code executable_code;
static void error(const char* str)
{
printf("An error occured: %s\n", str);
exit(-1);
}
void devel(void)
{
executable_code code;
struct sljit_compiler *compiler = sljit_create_compiler(NULL, NULL);
sljit_sw buf[4];
if (!compiler)
error("Not enough of memory");
buf[0] = 5;
buf[1] = 12;
buf[2] = 0;
buf[3] = 0;
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
sljit_compiler_verbose(compiler, stdout);
#endif
sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, P), 4, 5, 4, 0, 2 * sizeof(sljit_sw));
sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0);
code.code = sljit_generate_code(compiler);
sljit_free_compiler(compiler);
printf("Code at: %p\n", (void*)SLJIT_FUNC_ADDR(code.code));
printf("Function returned with %ld\n", (long)code.func((sljit_sw*)buf));
printf("buf[0] = %ld\n", (long)buf[0]);
printf("buf[1] = %ld\n", (long)buf[1]);
printf("buf[2] = %ld\n", (long)buf[2]);
printf("buf[3] = %ld\n", (long)buf[3]);
sljit_free_code(code.code, NULL);
}
int main(int argc, char* argv[])
{
/* devel(); */
return sljit_test(argc, argv);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,361 +0,0 @@
/*
* Stack-less Just-In-Time compiler
*
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
static void test_serialize1(void)
{
/* Test serializing large code. */
executable_code code;
struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL);
struct sljit_label *label;
struct sljit_jump *jump1;
struct sljit_jump *jump2;
struct sljit_jump *mov_addr;
sljit_sw executable_offset;
sljit_uw const_addr;
sljit_uw jump_addr;
sljit_uw label_addr;
sljit_sw buf[3];
sljit_uw* serialized_buffer;
sljit_uw serialized_size;
sljit_s32 i;
if (verbose)
printf("Run test_serialize1\n");
FAILED(!compiler, "cannot create compiler\n");
buf[0] = 0;
buf[1] = 0;
buf[2] = 0;
sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), 3, 2, 0, 0, 0);
jump1 = sljit_emit_jump(compiler, SLJIT_JUMP);
label = sljit_emit_label(compiler);
jump2 = sljit_emit_jump(compiler, SLJIT_JUMP);
sljit_set_label(jump2, label);
label = sljit_emit_label(compiler);
sljit_set_label(jump1, label);
mov_addr = sljit_emit_mov_addr(compiler, SLJIT_R2, 0);
/* buf[0] */
sljit_emit_const(compiler, SLJIT_MEM1(SLJIT_S0), 0, -1234);
sljit_emit_ijump(compiler, SLJIT_JUMP, SLJIT_R2, 0);
sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_IMM, -1234);
label = sljit_emit_label(compiler);
sljit_set_label(mov_addr, label);
sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 7);
for (i = 0; i < 4096; i++)
sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 3);
/* buf[1] */
sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R1, 0);
/* buf[2] */
sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_IMM, -56789);
jump1 = sljit_emit_jump(compiler, SLJIT_JUMP | SLJIT_REWRITABLE_JUMP);
label = sljit_emit_label(compiler);
sljit_set_label(jump1, label);
sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_IMM, 0);
sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_IMM, 0);
label = sljit_emit_label(compiler);
serialized_buffer = sljit_serialize_compiler(compiler, 0, &serialized_size);
FAILED(!serialized_buffer, "cannot serialize compiler\n");
sljit_free_compiler(compiler);
/* Continue code generation. */
compiler = sljit_deserialize_compiler(serialized_buffer, serialized_size, 0, NULL, NULL);
SLJIT_FREE(serialized_buffer, NULL);
FAILED(!compiler, "cannot deserialize compiler\n");
jump1 = sljit_emit_jump(compiler, SLJIT_JUMP);
label = sljit_emit_label(compiler);
jump2 = sljit_emit_jump(compiler, SLJIT_JUMP);
sljit_set_label(jump2, label);
label = sljit_emit_label(compiler);
sljit_set_label(jump1, label);
sljit_emit_return_void(compiler);
code.code = sljit_generate_code(compiler);
CHECK(compiler);
executable_offset = sljit_get_executable_offset(compiler);
const_addr = sljit_get_const_addr(sljit_get_first_const(compiler));
jump1 = sljit_get_next_jump(sljit_get_next_jump(sljit_get_next_jump(sljit_get_first_jump(compiler))));
SLJIT_ASSERT(!sljit_jump_is_mov_addr(jump1));
jump_addr = sljit_get_jump_addr(jump1);
label = sljit_get_next_label(sljit_get_next_label(sljit_get_next_label(sljit_get_next_label(sljit_get_first_label(compiler)))));
label_addr = sljit_get_label_addr(label);
sljit_free_compiler(compiler);
sljit_set_const(const_addr, 87654, executable_offset);
sljit_set_jump_addr(jump_addr, label_addr, executable_offset);
code.func1((sljit_sw)&buf);
FAILED(buf[0] != 87654, "test_serialize1 case 1 failed\n");
FAILED(buf[1] != 7 + 4096 * 3, "test_serialize1 case 2 failed\n");
FAILED(buf[2] != -56789, "test_serialize1 case 3 failed\n");
sljit_free_code(code.code, NULL);
successful_tests++;
}
static void test_serialize2(void)
{
/* Test serializing jumps/labels. */
executable_code code;
struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL);
struct sljit_label *label;
struct sljit_jump *jump;
sljit_uw* serialized_buffer;
sljit_uw serialized_size;
sljit_sw buf[3];
if (verbose)
printf("Run test_serialize2\n");
FAILED(!compiler, "cannot create compiler\n");
buf[0] = 0;
buf[1] = 0;
buf[2] = 0;
sljit_emit_enter(compiler, 0, SLJIT_ARGS2V(P, W), 3, 3, 0, 0, 32);
sljit_emit_cmp(compiler, SLJIT_EQUAL, SLJIT_S1, 0, SLJIT_IMM, 37);
sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0);
sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R0), 0);
sljit_emit_label(compiler);
/* buf[0] */
sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_IMM, -5678);
sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 16, SLJIT_IMM, -8765);
sljit_emit_mov_addr(compiler, SLJIT_S2, 0);
sljit_emit_cmp(compiler, SLJIT_NOT_EQUAL, SLJIT_S2, 0, SLJIT_IMM, 0);
sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0);
sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R0), 0);
serialized_buffer = sljit_serialize_compiler(compiler, 0, &serialized_size);
FAILED(!serialized_buffer, "cannot serialize compiler\n");
sljit_free_compiler(compiler);
/* Continue code generation. */
compiler = sljit_deserialize_compiler(serialized_buffer, serialized_size, 0, NULL, NULL);
SLJIT_FREE(serialized_buffer, NULL);
FAILED(!compiler, "cannot deserialize compiler\n");
label = sljit_emit_label(compiler);
SLJIT_ASSERT(sljit_get_label_index(label) == 1);
jump = sljit_get_first_jump(compiler);
SLJIT_ASSERT(!sljit_jump_is_mov_addr(jump));
SLJIT_ASSERT(!sljit_jump_has_label(jump) && !sljit_jump_has_target(jump));
sljit_set_label(jump, label);
/* buf[1] */
sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_IMM, 3456);
label = sljit_get_first_label(compiler);
SLJIT_ASSERT(sljit_get_label_index(label) == 0);
jump = sljit_emit_jump(compiler, SLJIT_JUMP);
sljit_set_label(jump, label);
sljit_emit_label(compiler);
serialized_buffer = sljit_serialize_compiler(compiler, 0, &serialized_size);
FAILED(!serialized_buffer, "cannot serialize compiler\n");
sljit_free_compiler(compiler);
/* Continue code generation. */
compiler = sljit_deserialize_compiler(serialized_buffer, serialized_size, 0, NULL, NULL);
SLJIT_FREE(serialized_buffer, NULL);
FAILED(!compiler, "cannot deserialize compiler\n");
sljit_emit_return_void(compiler);
jump = sljit_get_first_jump(compiler);
SLJIT_ASSERT(sljit_jump_has_label(jump) && !sljit_jump_has_target(jump));
jump = sljit_get_next_jump(jump);
SLJIT_ASSERT(sljit_jump_is_mov_addr(jump));
jump = sljit_get_next_jump(jump);
SLJIT_ASSERT(!sljit_jump_is_mov_addr(jump));
SLJIT_ASSERT(!sljit_jump_has_label(jump) && !sljit_jump_has_target(jump));
label = sljit_emit_label(compiler);
sljit_set_label(jump, label);
/* buf[2] */
sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_MEM1(SLJIT_SP), 16);
sljit_emit_ijump(compiler, SLJIT_JUMP, SLJIT_S2, 0);
label = sljit_get_first_label(compiler);
SLJIT_ASSERT(sljit_get_label_index(label) == 0);
label = sljit_get_next_label(label);
SLJIT_ASSERT(sljit_get_label_index(label) == 1);
label = sljit_get_next_label(label);
SLJIT_ASSERT(sljit_get_label_index(label) == 2);
jump = sljit_get_next_jump(sljit_get_first_jump(compiler));
SLJIT_ASSERT(sljit_jump_is_mov_addr(jump));
sljit_set_label(jump, label);
label = sljit_get_next_label(label);
SLJIT_ASSERT(sljit_get_label_index(label) == 3);
SLJIT_ASSERT(sljit_get_next_label(label) == NULL);
code.code = sljit_generate_code(compiler);
CHECK(compiler);
sljit_free_compiler(compiler);
code.func2((sljit_sw)&buf, 37);
FAILED(buf[0] != -5678, "test_serialize2 case 1 failed\n");
FAILED(buf[1] != 3456, "test_serialize2 case 2 failed\n");
FAILED(buf[2] != -8765, "test_serialize2 case 3 failed\n");
sljit_free_code(code.code, NULL);
successful_tests++;
}
static void test_serialize3_f1(sljit_sw a, sljit_sw b, sljit_sw c)
{
sljit_sw* ptr = (sljit_sw*)c;
ptr[0] = a;
ptr[1] = b;
}
static void test_serialize3(void)
{
/* Test serializing consts/calls. */
executable_code code;
struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL);
struct sljit_label *label;
struct sljit_jump *jump;
struct sljit_const *const_;
sljit_sw executable_offset;
sljit_uw* serialized_buffer;
sljit_uw serialized_size;
sljit_sw buf[6];
sljit_sw label_addr;
sljit_s32 i;
if (verbose)
printf("Run test_serialize3\n");
FAILED(!compiler, "cannot create compiler\n");
for (i = 0; i < 6 ; i++)
buf[i] = 0;
sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), 3, 3, 0, 0, 32);
sljit_emit_mov_addr(compiler, SLJIT_R0, 0);
sljit_emit_const(compiler, SLJIT_R1, 0, 0);
sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_S0, 0);
jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS3V(W, W, W));
/* buf[0], buf[1] */
sljit_set_target(jump, SLJIT_FUNC_UADDR(test_serialize3_f1));
serialized_buffer = sljit_serialize_compiler(compiler, 0, &serialized_size);
FAILED(!serialized_buffer, "cannot serialize compiler\n");
sljit_free_compiler(compiler);
/* Continue code generation. */
compiler = sljit_deserialize_compiler(serialized_buffer, serialized_size, 0, NULL, NULL);
SLJIT_FREE(serialized_buffer, NULL);
FAILED(!compiler, "cannot deserialize compiler\n");
sljit_emit_mov_addr(compiler, SLJIT_R0, 0);
sljit_emit_const(compiler, SLJIT_R1, 0, 0);
sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R2, 0, SLJIT_S0, 0, SLJIT_IMM, 2 * sizeof(sljit_sw));
jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS3V(W, W, W));
/* buf[2], buf[3] */
sljit_set_target(jump, SLJIT_FUNC_UADDR(test_serialize3_f1));
serialized_buffer = sljit_serialize_compiler(compiler, 0, &serialized_size);
FAILED(!serialized_buffer, "cannot serialize compiler\n");
sljit_free_compiler(compiler);
/* Continue code generation. */
compiler = sljit_deserialize_compiler(serialized_buffer, serialized_size, 0, NULL, NULL);
SLJIT_FREE(serialized_buffer, NULL);
FAILED(!compiler, "cannot deserialize compiler\n");
sljit_emit_mov_addr(compiler, SLJIT_R0, 0);
sljit_emit_const(compiler, SLJIT_R1, 0, 0);
sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R2, 0, SLJIT_S0, 0, SLJIT_IMM, 4 * sizeof(sljit_sw));
jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS3V(W, W, W));
/* buf[4], buf[5] */
sljit_set_target(jump, SLJIT_FUNC_UADDR(test_serialize3_f1));
sljit_emit_return_void(compiler);
SLJIT_ASSERT(sljit_get_first_label(compiler) == NULL);
label = sljit_emit_label(compiler);
SLJIT_ASSERT(sljit_get_label_index(label) == 0);
jump = sljit_get_first_jump(compiler);
SLJIT_ASSERT(sljit_jump_is_mov_addr(jump));
sljit_set_label(jump, label);
jump = sljit_get_next_jump(jump);
SLJIT_ASSERT(!sljit_jump_is_mov_addr(jump));
SLJIT_ASSERT(sljit_jump_has_target(jump) && sljit_jump_get_target(jump) == SLJIT_FUNC_UADDR(test_serialize3_f1));
jump = sljit_get_next_jump(jump);
SLJIT_ASSERT(sljit_jump_is_mov_addr(jump));
sljit_set_label(jump, label);
jump = sljit_get_next_jump(jump);
SLJIT_ASSERT(!sljit_jump_is_mov_addr(jump));
SLJIT_ASSERT(sljit_jump_has_target(jump) && sljit_jump_get_target(jump) == SLJIT_FUNC_UADDR(test_serialize3_f1));
jump = sljit_get_next_jump(jump);
SLJIT_ASSERT(sljit_jump_is_mov_addr(jump));
sljit_set_label(jump, label);
jump = sljit_get_next_jump(jump);
SLJIT_ASSERT(sljit_jump_has_target(jump) && sljit_jump_get_target(jump) == SLJIT_FUNC_UADDR(test_serialize3_f1));
SLJIT_ASSERT(sljit_get_next_jump(jump) == NULL);
code.code = sljit_generate_code(compiler);
CHECK(compiler);
executable_offset = sljit_get_executable_offset(compiler);
const_ = sljit_get_first_const(compiler);
sljit_set_const(sljit_get_const_addr(const_), 0x5678, executable_offset);
const_ = sljit_get_next_const(const_);
sljit_set_const(sljit_get_const_addr(const_), -0x9876, executable_offset);
const_ = sljit_get_next_const(const_);
sljit_set_const(sljit_get_const_addr(const_), 0x2345, executable_offset);
SLJIT_ASSERT(sljit_get_next_const(const_) == NULL);
label_addr = (sljit_sw)sljit_get_label_addr(label);
sljit_free_compiler(compiler);
code.func1((sljit_sw)&buf);
FAILED(buf[0] != label_addr, "test_serialize3 case 1 failed\n");
FAILED(buf[1] != 0x5678, "test_serialize3 case 2 failed\n");
FAILED(buf[2] != label_addr, "test_serialize3 case 3 failed\n");
FAILED(buf[3] != -0x9876, "test_serialize3 case 4 failed\n");
FAILED(buf[4] != label_addr, "test_serialize3 case 5 failed\n");
FAILED(buf[5] != 0x2345, "test_serialize3 case 6 failed\n");
sljit_free_code(code.code, NULL);
successful_tests++;
}

File diff suppressed because it is too large Load Diff