Skip to content

Instantly share code, notes, and snippets.

@alphaKAI
Created January 14, 2019 12:19
Show Gist options
  • Save alphaKAI/94c7f44699128c701bbfb3c425c61ec1 to your computer and use it in GitHub Desktop.
Save alphaKAI/94c7f44699128c701bbfb3c425c61ec1 to your computer and use it in GitHub Desktop.
Tiny example of direct threaded vm and a naive switch-case implementation.
#include <stdio.h>
#include <stdlib.h>
// Instruction set
enum {
Push,
Add,
Sub,
Mul,
Div,
Print,
End
};
#define STACK_SIZE 1024
int stack[STACK_SIZE];
size_t stack_count = 0;
void init_stack() {
stack_count = 0;
}
void push(int v) {
stack[stack_count++] = v;
}
int pop() {
if (stack_count > 0) {
return stack[--stack_count];
} else {
fprintf(stderr, "out of stack\n");
exit(EXIT_FAILURE);
}
}
// naive implementation
void itpr1(int ops[], size_t ops_length) {
init_stack();
int op, a, b, v;
for (size_t i = 0; i < ops_length; i++) {
op = ops[i];
switch (op) {
case Push:
if(!(i + 1 < ops_length && stack_count + 1 < STACK_SIZE)) {
fprintf(stderr, "out of order\n");
exit(EXIT_FAILURE);
}
int v = ops[++i];
push(v);
break;
case Add:
b = pop();
a = pop();
push(a + b);
break;
case Sub:
b = pop();
a = pop();
push(a - b);
break;
case Mul:
b = pop();
a = pop();
push(a * b);
break;
case Div:
b = pop();
a = pop();
push(a / b);
break;
case Print:
v = pop();
push(v);
printf("v : %d\n", v);
break;
case End:
return;
default:
fprintf(stderr, "no default\n");
exit(EXIT_FAILURE);
}
}
}
void* xmalloc(size_t size) {
void* ptr = malloc(size);
if (ptr == NULL) {
fprintf(stderr, "Failed to allocate memory\n");
exit(EXIT_FAILURE);
}
return ptr;
}
// Direct Threaded VM
void itpr2(int ops[], size_t ops_length) {
init_stack();
int op = 0, a = 0, b = 0, v = 0;
int i = 0;
static void* table[] = {
&&L_push,
&&L_add,
&&L_sub,
&&L_mul,
&&L_div,
&&L_print,
&&L_end
};
void** ops_ptr = xmalloc(sizeof(void*) * ops_length);
for(int j = 0; j < ops_length; j++){
ops_ptr[j] = table[ops[j]];
}
loop_start:
op = ops[i];
goto *table[op];
L_push:
{
if(!(i + 1 < ops_length && stack_count + 1 < STACK_SIZE)) {
fprintf(stderr, "out of range\n");
exit(EXIT_FAILURE);
}
v = ops[++i];
push(v);
i++;
goto *ops_ptr[i];
}
L_add:
{
b = pop();
a = pop();
push(a + b);
i++;
goto *ops_ptr[i];
}
L_sub:
{
b = pop();
a = pop();
push(a - b);
i++;
goto *ops_ptr[i];
}
L_mul:
{
b = pop();
a = pop();
push(a * b);
i++;
goto *ops_ptr[i];
}
L_div:
{
b = pop();
a = pop();
push(a / b);
i++;
goto *ops_ptr[i];
}
L_print:
{
v = pop();
push(v);
printf("v : %d\n", v);
i++;
goto *ops_ptr[i];
}
L_end:
return;
}
int main() {
int ops[] = {
Push, 1,
Push, 2,
Add,
Print,
End
};
size_t ops_len = sizeof(ops)/sizeof(ops[0]);
printf("itpr1:\n");
itpr1(ops, ops_len);
printf("itpr2:\n");
itpr2(ops, ops_len);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment