overview.txt revision 1.1.1.1.2.2 1 1.1.1.1.2.2 skrll The following text is a brief overview of those key
2 1.1.1.1.2.2 skrll principles which are useful to know when generating code
3 1.1.1.1.2.2 skrll with SLJIT. Further details can be found in sljitLir.h.
4 1.1.1.1.2.2 skrll
5 1.1.1.1.2.2 skrll ----------------------------------------------------------------
6 1.1.1.1.2.2 skrll What is SLJIT?
7 1.1.1.1.2.2 skrll ----------------------------------------------------------------
8 1.1.1.1.2.2 skrll
9 1.1.1.1.2.2 skrll SLJIT is a platform independent assembler which
10 1.1.1.1.2.2 skrll - provides access to common CPU features
11 1.1.1.1.2.2 skrll - can be easily ported to wide-spread CPU
12 1.1.1.1.2.2 skrll architectures (e.g. x86, ARM, POWER, MIPS, SPARC)
13 1.1.1.1.2.2 skrll
14 1.1.1.1.2.2 skrll The key challenge of this project is finding a common
15 1.1.1.1.2.2 skrll subset of CPU features which
16 1.1.1.1.2.2 skrll - covers traditional assembly level programming
17 1.1.1.1.2.2 skrll - can be translated to machine code efficiently
18 1.1.1.1.2.2 skrll
19 1.1.1.1.2.2 skrll This aim is achieved by selecting those instructions / CPU
20 1.1.1.1.2.2 skrll features which are either available on all platforms or
21 1.1.1.1.2.2 skrll simulating them has a low performance overhead.
22 1.1.1.1.2.2 skrll
23 1.1.1.1.2.2 skrll For example, some SLJIT instructions support base register
24 1.1.1.1.2.2 skrll pre-update when [base+offs] memory accessing mode is used.
25 1.1.1.1.2.2 skrll Although this feature is only available on ARM and POWER
26 1.1.1.1.2.2 skrll CPUs, the simulation overhead is low on other CPUs.
27 1.1.1.1.2.2 skrll
28 1.1.1.1.2.2 skrll ----------------------------------------------------------------
29 1.1.1.1.2.2 skrll The generic CPU model of SLJIT
30 1.1.1.1.2.2 skrll ----------------------------------------------------------------
31 1.1.1.1.2.2 skrll
32 1.1.1.1.2.2 skrll The CPU has
33 1.1.1.1.2.2 skrll - integer registers, which can store either an
34 1.1.1.1.2.2 skrll int32_t (4 byte) or intptr_t (4 or 8 byte) value
35 1.1.1.1.2.2 skrll - floating point registers, which can store either a
36 1.1.1.1.2.2 skrll single (4 byte) or double (8 byte) precision value
37 1.1.1.1.2.2 skrll - boolean status flags
38 1.1.1.1.2.2 skrll
39 1.1.1.1.2.2 skrll *** Integer registers:
40 1.1.1.1.2.2 skrll
41 1.1.1.1.2.2 skrll The most important rule is: when a source operand of
42 1.1.1.1.2.2 skrll an instruction is a register, the data type of the
43 1.1.1.1.2.2 skrll register must match the data type expected by an
44 1.1.1.1.2.2 skrll instruction.
45 1.1.1.1.2.2 skrll
46 1.1.1.1.2.2 skrll For example, the following code snippet
47 1.1.1.1.2.2 skrll is a valid instruction sequence:
48 1.1.1.1.2.2 skrll
49 1.1.1.1.2.2 skrll sljit_emit_op1(compiler, SLJIT_IMOV,
50 1.1.1.1.2.2 skrll SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R1), 0);
51 1.1.1.1.2.2 skrll // An int32_t value is loaded into SLJIT_R0
52 1.1.1.1.2.2 skrll sljit_emit_op1(compiler, SLJIT_INEG,
53 1.1.1.1.2.2 skrll SLJIT_R0, 0, SLJIT_R0, 0);
54 1.1.1.1.2.2 skrll // the int32_t value in SLJIT_R0 is negated
55 1.1.1.1.2.2 skrll // and the type of the result is still int32_t
56 1.1.1.1.2.2 skrll
57 1.1.1.1.2.2 skrll The next code snippet is not allowed:
58 1.1.1.1.2.2 skrll
59 1.1.1.1.2.2 skrll sljit_emit_op1(compiler, SLJIT_MOV,
60 1.1.1.1.2.2 skrll SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R1), 0);
61 1.1.1.1.2.2 skrll // An intptr_t value is loaded into SLJIT_R0
62 1.1.1.1.2.2 skrll sljit_emit_op1(compiler, SLJIT_INEG,
63 1.1.1.1.2.2 skrll SLJIT_R0, 0, SLJIT_R0, 0);
64 1.1.1.1.2.2 skrll // The result of SLJIT_INEG instruction
65 1.1.1.1.2.2 skrll // is undefined. Even crash is possible
66 1.1.1.1.2.2 skrll // (e.g. on MIPS-64).
67 1.1.1.1.2.2 skrll
68 1.1.1.1.2.2 skrll However, it is always allowed to overwrite a
69 1.1.1.1.2.2 skrll register regardless its previous value:
70 1.1.1.1.2.2 skrll
71 1.1.1.1.2.2 skrll sljit_emit_op1(compiler, SLJIT_MOV,
72 1.1.1.1.2.2 skrll SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R1), 0);
73 1.1.1.1.2.2 skrll // An intptr_t value is loaded into SLJIT_R0
74 1.1.1.1.2.2 skrll sljit_emit_op1(compiler, SLJIT_IMOV,
75 1.1.1.1.2.2 skrll SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R2), 0);
76 1.1.1.1.2.2 skrll // From now on SLJIT_R0 contains an int32_t
77 1.1.1.1.2.2 skrll // value. The previous value is discarded.
78 1.1.1.1.2.2 skrll
79 1.1.1.1.2.2 skrll Type conversion instructions are provided to convert an
80 1.1.1.1.2.2 skrll int32_t value to an intptr_t value and vice versa. In
81 1.1.1.1.2.2 skrll certain architectures these conversions are nops (no
82 1.1.1.1.2.2 skrll instructions are emitted).
83 1.1.1.1.2.2 skrll
84 1.1.1.1.2.2 skrll Memory accessing:
85 1.1.1.1.2.2 skrll
86 1.1.1.1.2.2 skrll Registers arguments of SLJIT_MEM1 / SLJIT_MEM2 addressing
87 1.1.1.1.2.2 skrll modes must contain intptr_t data.
88 1.1.1.1.2.2 skrll
89 1.1.1.1.2.2 skrll Signed / unsigned values:
90 1.1.1.1.2.2 skrll
91 1.1.1.1.2.2 skrll Most operations are executed in the same way regardless
92 1.1.1.1.2.2 skrll the value is signed or unsigned. These operations have
93 1.1.1.1.2.2 skrll only one instruction form (e.g. SLJIT_ADD / SLJIT_MUL).
94 1.1.1.1.2.2 skrll Instructions where the result depends on the sign have
95 1.1.1.1.2.2 skrll two forms (e.g. integer division, long multiply).
96 1.1.1.1.2.2 skrll
97 1.1.1.1.2.2 skrll *** Floating point registers
98 1.1.1.1.2.2 skrll
99 1.1.1.1.2.2 skrll Floating point registers can either contain a single
100 1.1.1.1.2.2 skrll or double precision value. Similar to integer registers,
101 1.1.1.1.2.2 skrll the data type of the value stored in a source register
102 1.1.1.1.2.2 skrll must match the data type expected by the instruction.
103 1.1.1.1.2.2 skrll Otherwise the result is undefined (even crash is possible).
104 1.1.1.1.2.2 skrll
105 1.1.1.1.2.2 skrll Rounding:
106 1.1.1.1.2.2 skrll
107 1.1.1.1.2.2 skrll Similar to standard C, floating point computation
108 1.1.1.1.2.2 skrll results are rounded toward zero.
109 1.1.1.1.2.2 skrll
110 1.1.1.1.2.2 skrll *** Boolean status flags:
111 1.1.1.1.2.2 skrll
112 1.1.1.1.2.2 skrll Conditional branches usually depend on the value
113 1.1.1.1.2.2 skrll of CPU status flags. These status flags are boolean
114 1.1.1.1.2.2 skrll values and can be set by certain instructions.
115 1.1.1.1.2.2 skrll
116 1.1.1.1.2.2 skrll To achive maximum efficiency and portability, the
117 1.1.1.1.2.2 skrll following rules were introduced:
118 1.1.1.1.2.2 skrll - Most instructions can freely modify these status
119 1.1.1.1.2.2 skrll flags except if SLJIT_KEEP_FLAGS is passed.
120 1.1.1.1.2.2 skrll - The SLJIT_KEEP_FLAGS option may have a performance
121 1.1.1.1.2.2 skrll overhead, so it should only be used when necessary.
122 1.1.1.1.2.2 skrll - The SLJIT_SET_E, SLJIT_SET_U, etc. options can
123 1.1.1.1.2.2 skrll force an instruction to correctly set the
124 1.1.1.1.2.2 skrll specified status flags. However, all other
125 1.1.1.1.2.2 skrll status flags are undefined. This rule must
126 1.1.1.1.2.2 skrll always be kept in mind!
127 1.1.1.1.2.2 skrll - Status flags cannot be controlled directly
128 1.1.1.1.2.2 skrll (there are no set/clear/invert operations)
129 1.1.1.1.2.2 skrll
130 1.1.1.1.2.2 skrll The last two rules allows efficent mapping of status flags.
131 1.1.1.1.2.2 skrll For example the arithmetic and multiply overflow flag is
132 1.1.1.1.2.2 skrll mapped to the same overflow flag bit on x86. This is allowed,
133 1.1.1.1.2.2 skrll since no instruction can set both of these flags. When
134 1.1.1.1.2.2 skrll either of them is set by an instruction, the other can
135 1.1.1.1.2.2 skrll have any value (this satisfies the "all other flags are
136 1.1.1.1.2.2 skrll undefined" rule). Therefore mapping two SLJIT flags to the
137 1.1.1.1.2.2 skrll same CPU flag is possible. Even though SLJIT supports
138 1.1.1.1.2.2 skrll a dozen status flags, they can be efficiently mapped
139 1.1.1.1.2.2 skrll to CPUs with only 4 status flags (e.g. ARM or SPARC).
140 1.1.1.1.2.2 skrll
141 1.1.1.1.2.2 skrll ----------------------------------------------------------------
142 1.1.1.1.2.2 skrll Complex instructions
143 1.1.1.1.2.2 skrll ----------------------------------------------------------------
144 1.1.1.1.2.2 skrll
145 1.1.1.1.2.2 skrll We noticed, that introducing complex instructions for common
146 1.1.1.1.2.2 skrll tasks can improve performance. For example, compare and
147 1.1.1.1.2.2 skrll branch instruction sequences can be optimized if certain
148 1.1.1.1.2.2 skrll conditions apply, but these conditions depend on the target
149 1.1.1.1.2.2 skrll CPU. SLJIT can do these optimizations, but it needs to
150 1.1.1.1.2.2 skrll understand the "purpose" of the generated code. Static
151 1.1.1.1.2.2 skrll instruction analysis has a large performance overhead
152 1.1.1.1.2.2 skrll however, so we choose another approach: we introduced
153 1.1.1.1.2.2 skrll complex instruction forms for certain non-atomic tasks.
154 1.1.1.1.2.2 skrll SLJIT can optimize these "instructions" more efficiently
155 1.1.1.1.2.2 skrll since the "purpose" is known to the compiler. These complex
156 1.1.1.1.2.2 skrll instruction forms can often be assembled from other SLJIT
157 1.1.1.1.2.2 skrll instructions, but we recommended to use them since the
158 1.1.1.1.2.2 skrll compiler can optimize them on certain CPUs.
159 1.1.1.1.2.2 skrll
160 1.1.1.1.2.2 skrll ----------------------------------------------------------------
161 1.1.1.1.2.2 skrll Generating functions
162 1.1.1.1.2.2 skrll ----------------------------------------------------------------
163 1.1.1.1.2.2 skrll
164 1.1.1.1.2.2 skrll SLJIT is often used for generating function bodies which are
165 1.1.1.1.2.2 skrll called from C. SLJIT provides two complex instructions for
166 1.1.1.1.2.2 skrll generating function entry and return: sljit_emit_enter and
167 1.1.1.1.2.2 skrll sljit_emit_return. The sljit_emit_enter also initializes the
168 1.1.1.1.2.2 skrll "compiling context" which specify the current register mapping,
169 1.1.1.1.2.2 skrll local space size, etc. configurations. The sljit_set_context
170 1.1.1.1.2.2 skrll can also set this context without emitting any machine
171 1.1.1.1.2.2 skrll instructions.
172 1.1.1.1.2.2 skrll
173 1.1.1.1.2.2 skrll This context is important since it affects the compiler, so
174 1.1.1.1.2.2 skrll the first instruction after a compiler is created must be
175 1.1.1.1.2.2 skrll either sljit_emit_enter or sljit_set_context. The context can
176 1.1.1.1.2.2 skrll be changed by calling sljit_emit_enter or sljit_set_context
177 1.1.1.1.2.2 skrll again.
178 1.1.1.1.2.2 skrll
179 1.1.1.1.2.2 skrll ----------------------------------------------------------------
180 1.1.1.1.2.2 skrll All-in-one building
181 1.1.1.1.2.2 skrll ----------------------------------------------------------------
182 1.1.1.1.2.2 skrll
183 1.1.1.1.2.2 skrll Instead of using a separate library, the whole SLJIT
184 1.1.1.1.2.2 skrll compiler infrastructure can be directly included:
185 1.1.1.1.2.2 skrll
186 1.1.1.1.2.2 skrll #define SLJIT_CONFIG_STATIC 1
187 1.1.1.1.2.2 skrll #include "sljitLir.c"
188 1.1.1.1.2.2 skrll
189 1.1.1.1.2.2 skrll This approach is useful for single file compilers.
190 1.1.1.1.2.2 skrll
191 1.1.1.1.2.2 skrll Advantages:
192 1.1.1.1.2.2 skrll - Everything provided by SLJIT is available
193 1.1.1.1.2.2 skrll (no need to include anything else).
194 1.1.1.1.2.2 skrll - Configuring SLJIT is easy
195 1.1.1.1.2.2 skrll (e.g. redefining SLJIT_MALLOC / SLJIT_FREE).
196 1.1.1.1.2.2 skrll - The SLJIT compiler API is hidden from the
197 1.1.1.1.2.2 skrll world which improves securtity.
198 1.1.1.1.2.2 skrll - The C compiler can optimize the SLJIT code
199 1.1.1.1.2.2 skrll generator (e.g. removing unused functions).
200 1.1.1.1.2.2 skrll
201 1.1.1.1.2.2 skrll ----------------------------------------------------------------
202 1.1.1.1.2.2 skrll Types and macros
203 1.1.1.1.2.2 skrll ----------------------------------------------------------------
204 1.1.1.1.2.2 skrll
205 1.1.1.1.2.2 skrll The sljitConfig.h contains those defines, which controls
206 1.1.1.1.2.2 skrll the compiler. The beginning of sljitConfigInternal.h
207 1.1.1.1.2.2 skrll lists architecture specific types and macros provided
208 1.1.1.1.2.2 skrll by SLJIT. Some of these macros:
209 1.1.1.1.2.2 skrll
210 1.1.1.1.2.2 skrll SLJIT_DEBUG : enabled by default
211 1.1.1.1.2.2 skrll Enables assertions. Should be disabled in release mode.
212 1.1.1.1.2.2 skrll
213 1.1.1.1.2.2 skrll SLJIT_VERBOSE : enabled by default
214 1.1.1.1.2.2 skrll When this macro is enabled, the sljit_compiler_verbose
215 1.1.1.1.2.2 skrll function can be used to dump SLJIT instructions.
216 1.1.1.1.2.2 skrll Otherwise this function is not available. Should be
217 1.1.1.1.2.2 skrll disabled in release mode.
218 1.1.1.1.2.2 skrll
219 1.1.1.1.2.2 skrll SLJIT_SINGLE_THREADED : disabled by default
220 1.1.1.1.2.2 skrll Single threaded programs can define this flag which
221 1.1.1.1.2.2 skrll eliminates the pthread dependency.
222 1.1.1.1.2.2 skrll
223 1.1.1.1.2.2 skrll sljit_sw, sljit_uw, etc. :
224 1.1.1.1.2.2 skrll It is recommended to use these types instead of long,
225 1.1.1.1.2.2 skrll intptr_t, etc. Improves readability / portability of
226 1.1.1.1.2.2 skrll the code.
227