Skip to content
prabanta-devPublic

About

Meri: the Prabanta back end in C. A register-based virtual machine for the IR of Limba, then AOT and JIT compilation.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Latest commit

 

History

67 Commits

Folders and files

Repository files navigation

Meri

Status: experimental Platform: Linux x86-64 Licence: GPL-3.0-or-later LinkedIn Substack

Meri is the back end of the Prabanta family of compilers, written in C with no dependencies beyond the C library. It reads the intermediate representation (IR) made by Limba, the front end, and runs it: a register-based virtual machine first, then AOT and JIT compilation.

Meri takes its ideas from SedaiBasic2, an earlier compiler of the author written in Free Pascal, not its code.


⚠️ Read this first

This is a project in development, not a usable program. meri reads a module of the IR, compiles it to bytecode and runs it on a virtual machine: no JIT and no AOT yet.

Stage Just started. The bytecode, its file format and the command line change without notice.
Platform Developed and tested on Linux x86-64 only (Debian 13, GCC).

Using it

luxia --emit=lir program.luxia   # writes program.lir (Luxia)
meri program.lir [arguments]     # runs it
meri --disasm program.lir        # prints its bytecode
meri --summary program.lir       # prints what the module holds
meri --lib-path=DIR program.lir  # where its C libraries are looked for

A run-time error stops the program with a message on the standard error and exit status 1; halt(code) exits with code. The language of the module words its errors, luxia: index out of range at program.luxia:12:5; Meri's own errors, such as a module it refuses, begin with meri:. A program has the memory --max-memory gives it (by default half of the physical memory): past it, "out of memory", never a crash. An error of input or output is input/output error; a program whose output is closed (program | head) ends with status 141 and no message.

What runs today: all of Luxia 0 that its front end compiles, the integers of any size (BigInt, on mini-gmp) and calls of C libraries declared in the program (x86-64 Linux only), with Meri's own calling convention, without libffi.

What Meri trusts

A module of the IR is trusted, as a precompiled chunk is in Lua. Meri reads a .lir from a file with Limba's verifier first, and the verifier checks the form of the module (types, SSA), not that its memory accesses are safe. Those safety checks are in the IR itself: a front end such as Luxia writes the checks of nil, of a block still alive and of the bounds, and the optimizer keeps them. A module without them is a wrong module:

  • an access of nil, within the first 64 KiB of memory, stops the run (wrong module: memory accessed with no check of nil);
  • any other unchecked access may crash the process or change the memory of the program or of the engine.

The fuzz target of meri defends the reader and the engine against a malformed file, not against a valid module that does wrong things. Pointers of the program are checked before the C library is given them.

The plan

  • meri program.lir runs the IR written by a front end, such as luxia --emit=lir.
  • luxia program.luxia does both in one executable, in the repository of the language: the libraries are linked statically, and each function goes from the front end to the back end in memory, as soon as it is complete, with no file in between.
  • The virtual machine keeps one file of 64-bit registers, a window of them for each call, and fixed 4-byte instructions.
  • Every program must print in Meri what it prints in the reference interpreter of Limba, on every engine.

As a library

include/meri/meri.h is Meri for another program: a module of the IR compiled whole, or a function at a time as a front end gives it (Luxia's limba/limba_luxia.h), each body read once, while it is still there; the engine chosen when the compilation begins (meri_options); the C libraries linked; the run, which only reads the program; its end flushed and reported as meri reports it, the result owning what it holds (meri_result_free). Luxia's tests/test_meri_api.c uses that header only, fed by the front end of Luxia.

Building

Meri needs Limba next to it (../Limba, or LIMBA_DIR), at the commit named at the end of the last commit message of Meri ("Limba: ..."): its build script builds Limba first. A later Limba may change the IR; until Meri follows, it refuses the modules of that Limba ("written against another runtime or operation table").

./build.sh               # release build
./build.sh release test  # and the tests
./build.sh --help        # variants (debug, asan, ubsan, tsan), actions

A C11 compiler (GCC or Clang) and a POSIX shell are all it needs.

Licence

GPL-3.0-or-later, see LICENSE. The authors, and the code of others compiled into Meri (mini-gmp, under its own licences), are in AUTHORS.

About

Meri: the Prabanta back end in C. A register-based virtual machine for the IR of Limba, then AOT and JIT compilation.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages