aboutsummaryrefslogtreecommitdiff
path: root/README.org
blob: d1764d034b5acdddebb57b0ee5f00a2797e0c0c5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#+title: Oreo's Virtual Machine (OVM)
#+author: Aryadev Chavali
#+date: 2023-10-15

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.
* 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 [[file:Makefile::CC=gcc][here]] to change the compiler).

To build everything simply run ~make~.  This will build:
+ [[file:lib/inst.c][instruction bytecode system]] which provides
  object files to target the VM
+ [[file:vm/main.c][VM executable]] which executes bytecode
+ [[file:asm/main.c][Assembler executable]] which assembles compliant
  assembly code to VM bytecode
+ [[file:examples/][Assembly examples]] which provide some source code
  examples on common programs one may write.  Use this to figure out
  how to write compliant assembly.  Also a good test of both the VM
  and assembler.

You may also build each component individually through the
corresponding recipe:
+ ~make lib~
+ ~make vm~
+ ~make asm~
+ ~make examples~
* Instructions to target the virtual machine
You need to link with the object files for
[[file:lib/base.c][base.c]], [[file:lib/darr.c][darr.c]] and
[[file:lib/inst.c][inst.c]] to be able to properly target the OVM.
The basic idea is to create some instructions via ~inst_t~,
instantiating a ~prog_t~ structure which wraps those instructions
(includes a header and other useful things for the runtime), then
using ~prog_write_file~ to serialise and write bytecode to a file
pointer.

To execute directly compiled bytecode use the ~ovm.out~ executable on
the bytecode file.

For clarity, one may build ~lib~ (~make lib~) then use the resulting
object files to link and create bytecode for the virtual machine.
** In memory virtual machine
Instead of serialising and writing bytecode to a file, one may instead
serialise bytecode in memory using ~prog_write_bytecode~ which writes
bytecode to a dynamic byte buffer, so called *in memory compilation*.
To execute this bytecode, deserialise the bytecode into a program then
load it into a complete ~vm_t~ structure (linking with
[[file:vm/runtime.c][runtime.c]]).

In fact, you may skip the process of serialising entirely.  You can
emit a ~prog_t~ structure corresponding to source code, load it
directly into the ~vm_t~ structure, then execute.  To do so is a bit
involved, so I recommend looking at [[file:vm/main.c]].  In rough
steps:
+ Create a virtual machine "from scratch" (load the necessary
  components (the stack, heap and call stack) by hand)
+ Load program into VM (~vm_load_program~)
+ Run ~vm_execute_all~

This is recommended if writing an interpreted language such as a Lisp,
where on demand execution of code is more suitable.
* Lines of code
#+begin_src sh :results table :exports results
wc -lwc $(find -regex ".*\.[ch]\(pp\)?")
#+end_src

#+RESULTS:
| Files                  | Lines | Words |  Bytes |
|------------------------+-------+-------+--------|
| ./lib/heap.h           |    42 |   111 |    801 |
| ./lib/inst.c           |   516 |  1315 |  13982 |
| ./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 |
| ./asm/base.hpp         |    21 |    68 |    472 |
| ./asm/lexer.cpp        |   565 |  1448 |  14067 |
| ./asm/base.cpp         |    33 |    89 |    705 |
| ./asm/parser.hpp       |    82 |   199 |   1656 |
| ./asm/parser.cpp       |    42 |   129 |   1294 |
| ./asm/lexer.hpp        |   106 |   204 |   1757 |
| ./asm/preprocesser.cpp |   218 |   574 |   5800 |
| ./asm/preprocesser.hpp |    62 |   147 |   1360 |
| ./asm/main.cpp         |   148 |   414 |   3791 |
|------------------------+-------+-------+--------|
| total                  |  4103 | 11405 | 104867 |