Home | History | Annotate | Line # | Download | only in doc
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