aboutsummaryrefslogtreecommitdiff
path: root/vm/src/vm.h
diff options
context:
space:
mode:
Diffstat (limited to 'vm/src/vm.h')
-rw-r--r--vm/src/vm.h166
1 files changed, 166 insertions, 0 deletions
diff --git a/vm/src/vm.h b/vm/src/vm.h
new file mode 100644
index 0000000..03dfc88
--- /dev/null
+++ b/vm/src/vm.h
@@ -0,0 +1,166 @@
1#pragma once
2
3#include <stdbool.h>
4#include <stddef.h>
5#include <stdint.h>
6
7typedef enum Op {
8 Exit, // Pop value from the stack and return as exit code. Return 0 if the
9 // stack is empty.
10 Push,
11 Pop,
12 Add,
13 Sub,
14 Mul,
15 Div,
16 Dec, // Decrement the top of the stack by 1.
17 Empty, // Check whether the stack is empty. Pushes a bool.
18 Cmp, // Pop the top of the stack and compare it with the payload. Pushes a
19 // bool.
20 /* Blocks */
21 End, // Marks the end of a block.
22 Break, // Exit the current block.
23 Loop, // Push a loop block. Payload (i32): label.
24 /* Branches */
25 Br, // Branch. Payload (i64): [(i32) conditional? | (i32) label].
26 // A condtional branch pops a bool from the stack and branches if true.
27 // The condition can also be negated. See br_if().
28 /* Functions */
29 Func,
30 Arg,
31 Call,
32 /* Locals */
33 Local, // Create a local variable.
34 LocalRd, // Load a local variable into the top of the stack.
35 LocalWr, // Pop the top of the stack and store it in a local variable.
36} Op;
37
38typedef enum Type {
39 I32,
40 F32,
41} Type;
42
43// Label type for blocks and locals.
44typedef uint32_t Label;
45
46typedef struct Branch {
47 Label label;
48 bool conditional : 1; // True for conditional branches.
49 bool expected : 1; // Comparison value for conditional branches.
50} Branch;
51
52typedef struct Function {
53 Label label;
54} Function;
55
56typedef struct Value {
57 union {
58 uint64_t u64;
59 int32_t i32;
60 float f32;
61 Branch branch;
62 Label label;
63 };
64} Value;
65
66typedef struct Inst {
67 Op op : 5;
68 Type type : 2;
69 Value payload;
70} Inst;
71
72typedef struct Vm Vm;
73
74// -----------------------------------------------------------------------------
75// VM API
76
77/// Create a new virtual machine.
78Vm* vm_new();
79
80/// Destroy the virtual machine.
81void vm_del(Vm**);
82
83/// Execute code on the virtual machine.
84///
85/// Returns the program exit code if an exit operation is executed, 0 otherwise.
86int vm_run(Vm*, const Inst[], size_t count);
87
88/// Prints the virtual machine's stack to stdout.
89void vm_print_stack(const Vm*);
90
91// -----------------------------------------------------------------------------
92// Programming API
93
94/// Exit the program.
95static inline Inst vmExit() { return (Inst){.op = Exit}; }
96
97/// Push a value.
98static inline Inst vmPushI32(int32_t value) {
99 return (Inst){.op = Push, .type = I32, .payload = (Value){.i32 = value}};
100}
101
102/// Pop a value.
103static inline Inst vmPop(Type type) { return (Inst){.op = Pop, .type = type}; }
104
105/// Add two values.
106static inline Inst vmAdd(Type type) { return (Inst){.op = Add, .type = type}; }
107
108/// Decrement a value.
109static inline Inst vmDec(Type type) { return (Inst){.op = Dec, .type = type}; }
110
111/// Compare a value.
112static inline Inst vmCmpI32(int32_t value) {
113 return (Inst){.op = Cmp, .type = I32, .payload = (Value){.i32 = value}};
114}
115
116/// End the current block.
117static inline Inst vmEnd() { return (Inst){.op = End}; }
118
119/// Create a loop.
120static inline Inst vmLoop(Label label) {
121 return (Inst){.op = Loop, .payload = (Value){.label = label}};
122}
123
124/// Create the payload of a conditional branch.
125static inline Inst vmBr_if(bool value, Label label) {
126 return (Inst){
127 .op = Br,
128 .payload = (Value){
129 .branch = {
130 .label = label,
131 .conditional = 1,
132 .expected = value,
133 }}};
134}
135
136/// Create a function.
137static inline Inst vmFunc(Label label) {
138 return (Inst){.op = Func, .payload = (Value){.label = label}};
139}
140
141/// Create a function argument.
142static inline Inst vmArg(Type type, Label label) {
143 return (Inst){.op = Arg, .type = type, .payload = (Value){.label = label}};
144}
145
146/// Call a function.
147static inline Inst vmCall(Label label) {
148 return (Inst){.op = Call, .payload = (Value){.label = label}};
149}
150
151/// Create a local variable.
152static inline Inst vmLocal(Type type, Label label) {
153 return (Inst){.op = Local, .type = type, .payload = (Value){.label = label}};
154}
155
156/// Read a local variable.
157static inline Inst vmLocalRd(Type type, Label label) {
158 return (Inst){
159 .op = LocalRd, .type = type, .payload = (Value){.label = label}};
160}
161
162/// Write a local variable.
163static inline Inst vmLocalWr(Type type, Label label) {
164 return (Inst){
165 .op = LocalWr, .type = type, .payload = (Value){.label = label}};
166}