<commit_before># nanojit
Nanojit is a small, cross-platform C++ library that emits machine code. It is part of [Adobe ActionScript](https://github.com/adobe/avmplus) 
and used to be part of [Mozilla SpiderMonkey](https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/Internals/Tracing_JIT) but is no longer used in SpiderMonkey.

## High level overview
Nanojit defines its own linear IR called LIR. This is not an SSA IR as there are no phi nodes. Compared with LLVM IR, the Nanojit IR is low level. There are only primitive types such as 32-bit and 64-bit integers, doubles and floats, and pointers. Users have to manage complex types on their own.

The Nanojit IR is also restricted by platform, e.g. some instructions are only available on 64-bit platforms. 

The main unit of compilation in Nanojit is a Fragment - which can be thought of as a chunk of code. You can make a function out of a fragment by providing a start instruction and appropriate ret instructions. But Fragments need not be functions. I believe this flexibility stems from the fact that Nanojit was designed to be used in a tracing JIT.

A limitation (or complexity) in Nanojit is that function parameters are always the architecture word size, i.e. 64-bit on 64-bit platforms, and 32-bit on 32-bit platforms. This means that you cannot directly pass a double as a parameter on a 32-bit platform! However the workaround is simple, just pass a pointer to a struct that contains the arguments. Of course Nanojit does not understand structs so you need to call the relevant memory load/store operations.

The documentation on Nanojit is sparse or non-existent, making it hard to get started. I hope to provide a simpler, documented api to make it easier to use Nanojit.

## Playing with Nanojit

Nanojit comes with a nice tool called lirasm. This is a command line tool that allows you to run a script containing Nanojit IR instructions. For example, say you want a function that adds its two arguments. We can write this as follows:

```
; this is our add function
; it takes two parameters
; and returns the sum of the two
; note that this script will only run on 64-bit platforms as q2i instruction is
; not available on 32-bit platforms

; the .begin and .end instructions tell lirasm to generate the function prologue and epilogue

.begin add
p1 = paramp 0 0		     ; the first '0' says that this is the 0th parameter 
                       ; the second argument '0' says this is a parameter
p2 = paramp 1 0		     ; the second parameter
x  = q2i p1            ; convert from int64 to int32
                       ; this instruction will only work on 64-bit machines
                       ; it ensures that the script will fail to compile on 32-bit arch
y  = q2i p2            ; convert from int64 to int32
sum = addi x y	       ; add
reti sum
.end

; this is our main function
; we just call add with 200, 100
.begin main
oneh = immi 100		     ; constant 100
twoh = immi 200		     ; constant 200
res = calli add fastcall twoh oneh     ; call function add
reti res
.end
```

If you save above script to a file named add.in, then you can run lirasm as follows:

```
lirasm add.in
```

You can see the generated code by running:

```
lirasm -v add.in
```

## Example using NanoJitExtra API
This project is creating a simplified C API for nanojit - we call this nanojitexra. The API is defined in [nanojitextra.h](https://github.com/dibyendumajumdar/nanojit/blob/master/nanojitextra/nanojitextra.h). *Note* that this is work in progress.

```c++

NJXContextRef jit = NJX_create_context(true);

const char *name = "add";
typedef int (*functype)(NJXParamType, NJXParamType);

// Create a function builder
NJXFunctionBuilderRef builder = NJX_create_function_builder(jit, name, true);

auto param1 = NJX_insert_parameter(builder); /* arg1 */
auto param2 = NJX_insert_parameter(builder); /* arg2 */
auto x = NJX_q2i(builder, param1);           /* x = (int) arg1 */
auto y = NJX_q2i(builder, param2);           /* y = (int) arg2 */
auto result = NJX_addi(builder, x, y);       /* result = x = y */
auto ret = NJX_reti(builder, result);        /* return result */

functype f = (functype)NJX_finalize(builder);

NJX_destroy_function_builder(builder);

assert(f);
assert(f(100, 200) == 300);

NJX_destroy_context(jit);

```

## Building Nanojit
While the goal of this project is to create a standalone build of Nanojit, the original folder structure of avmplus is maintained so that merging upstream changes is easier.

The new build is work in progress. A very early version of CMakeLists.txt is available, this has been tested only on Windows 10 with Visual Studio 2017. The aim is to initially support the build on X86_64 processors, and Windows, Linux and Mac OSX.  

To create Visual Studio project files do following:

```
mkdir build
cd build<commit_msg>convert nanojitextra api to C so that it can be used more easily by diverse programs<commit_after># nanojit
Nanojit is a small, cross-platform C++ library that emits machine code. It is part of [Adobe ActionScript](https://github.com/adobe/avmplus) 
and used to be part of [Mozilla SpiderMonkey](https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/Internals/Tracing_JIT) but is no longer used in SpiderMonkey.

## High level overview
Nanojit defines its own linear IR called LIR. This is not an SSA IR as there are no phi nodes. Compared with LLVM IR, the Nanojit IR is low level. There are only primitive types such as 32-bit and 64-bit integers, doubles and floats, and pointers. Users have to manage complex types on their own.

The Nanojit IR is also restricted by platform, e.g. some instructions are only available on 64-bit platforms. 

The main unit of compilation in Nanojit is a Fragment - which can be thought of as a chunk of code. You can make a function out of a fragment by providing a start instruction and appropriate ret instructions. But Fragments need not be functions. I believe this flexibility stems from the fact that Nanojit was designed to be used in a tracing JIT.

A limitation (or complexity) in Nanojit is that function parameters are always the architecture word size, i.e. 64-bit on 64-bit platforms, and 32-bit on 32-bit platforms. This means that you cannot directly pass a double as a parameter on a 32-bit platform! However the workaround is simple, just pass a pointer to a struct that contains the arguments. Of course Nanojit does not understand structs so you need to call the relevant memory load/store operations.

The documentation on Nanojit is sparse or non-existent, making it hard to get started. I hope to provide a simpler, documented api to make it easier to use Nanojit.

## Playing with Nanojit

Nanojit comes with a nice tool called lirasm. This is a command line tool that allows you to run a script containing Nanojit IR instructions. For example, say you want a function that adds its two arguments. We can write this as follows:

```
; this is our add function
; it takes two parameters
; and returns the sum of the two
; note that this script will only run on 64-bit platforms as q2i instruction is
; not available on 32-bit platforms

; the .begin and .end instructions tell lirasm to generate the function prologue and epilogue

.begin add
p1 = paramp 0 0		     ; the first '0' says that this is the 0th parameter 
                       ; the second argument '0' says this is a parameter
p2 = paramp 1 0		     ; the second parameter
x  = q2i p1            ; convert from int64 to int32
                       ; this instruction will only work on 64-bit machines
                       ; it ensures that the script will fail to compile on 32-bit arch
y  = q2i p2            ; convert from int64 to int32
sum = addi x y	       ; add
reti sum
.end

; this is our main function
; we just call add with 200, 100
.begin main
oneh = immi 100		     ; constant 100
twoh = immi 200		     ; constant 200
res = calli add fastcall twoh oneh     ; call function add
reti res
.end
```

If you save above script to a file named add.in, then you can run lirasm as follows:

```
lirasm add.in
```

You can see the generated code by running:

```
lirasm -v add.in
```

## Example using NanoJitExtra API
This project is creating a simplified C API for nanojit - we call this nanojitexra. The API is defined in [nanojitextra.h](https://github.com/dibyendumajumdar/nanojit/blob/master/nanojitextra/nanojitextra.h). *Note* that this is work in progress.

```c++

NJXContextRef jit = NJX_create_context(true);

const char *name = "add";
typedef int (*functype)(NJXParamType, NJXParamType);

// Create a function builder
NJXFunctionBuilderRef builder = NJX_create_function_builder(jit, name, true);

auto param1 = NJX_insert_parameter(builder); /* arg1 */
auto param2 = NJX_insert_parameter(builder); /* arg2 */
auto x = NJX_q2i(builder, param1);           /* x = (int) arg1 */
auto y = NJX_q2i(builder, param2);           /* y = (int) arg2 */
auto result = NJX_addi(builder, x, y);       /* result = x + y */
auto ret = NJX_reti(builder, result);        /* return result */

functype f = (functype)NJX_finalize(builder);

NJX_destroy_function_builder(builder);

assert(f);
assert(f(100, 200) == 300);

NJX_destroy_context(jit);

```

## Building Nanojit
While the goal of this project is to create a standalone build of Nanojit, the original folder structure of avmplus is maintained so that merging upstream changes is easier.

The new build is work in progress. A very early version of CMakeLists.txt is available, this has been tested only on Windows 10 with Visual Studio 2017. The aim is to initially support the build on X86_64 processors, and Windows, Linux and Mac OSX.  

To create Visual Studio project files do following:

```
mkdir build
cd build
{'fraction_non_alphanumeric': 0.0635441221686994, 'fraction_numerical': 0.01906323665060982, 'mean_word_length': 3.5598130841121494, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 6, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7402862', 'n_tokens_mistral': 3047, 'n_tokens_neox': 2771, 'n_words': 1410}