This repository has been archived on 2025-11-10. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Aryadev Chavali a4b057f20a Refactored inst.c and runtime.c for OPCODE_IS_TYPE change
Pretty simple, there are fewer opcode types that use signed types than
unsigned so it was a pretty simple rename.
2024-04-25 02:55:54 +05:30
2023-11-01 18:20:03 +00:00
2023-10-15 01:25:24 +01:00
2024-04-16 20:45:02 +06:30
2024-04-09 21:23:54 +06:30

Aryadev's Virtual Machine (AVM)

A stack based virtual machine in C11, with a dynamic register setup which acts as variable space. Deals primarily in bytes, doesn't make assertions about typing and is very simple to target.

This repository contains both a library (lib folder) to (de)serialize bytecode and a program (vm folder) to execute bytecode.

Along with this is an assembler program which can compile an assembly-like language to bytecode.

How to build

Requires GNU make and a compliant C11 compiler. Code base has been tested against gcc and clang, but given how the project has been written without use of GNU'isms (that I'm aware of) it shouldn't be an issue to compile using something like tcc or another compiler (look at here to change the compiler).

To build everything simply run make. This will build:

You may also build each component individually through the corresponding recipe:

  • make lib
  • make vm

How to target the virtual machine

Link with the object files for base.c and inst.c to be able to properly target the virtual machine. The general idea is to convert parse units into instances of inst_t. Once a collection of inst_t's have been made, they must be wrapped in a prog_t structure which is a flexibly allocated structure with two components:

  1. A program header prog_header_t with some essential properties of the program (start address, count, etc)
  2. A buffer of type inst_t which should contain the ordered collection constructed

There are two ways to utilise execute this program structure: compilation or in memory execution.

Compilation

The prog_t structure can be fed to prog_write_file with a file pointer to write well formed AVM bytecode into a file. To execute this bytecode, simply use the avm.out executable with the bytecode file name.

This is the classical way I expect languages to target the virtual machine.

In memory virtual machine

This method requires linking with vm/runtime.c to be able to construct a working vm_t structure. The steps are:

  • Load the stack, heap and call stack into a vm_t structure
  • Load the prog_t into the vm_t (vm_load_program)
  • Execute via vm_execute or vm_execute_all

vm_execute executes the next instruction and stops, while vm_execute_all continues execution till the program halts. Either can be useful depending on requirements.

I expect this method to be used for languages that are interpreted such as Lisp or Python where code -> execution rather than code -> compile unit -> execute unit, while still providing the ability to compile code to a byte code unit.

Lines of code

Files Lines Words Bytes
./lib/heap.h 42 111 801
./lib/inst.c 512 1303 13936
./lib/darr.c 77 225 1757
./lib/base.c 107 306 2002
./lib/inst.h 108 426 4067
./lib/prog.h 176 247 2616
./lib/base.h 148 626 3915
./lib/darr.h 88 465 2697
./lib/heap.c 101 270 1910
./vm/runtime.h 301 780 7965
./vm/runtime.c 1070 3097 30010
./vm/main.c 92 265 2243
total 2822 8121 73919
Description
No description provided
Readme 27 KiB
Languages
C 97%
Makefile 3%