# Your First Program
To use SLJIT, simply include the `sljitLir.h` header in your code and link against `sljitLir.c`.
Let's jump right into your first program:
```c
#include "sljitLir.h"
#include <stdio.h>
#include <stdlib.h>
typedef sljit_sw (SLJIT_FUNC *func3_t)(sljit_sw a, sljit_sw b, sljit_sw c);
static int add3(sljit_sw a, sljit_sw b, sljit_sw c)
{
void *code;
sljit_uw len;
func3_t func;
/* Create a SLJIT compiler */
struct sljit_compiler *C = sljit_create_compiler(NULL);
/* Start a context (function prologue) */
sljit_emit_enter(C,
0, /* Options */
SLJIT_ARGS3(W, W, W, W), /* 1 return value and 3 parameters of type sljit_sw */
1, /* 1 scratch register used */
3, /* 3 saved registers used */
0); /* 0 bytes allocated for function local variables */
/* The first argument of a function is stored in register SLJIT_S0, the 2nd in 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 moves R0 to RETURN REG and returns */
/* (in fact, R0 is the RETURN REG itself) */
sljit_emit_return(C, SLJIT_MOV, SLJIT_R0, 0);
/* Generate machine code */
code = sljit_generate_code(C, 0, NULL);
len = sljit_get_generated_code_size(C);
/* Execute code */
func = (func3_t)code;
printf("func return %ld\n", (long)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);
}
```
Code generation with SLJIT typically starts with a call to `sljit_emit_enter`, which generates the *function prologue*: certain register are saved to the stack, stack space for function-local variables is allocted if requested and a call frame is established.
This is necessary as the code generated by SLJIT wants to interoperate nicely with the other parts of your program: it can be called just like a C function pointer and you can [call C functions](04-calling-external-functions.md) from within JIT-ed code with ease.
The rules for interoperation are also refered to as the *Application Binary Interface*, or ABI for short. These typically vary between different architectures and operating systems. The most common ones are:
- [System V ABI](https://wiki.osdev.org/System_V_ABI) - used by the major Unix operating systems (Linux / BSD / AIX / ...)
- [Windows x64 ABI](https://learn.microsoft.com/en-us/cpp/build/x64-software-conventions?view=msvc-170) - used by (you guessed it) Windows
Luckily, SLJIT does all the heavy lifting so that you do not have to worry about platform and ABI specific stuff for the most part. If you are interested in how things work under the hood though, take a look at the *calling conventions* sections in the ABI documentation.
SLJIT supports two types of registers (analoguous to the underlying ABIs):
- **Scratch registers** (also known as *volatile registers*) - may not preserve their value accross function calls
- **Saved registers** (also known as *non-volatile registers*) - preserve their value accross function calls
We declare the amount of scratch and saved registers our function will use upfront in the call to `sljit_emit_enter`. These registers are then referred to by their names (`SLJIT_R0`, `SLJIT_R1`, `SLJIT_R2`, ... for scratch registers and `SLJIT_S0`, `SLJIT_S1`, `SLJIT_S2`, ... for saved registers).
Additionally, SLJIT supports dedicated floating point and vector registers. These are referred to by `SLJIT_FRN` / `SLJIT_FSN` and `SLJIT_VRN` / `SLJIT_VSN` respectively (where `N` is a number starting from `0`).
As different architectures have different amounts of registers, the amount of scratch and saved registers available varies accross them. You can query the available amount of registers with the following macros:
- `SLJIT_NUMBER_OF_REGISTERS` (>= 12 on all supported platforms)
- `SLJIT_NUMBER_OF_SCRATCH_REGISTERS`
- `SLJIT_NUMBER_OF_SAVED_REGISTERS` (>= 6 on all supported platforms)
- `SLJIT_NUMBER_OF_FLOAT_REGISTERS`
- `SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS`
- `SLJIT_NUMBER_OF_VECTOR_REGISTERS`
- `SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS`
Note that the different register sets may overlap, i.e. two distinct SLJIT registers may refer to the same physical register. This is especially true between scratch and saved registers of the same kind, as well as between floating point and vector registers.
A function's signature is defined using one of the `SLJIT_ARGS...` macros. In the example above, the function declares a return type and three parameters of type `W`, i.e. an integer of machine word width. For the other supported types, take a look at the `SLJIT_ARG_TYPE_...` macros in `sljitLir.h`. Parameters are passed by default in registers `SLJIT_S0` - `SLJIT_S3` (for integers) and `SLJIT_FR0` - `SLJIT_FR3` (for floating point numbers) respectively. Analoguos, the return value is passed in `SLJIT_R0` or `SLJIT_FR0`.
Most generic operations are carried out by invoking one of the `sljit_emit_opN` functions. These typically take one target, as well as `N` source operands.
| 1st parameter | 2nd parameter | Semantic | Example |
| --- | --- | --- | --- |
| `r` | `0` | The value contained in register `r`, i.e. `*r` | `SLJIT_R0, 0` |
| `SLJIT_IMM` | Value `i` | The value `i` | `SLJIT_IMM, 17` |
| `SLJIT_MEM` / `SLJIT_MEM0` | Address `a` | The value at address `a` | `SLJIT_MEM0, &my_c_func` |
| `SLJIT_MEM1(r)` | Offset `o` | The value at address `*r + o` | `SLJIT_MEM1(SLJIT_R0), 16`<br />Access the memory at the address in `SLJIT_R0` offset by `16` |
| `SLJIT_MEM2(r1, r2)` | Shift `s` | The value at address `*r1 + (*r2 * (1 << s))`;<br />`s` must be in `[0, 1, 2, 3]` | `SLJIT_MEM2(SLJIT_R0, SLJIT_R1), 2`<br />Access index `SLJIT_R1` in an array of items of length `2` byte starting at address `SLJIT_R0` |
Lastly, control is returned to the caller by invoking `sljit_emit_return`.