SlideShare a Scribd company logo
1 of 38
Download to read offline
implementing software
machines in Go and C
Eleanor McHugh
@feyeleanor
this is a talk about VMs
system virtualisation
hardware emulation
abstract virtual machines
system virtualisation
this is a talk about VMs
system virtualisation
hardware emulation
abstract virtual machines
hardware emulation
this is a talk about VMs
system virtualisation
hardware emulation
abstract virtual machines
program execution
this is a talk about VMs
system virtualisation
hardware emulation
abstract virtual machines
inspired by hardware
discrete components
processors
storage
communications
software machines
timely
stateful
scriptable
#include <stdio.h>
#define STACK_MAX 100
typedef enum {
STACK_OK = 0,
STACK_OVERFLOW,
STACK_UNDERFLOW
} STACK_STATUS;
typedef struct stack STACK;
struct stack {
int data[STACK_MAX];
int size;
};
STACK *NewStack() {
STACK s;
s.size = 0;
return &s;
}
STACK_STATUS push(STACK *s, int data) {
if (s->size < STACK_MAX) {
s->data[s->size++] = data;
return STACK_OK;
}
return STACK_OVERFLOW;
}
STACK_STATUS pop(STACK *s, int *r) {
if (s->size > 0) {
*r = s->data[s->size - 1];
s->size--;
return STACK_OK;
}
return STACK_UNDERFLOW;
}
int main() {
int l, r;
STACK *s = NewStack();
push(s, 1);
push(s, 3);
pop(s, &l);
pop(s, &r);
printf("%d + %d = %dn", l, r, l + r);
}
c: array stack
package main
import "fmt"
type stack_status int
const (
STACK_OK = stack_status(iota)
STACK_OVERFLOW
STACK_UNDERFLOW
)
type stack struct {
data []int
}
func (s *stack) Push(data int) {
s.data = append(s.data, data)
}
func (s *stack) Pop() (int, stack_status) {
if s == nil || len(s.data) < 1 {
return 0, STACK_UNDERFLOW
}
sp := len(s.data) - 1
r := s.data[sp]
s.data = s.data[:sp]
return r, STACK_OK
}
func main() {
s := new(stack)
s.Push(1)
s.Push(3)
l, _ := s.Pop()
r, _ := s.Pop()
fmt.Printf("%d + %d = %dn", l, r, l+r)
}
go: array stack
#include <stdio.h>
#include <stdlib.h>
typedef struct stack STACK;
struct stack {
int data;
STACK *next;
};
STACK *push(STACK *s, int data) {
STACK *r = malloc(sizeof(STACK));
r->data = data;
r->next = s;
return r;
}
STACK *pop(STACK *s, int *r) {
if (s == NULL)
exit(1);
*r = s->data;
return s->next;
}
int main() {
int l, r;
STACK *s = push(NULL, 1);
s = push(s, 3);
pop(pop(s, &r), &l);
printf("%d + %d = %dn", l, r, l + r);
}
c: functional cactus stack
package main
import "fmt"
type stack struct {
data int
tail *stack
}
func (s *stack) Push(v int) (r *stack) {
r = &stack{data: v, tail: s}
return
}
func (s *stack) Pop() (v int, r *stack) {
return s.data, s.tail
}
func main() {
var l, r int
var s *stack
s = s.Push(1).Push(3)
l, s = s.Pop()
r, s = s.Pop()
fmt.Printf("%d + %d = %dn", l, r, l+r)
}
go: functional cactus stack
#include <stdio.h>
#include <stdlib.h>
typedef struct stack STACK;
struct stack {
int data;
STACK *next;
};
STACK *push(STACK *s, int data) {
STACK *r = malloc(sizeof(STACK));
r->data = data;
r->next = s;
return r;
}
STACK *pop(STACK *s, int *r) {
if (s == NULL)
exit(1);
*r = s->data;
return s->next;
}
int sum(STACK *tos) {
int a, p;
a = 0;
for (; tos != NULL;) {
tos = pop(tos, &p);
a += p;
}
return a;
}
int main() {
STACK *s1 = push(NULL, 7);
STACK *s2 = push(push(s1, 7), 11);
s1 = push(push(push(s1, 2), 9), 4);
STACK *s3 = push(s1, 17);
s1 = push(s1, 3);
printf("sum = %dn", sum(s1));
printf("sum = %dn", sum(s2));
printf("sum = %dn", sum(s3));
}
c: functional cactus stack
package main
import "fmt"
type stack struct {
data int
tail *stack
}
func (s *stack) Push(v int) (r *stack) {
r = &stack{data: v, tail: s}
return
}
func (s *stack) Pop() (v int, r *stack) {
return s.data, s.tail
}
func (s *stack) Sum() (r int) {
for p := 0; s != nil; r += p {
p, s = s.Pop()
}
return
}
func main() {
var s1, s2, s3 *stack
s1 = s1.Push(7)
s2 = s1.Push(7).Push(11)
s1 = s1.Push(2).Push(9).Push(4)
s3 = s1.Push(17)
s1 = s1.Push(3)
fmt.Printf("sum = %vn", s1.Sum())
fmt.Printf("sum = %vn", s2.Sum())
fmt.Printf("sum = %vn", s3.Sum())
}
go: functional cactus stack
dispatch loops
fetch
decode
execute
dispatch loops
read next instruction via a program counter
determine the operation to perform
execute the operation and adjust machine state
switch interpreter
instructions stored sequentially in memory
each represented by a token or opcode
available in all implementation languages
tokens can be compact - often single bytes
#include <stdio.h>
#include <stdlib.h>
typedef struct stack STACK;
struct stack {
int data;
STACK *next;
};
STACK *push(STACK *s, int data) {
STACK *r = malloc(sizeof(STACK));
r->data = data;
r->next = s;
return r;
}
STACK *pop(STACK *s, int *r) {
if (s == NULL)
exit(1);
*r = s->data;
return s->next;
}
typedef enum { PUSH = 0, ADD, PRINT, EXIT } opcodes;
STACK *S;
void interpret(int *PC) {
int l, r;
while (1) {
switch(*PC++) {
case PUSH:
S = push(S, *PC++);
break;
case ADD:
S = pop(S, &l);
S = pop(S, &r);
S = push(S, l + r);
break;
case PRINT:
printf(“%d + %d = %dn, l, r, S->data);
break;
case EXIT:
return;
}
}
}
int main() {
int program [] = {
(int)PUSH, 13,
(int)PUSH, 28,
(int)ADD,
PRINT,
EXIT,
};
interpret(program);
}
c: switch interpreter
#include <stdio.h>
#include <stdlib.h>
typedef struct stack STACK;
struct stack {
int data;
STACK *next;
};
STACK *push(STACK *s, int data) {
STACK *r = malloc(sizeof(STACK));
r->data = data;
r->next = s;
return r;
}
STACK *pop(STACK *s, int *r) {
if (s == NULL)
exit(1);
*r = s->data;
return s->next;
}
typedef enum { PUSH = 0, ADD, PRINT, EXIT } opcodes;
STACK *S;
#define READ_OPCODE *PC++
void interpret(int *PC) {
int l, r;
while (1) {
switch(READ_OPCODE) {
case PUSH:
S = push(S, READ_OPCODE);
break;
case ADD:
S = pop(S, &l);
S = pop(S, &r);
S = push(S, l + r);
break;
case PRINT:
printf(“%d + %d = %dn, l, r, S->data);
break;
case EXIT:
return;
}
}
}
int main() {
int program [] = {
(int)PUSH, 13,
(int)PUSH, 28,
(int)ADD,
PRINT,
EXIT,
};
interpret(program);
}
c: switch interpreter
package main
import "fmt"
func main() {
var program = []interface{}{
PUSH, 13,
PUSH, 28,
ADD,
PRINT,
EXIT,
}
interpret(program)
}
type stack struct {
data int
tail *stack
}
func (s *stack) Push(v int) (r *stack) {
r = &stack{data: v, tail: s}
return
}
func (s *stack) Pop() (v int, r *stack) {
return s.data, s.tail
}
type OPCODE int
const (
PUSH = OPCODE(iota)
ADD
PRINT
EXIT
)
func interpret(p []interface{}) {
var l, r int
S := new(stack)
for PC := 0; ; PC++ {
if op, ok := p[PC].(OPCODE); ok {
switch op {
case PUSH:
PC++
S = S.Push(p[PC].(int))
case ADD:
l, S, = S.Pop()
r, S = S.Pop()
S = S.Push(l + r)
case PRINT:
fmt.Printf("%v + %v = %vn", l, r, S.data)
case EXIT:
return
}
} else {
return
}
}
}
go: switch interpreter
direct call threading
instructions stored sequentially in memory
each represented by a pointer to a function
not available in all languages
instructions each require a machine word
#include <stdio.h>
#include <stdlib.h>
typedef struct stack STACK;
struct stack {
int data;
STACK *next;
};
STACK *push(STACK *s, int data) {
STACK *r = malloc(sizeof(STACK));
r->data = data;
r->next = s;
return r;
}
STACK *pop(STACK *s, int *r) {
if (s == NULL)
exit(1);
*r = s->data;
return s->next;
}
typedef void (*opcode)();
STACK *S;
opcode *PC;
void op_push() {
S = push(S, (int)(long)(*PC++));
}
void op_add_and_print() {
int l, r;
S = pop(S, &l);
S = pop(S, &r);
S = push(S, l + r);
printf("%d + %d = %dn", l, r, S->data);
}
void op_exit() {
exit(0);
}
int main() {
opcode program [] = {
op_push, (opcode)(long)13,
op_push, (opcode)(long)28,
op_add_and_print,
op_exit
};
PC = program;
while (1) {
(*PC++)();
}
}
c: direct call-threaded interpreter
#include <stdio.h>
#include <stdlib.h>
typedef struct stack STACK;
struct stack {
int data;
STACK *next;
};
STACK *push(STACK *s, int data) {
STACK *r = malloc(sizeof(STACK));
r->data = data;
r->next = s;
return r;
}
STACK *pop(STACK *s, int *r) {
if (s == NULL)
exit(1);
*r = s->data;
return s->next;
}
typedef void (*opcode)();
STACK *S;
opcode *PC;
#define READ_OPCODE *PC++
void op_push() {
S = push(S, (int)(long)(READ_OPCODE));
}
void op_add_and_print() {
int l, r;
S = pop(S, &l);
S = pop(S, &r);
S = push(S, l + r);
printf("%d + %d = %dn", l, r, S->data);
}
void op_exit() {
exit(0);
}
int main() {
opcode program [] = {
op_push, (opcode)(long)13,
op_push, (opcode)(long)28,
op_add_and_print,
op_exit
};
PC = program;
while (1) {
(READ_OPCODE)();
}
}
c: direct call-threaded interpreter
package main
import "fmt"
import "os"
func main() {
p := new(Interpreter)
p.m = []interface{}{
p.Push, 13,
p.Push, 28,
p.Add,
p.Print,
p.Exit,
}
p.Run()
}
type stack struct {
data int
tail *stack
}
func (s *stack) Push(v int) (r *stack) {
r = &stack{data: v, tail: s}
return
}
func (s *stack) Pop() (v int, r *stack) {
return s.data, s.tail
}
type Interpreter struct {
S *stack
l, r, PC int
m []interface{}
}
func (i *Interpreter) opcode() func() {
return i.m[i.PC].(func())
}
func (i *Interpreter) operand() int {
return i.m[i.PC].(int)
}
func (i *Interpreter) Run() {
for {
i.opcode()()
i.PC++
}
}
func (i *Interpreter) Push() {
i.PC++
i.S = i.S.Push(i.operand())
}
func (i *Interpreter) Add() {
i.l, i.S = i.S.Pop()
i.r, i.S = i.S.Pop()
i.S = i.S.Push(i.l + i.r)
}
func (i *Interpreter) Print() {
fmt.Printf("%v + %v = %vn", i.l, i.r, i.S.data)
}
func (i *Interpreter) Exit() {
os.Exit(0)
}
go: direct call-threaded interpreter
indirect threading
instructions stored sequentially in memory
each represented by a local jump label
gcc/clang specific C extension
instructions indirectly load successor
#include <stdio.h>
#include <stdlib.h>
typedef struct stack STACK;
struct stack {
int data;
STACK *next;
};
STACK *push(STACK *s, int data) {
STACK *r = malloc(sizeof(STACK));
r->data = data;
r->next = s;
return r;
}
STACK *pop(STACK *s, int *r) {
if (s == NULL)
exit(1);
*r = s->data;
return s->next;
}
typedef enum { PUSH = 0, ADD, EXIT } opcodes;
STACK *S;
void interpret(int *program) {
static void *opcodes [] = {
&&op_push,
&&op_add,
&&op_print,
&&op_exit
};
int l, r;
int *PC = program;
goto *opcodes[*PC++];
op_push:
S = push(S, *PC++);
goto *opcodes[*PC++];
op_add:
S = pop(S, &l);
S = pop(S, &r);
S = push(S, l + r);
goto *opcodes[*PC++];
op_print:
printf("%d + %d = %dn", l, r, S->data);
goto *opcodes[*PC++];
op_exit:
return;
}
int main() {
int program [] = {
PUSH, 13,
PUSH, 28,
ADD,
EXIT
};
interpret(program);
}
c: indirect-threaded interpreter
#include <stdio.h>
#include <stdlib.h>
typedef struct stack STACK;
struct stack {
int data;
STACK *next;
};
STACK *push(STACK *s, int data) {
STACK *r = malloc(sizeof(STACK));
r->data = data;
r->next = s;
return r;
}
STACK *pop(STACK *s, int *r) {
if (s == NULL)
exit(1);
*r = s->data;
return s->next;
}
typedef enum { PUSH = 0, ADD, PRINT, EXIT } opcodes;
STACK *S;
#define READ_OPCODE *PC++
#define EXECUTE_OPCODE goto *opcodes[READ_OPCODE];
#define PRIMITIVE(name, body) 
name: 
body; 
EXECUTE_OPCODE
void interpret(int *program) {
static void *opcodes [] = {
&&op_push,
&&op_add,
&&op_print,
&&op_exit
};
int l, r;
int *PC = program;
EXECUTE_OPCODE;
PRIMITIVE(op_push, S = push(S, READ_OPCODE))
PRIMITIVE(op_add, 
S = pop(S, &l); 
S = pop(S, &r); 
S = push(S, l + r); 
)
PRIMITIVE(op_print, printf("%d + %d = %dn", l, r, S->data))
PRIMITIVE(op_exit, return)
}
int main() {
int program [] = {
PUSH, 13,
PUSH, 28,
ADD,
PRINT,
EXIT
};
interpret(program);
}
c: indirect-threaded interpreter
direct threading
instructions stored sequentially in memory
each represented by a local jump label
gcc/clang specific C extension
instructions directly load successors
#include <stdio.h>
#include <stdlib.h>
typedef struct stack STACK;
struct stack {
int data;
STACK *next;
};
STACK *push(STACK *s, int data) {
STACK *r = malloc(sizeof(STACK));
r->data = data;
r->next = s;
return r;
}
STACK *pop(STACK *s, int *r) {
if (s == NULL)
exit(1);
*r = s->data;
return s->next;
}
typedef enum { PUSH = 0, ADD, PRINT, EXIT } opcodes;
STACK *S;
void **compile(int *PC, int words, void *despatch_table[]) {
static void *compiler [] = {
&&comp_push,
&&comp_add,
&&comp_print,
&&comp_exit
};
if (words < 1)
return NULL;
void **program = malloc(sizeof(void *) * words);
void **cp = program;
goto *compiler[*PC++];
comp_push:
*cp++ = despatch_table[PUSH];
*cp++ = (void *)(long)*PC++;
words -= 2;
if (words == 0) return program;
goto *compiler[*PC++];
comp_add:
*cp++ = despatch_table[ADD];
words--;
if (words == 0) return program;
goto *compiler[*PC++];
comp_print:
*cp++ = despatch_table[PRINT];
words--;
if (words == 0) return program;
goto *compiler[*PC++];
comp_exit:
*cp++ = despatch_table[EXIT];
words--;
if (words == 0) return program;
goto *compiler[*PC++];
}
c: direct-threaded interpreter (1)
void interpret(int *PC, int words) {
static void *despatch_table[] = {
&&op_push,
&&op_add,
&&op_print,
&&op_exit
};
int l, r;
void **program = compile(PC, words, despatch_table);
if (program == NULL)
exit(1);
goto **program++;
op_push:
S = push(S, (int)(long)*program++);
goto **program++;
op_add:
S = pop(S, &l);
S = pop(S, &r);
S = push(S, l + r);
goto **program++;
op_print:
printf("%d + %d = %dn", l, r, S->data);
goto **program++;
op_exit:
return;
}
int main() {
int program[] = {
PUSH, 13,
PUSH, 28,
ADD,
PRINT,
EXIT
};
interpret(program, 7);
}
c: direct-threaded interpreter (2)
#include <stdio.h>
#include <stdlib.h>
typedef struct stack STACK;
struct stack {
int data;
STACK *next;
};
STACK *push(STACK *s, int data) {
STACK *r = malloc(sizeof(STACK));
r->data = data;
r->next = s;
return r;
}
STACK *pop(STACK *s, int *r) {
if (s == NULL)
exit(1);
*r = s->data;
return s->next;
}
typedef enum { PUSH = 0, ADD, PRINT, EXIT } opcodes;
STACK *S;
#define COMPILE(body) 
COMPILE_NEXT_OPCODE 
body
#define COMPILE_NEXT_OPCODE 
if (words < 1) 
return program; 
goto *compiler[*PC++];
#define DESCRIBE_PRIMITIVE(name, body) 
name: 
body; 
COMPILE_NEXT_OPCODE
#define WRITE_OPCODE(value) 
*cp++ = value; 
words--;
void **compile(int *PC, int words, void *despatch_table[]) {
static void *compiler[] = {
&&push,
&&add,
&&print,
&&exit
};
void **program = malloc(sizeof(void *) * words);
void **cp = program;
COMPILE( 
DESCRIBE_PRIMITIVE(push, 
WRITE_OPCODE(despatch_table[PUSH]) 
WRITE_OPCODE((void *)(long)*PC++)) 
DESCRIBE_PRIMITIVE(add, 
WRITE_OPCODE(despatch_table[ADD])) 
DESCRIBE_PRIMITIVE(print, 
WRITE_OPCODE(despatch_table[PRINT])) 
DESCRIBE_PRIMITIVE(exit, 
WRITE_OPCODE(despatch_table[EXIT])) 
)
}
c: direct-threaded interpreter (1)
#define READ_OPCODE *program++
#define EXECUTE_OPCODE goto *READ_OPCODE;
#define PRIMITIVE(name, body) 
name: 
body; 
EXECUTE_OPCODE
void interpret(int *PC, int words) {
static void *despatch_table[] = {
&&push,
&&add,
&&print,
&&exit
};
int l, r;
void **program = compile(PC, words, despatch_table);
if (program == NULL)
exit(1);
EXECUTE( 
PRIMITIVE(push, S = push(S, (int)(long)READ_OPCODE)) 
PRIMITIVE(add, 
S = pop(S, &l); 
S = pop(S, &r); 
S = push(S, l + r)) 
PRIMITIVE(print, printf("%d + %d = %dn", l, r, S->data)) 
PRIMITIVE(exit, return) 
)
}
int main() {
int program[] = {
PUSH, 13,
PUSH, 28,
ADD,
PRINT,
EXIT
};
interpret(program, 7);
}
c: direct-threaded interpreter (2)
Implementing Software Machines in Go and C

More Related Content

What's hot

All I know about rsc.io/c2go
All I know about rsc.io/c2goAll I know about rsc.io/c2go
All I know about rsc.io/c2go
Moriyoshi Koizumi
 
Network lap pgms 7th semester
Network lap pgms 7th semesterNetwork lap pgms 7th semester
Network lap pgms 7th semester
DOSONKA Group
 
Network lab manual
Network lab manualNetwork lab manual
Network lab manual
Prabhu D
 
Bytes in the Machine: Inside the CPython interpreter
Bytes in the Machine: Inside the CPython interpreterBytes in the Machine: Inside the CPython interpreter
Bytes in the Machine: Inside the CPython interpreter
akaptur
 
Assignment no39
Assignment no39Assignment no39
Assignment no39
Jay Patel
 

What's hot (20)

The Browser Environment - A Systems Programmer's Perspective
The Browser Environment - A Systems Programmer's PerspectiveThe Browser Environment - A Systems Programmer's Perspective
The Browser Environment - A Systems Programmer's Perspective
 
Implementing virtual machines in go & c 2018 redux
Implementing virtual machines in go & c 2018 reduxImplementing virtual machines in go & c 2018 redux
Implementing virtual machines in go & c 2018 redux
 
All I know about rsc.io/c2go
All I know about rsc.io/c2goAll I know about rsc.io/c2go
All I know about rsc.io/c2go
 
Diving into byte code optimization in python
Diving into byte code optimization in python Diving into byte code optimization in python
Diving into byte code optimization in python
 
Let's golang
Let's golangLet's golang
Let's golang
 
Going Loopy: Adventures in Iteration with Go
Going Loopy: Adventures in Iteration with GoGoing Loopy: Adventures in Iteration with Go
Going Loopy: Adventures in Iteration with Go
 
Go: It's Not Just For Google
Go: It's Not Just For GoogleGo: It's Not Just For Google
Go: It's Not Just For Google
 
Byterun, a Python bytecode interpreter - Allison Kaptur at NYCPython
Byterun, a Python bytecode interpreter - Allison Kaptur at NYCPythonByterun, a Python bytecode interpreter - Allison Kaptur at NYCPython
Byterun, a Python bytecode interpreter - Allison Kaptur at NYCPython
 
Allison Kaptur: Bytes in the Machine: Inside the CPython interpreter, PyGotha...
Allison Kaptur: Bytes in the Machine: Inside the CPython interpreter, PyGotha...Allison Kaptur: Bytes in the Machine: Inside the CPython interpreter, PyGotha...
Allison Kaptur: Bytes in the Machine: Inside the CPython interpreter, PyGotha...
 
C++ Lambda and concurrency
C++ Lambda and concurrencyC++ Lambda and concurrency
C++ Lambda and concurrency
 
4. Обработка ошибок, исключения, отладка
4. Обработка ошибок, исключения, отладка4. Обработка ошибок, исключения, отладка
4. Обработка ошибок, исключения, отладка
 
Go ahead, make my day
Go ahead, make my dayGo ahead, make my day
Go ahead, make my day
 
Are we ready to Go?
Are we ready to Go?Are we ready to Go?
Are we ready to Go?
 
Network lap pgms 7th semester
Network lap pgms 7th semesterNetwork lap pgms 7th semester
Network lap pgms 7th semester
 
Playing 44CON CTF for fun and profit
Playing 44CON CTF for fun and profitPlaying 44CON CTF for fun and profit
Playing 44CON CTF for fun and profit
 
Network lab manual
Network lab manualNetwork lab manual
Network lab manual
 
Implementing Virtual Machines in Go & C
Implementing Virtual Machines in Go & CImplementing Virtual Machines in Go & C
Implementing Virtual Machines in Go & C
 
Computer Networks Lab File
Computer Networks Lab FileComputer Networks Lab File
Computer Networks Lab File
 
Bytes in the Machine: Inside the CPython interpreter
Bytes in the Machine: Inside the CPython interpreterBytes in the Machine: Inside the CPython interpreter
Bytes in the Machine: Inside the CPython interpreter
 
Assignment no39
Assignment no39Assignment no39
Assignment no39
 

Viewers also liked

DIPLOMA Certificte
DIPLOMA CertificteDIPLOMA Certificte
DIPLOMA Certificte
masthan213
 
Assmang Vacation Training Certificate
Assmang Vacation Training CertificateAssmang Vacation Training Certificate
Assmang Vacation Training Certificate
Pieter Storm
 
Websites with Tiffany Truffo PBC
Websites with Tiffany Truffo PBCWebsites with Tiffany Truffo PBC
Websites with Tiffany Truffo PBC
caseytruffo
 

Viewers also liked (14)

DIPLOMA Certificte
DIPLOMA CertificteDIPLOMA Certificte
DIPLOMA Certificte
 
Assmang Vacation Training Certificate
Assmang Vacation Training CertificateAssmang Vacation Training Certificate
Assmang Vacation Training Certificate
 
resume (3)
resume (3)resume (3)
resume (3)
 
WRT 205 U3
WRT 205 U3WRT 205 U3
WRT 205 U3
 
Websites with Tiffany Truffo PBC
Websites with Tiffany Truffo PBCWebsites with Tiffany Truffo PBC
Websites with Tiffany Truffo PBC
 
MSU Transcript
MSU TranscriptMSU Transcript
MSU Transcript
 
Creating a Dynamic, Reactive Communication Model from Scratch
Creating a Dynamic, Reactive  Communication Model from ScratchCreating a Dynamic, Reactive  Communication Model from Scratch
Creating a Dynamic, Reactive Communication Model from Scratch
 
b-TECH DEGREE
b-TECH DEGREEb-TECH DEGREE
b-TECH DEGREE
 
Report w13
Report w13Report w13
Report w13
 
Internal Communication Plan
Internal Communication PlanInternal Communication Plan
Internal Communication Plan
 
TokyoR LT Rで連続データを離散化
TokyoR LT Rで連続データを離散化TokyoR LT Rで連続データを離散化
TokyoR LT Rで連続データを離散化
 
Artículo ley de reforma al código del trabajo (revisado)
Artículo ley de reforma al código del trabajo (revisado)Artículo ley de reforma al código del trabajo (revisado)
Artículo ley de reforma al código del trabajo (revisado)
 
エクセル統計の使い方(重回帰分析編)
エクセル統計の使い方(重回帰分析編)エクセル統計の使い方(重回帰分析編)
エクセル統計の使い方(重回帰分析編)
 
how to use the virtual keyboard
how to use the virtual keyboardhow to use the virtual keyboard
how to use the virtual keyboard
 

Similar to Implementing Software Machines in Go and C

DATA STRUCTURE USING C & C++
DATA STRUCTURE USING C & C++DATA STRUCTURE USING C & C++
DATA STRUCTURE USING C & C++
mustkeem khan
 
C basics
C basicsC basics
C basics
MSc CST
 
Data structure new lab manual
Data structure  new lab manualData structure  new lab manual
Data structure new lab manual
SANTOSH RATH
 

Similar to Implementing Software Machines in Go and C (20)

Concepts of C [Module 2]
Concepts of C [Module 2]Concepts of C [Module 2]
Concepts of C [Module 2]
 
String Manipulation Function and Header File Functions
String Manipulation Function and Header File FunctionsString Manipulation Function and Header File Functions
String Manipulation Function and Header File Functions
 
VTU Data Structures Lab Manual
VTU Data Structures Lab ManualVTU Data Structures Lab Manual
VTU Data Structures Lab Manual
 
DATA STRUCTURE USING C & C++
DATA STRUCTURE USING C & C++DATA STRUCTURE USING C & C++
DATA STRUCTURE USING C & C++
 
DSU C&C++ Practical File Diploma
DSU C&C++ Practical File DiplomaDSU C&C++ Practical File Diploma
DSU C&C++ Practical File Diploma
 
Cpds lab
Cpds labCpds lab
Cpds lab
 
Functions
FunctionsFunctions
Functions
 
Blocks+gcd入門
Blocks+gcd入門Blocks+gcd入門
Blocks+gcd入門
 
Phil Bartie QGIS PLPython
Phil Bartie QGIS PLPythonPhil Bartie QGIS PLPython
Phil Bartie QGIS PLPython
 
III MCS python lab (1).pdf
III MCS python lab (1).pdfIII MCS python lab (1).pdf
III MCS python lab (1).pdf
 
Scala 2 + 2 > 4
Scala 2 + 2 > 4Scala 2 + 2 > 4
Scala 2 + 2 > 4
 
C basics
C basicsC basics
C basics
 
7 functions
7  functions7  functions
7 functions
 
An imperative study of c
An imperative study of cAn imperative study of c
An imperative study of c
 
Go Says WAT?
Go Says WAT?Go Says WAT?
Go Says WAT?
 
Data structure new lab manual
Data structure  new lab manualData structure  new lab manual
Data structure new lab manual
 
An Intro To ES6
An Intro To ES6An Intro To ES6
An Intro To ES6
 
Imugi: Compiler made with Python
Imugi: Compiler made with PythonImugi: Compiler made with Python
Imugi: Compiler made with Python
 
Tu1
Tu1Tu1
Tu1
 
L25-L26-Parameter passing techniques.pptx
L25-L26-Parameter passing techniques.pptxL25-L26-Parameter passing techniques.pptx
L25-L26-Parameter passing techniques.pptx
 

More from Eleanor McHugh

More from Eleanor McHugh (20)

[2023] Putting the R! in R&D.pdf
[2023] Putting the R! in R&D.pdf[2023] Putting the R! in R&D.pdf
[2023] Putting the R! in R&D.pdf
 
Generics, Reflection, and Efficient Collections
Generics, Reflection, and Efficient CollectionsGenerics, Reflection, and Efficient Collections
Generics, Reflection, and Efficient Collections
 
The Relevance of Liveness - Biometrics and Data Integrity
The Relevance of Liveness - Biometrics and Data IntegrityThe Relevance of Liveness - Biometrics and Data Integrity
The Relevance of Liveness - Biometrics and Data Integrity
 
The Browser Environment - A Systems Programmer's Perspective [sinatra edition]
The Browser Environment - A Systems Programmer's Perspective [sinatra edition]The Browser Environment - A Systems Programmer's Perspective [sinatra edition]
The Browser Environment - A Systems Programmer's Perspective [sinatra edition]
 
Go for the paranoid network programmer, 3rd edition
Go for the paranoid network programmer, 3rd editionGo for the paranoid network programmer, 3rd edition
Go for the paranoid network programmer, 3rd edition
 
An introduction to functional programming with Go [redux]
An introduction to functional programming with Go [redux]An introduction to functional programming with Go [redux]
An introduction to functional programming with Go [redux]
 
An introduction to functional programming with go
An introduction to functional programming with goAn introduction to functional programming with go
An introduction to functional programming with go
 
Identity & trust in Monitored Spaces
Identity & trust in Monitored SpacesIdentity & trust in Monitored Spaces
Identity & trust in Monitored Spaces
 
Don't Ask, Don't Tell - The Virtues of Privacy By Design
Don't Ask, Don't Tell - The Virtues of Privacy By DesignDon't Ask, Don't Tell - The Virtues of Privacy By Design
Don't Ask, Don't Tell - The Virtues of Privacy By Design
 
Don't ask, don't tell the virtues of privacy by design
Don't ask, don't tell   the virtues of privacy by designDon't ask, don't tell   the virtues of privacy by design
Don't ask, don't tell the virtues of privacy by design
 
Anonymity, identity, trust
Anonymity, identity, trustAnonymity, identity, trust
Anonymity, identity, trust
 
Going Loopy - Adventures in Iteration with Google Go
Going Loopy - Adventures in Iteration with Google GoGoing Loopy - Adventures in Iteration with Google Go
Going Loopy - Adventures in Iteration with Google Go
 
Distributed Ledgers: Anonymity & Immutability at Scale
Distributed Ledgers: Anonymity & Immutability at ScaleDistributed Ledgers: Anonymity & Immutability at Scale
Distributed Ledgers: Anonymity & Immutability at Scale
 
Hello Go
Hello GoHello Go
Hello Go
 
Go for the paranoid network programmer, 2nd edition
Go for the paranoid network programmer, 2nd editionGo for the paranoid network programmer, 2nd edition
Go for the paranoid network programmer, 2nd edition
 
Finding a useful outlet for my many Adventures in go
Finding a useful outlet for my many Adventures in goFinding a useful outlet for my many Adventures in go
Finding a useful outlet for my many Adventures in go
 
Anonymity, trust, accountability
Anonymity, trust, accountabilityAnonymity, trust, accountability
Anonymity, trust, accountability
 
Implementing Virtual Machines in Ruby & C
Implementing Virtual Machines in Ruby & CImplementing Virtual Machines in Ruby & C
Implementing Virtual Machines in Ruby & C
 
Privacy is always a requirement
Privacy is always a requirementPrivacy is always a requirement
Privacy is always a requirement
 
Hybrid Cryptography with examples in Ruby and Go
Hybrid Cryptography with examples in Ruby and GoHybrid Cryptography with examples in Ruby and Go
Hybrid Cryptography with examples in Ruby and Go
 

Recently uploaded

%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
masabamasaba
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
mohitmore19
 
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfintroduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
VishalKumarJha10
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
VictorSzoltysek
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
Health
 

Recently uploaded (20)

SHRMPro HRMS Software Solutions Presentation
SHRMPro HRMS Software Solutions PresentationSHRMPro HRMS Software Solutions Presentation
SHRMPro HRMS Software Solutions Presentation
 
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
 
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdfPayment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
 
10 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 202410 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 2024
 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
 
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park %in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
 
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfintroduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
 
%in Lydenburg+277-882-255-28 abortion pills for sale in Lydenburg
%in Lydenburg+277-882-255-28 abortion pills for sale in Lydenburg%in Lydenburg+277-882-255-28 abortion pills for sale in Lydenburg
%in Lydenburg+277-882-255-28 abortion pills for sale in Lydenburg
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
Generic or specific? Making sensible software design decisions
Generic or specific? Making sensible software design decisionsGeneric or specific? Making sensible software design decisions
Generic or specific? Making sensible software design decisions
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
Define the academic and professional writing..pdf
Define the academic and professional writing..pdfDefine the academic and professional writing..pdf
Define the academic and professional writing..pdf
 

Implementing Software Machines in Go and C

  • 1. implementing software machines in Go and C Eleanor McHugh @feyeleanor
  • 2. this is a talk about VMs system virtualisation hardware emulation abstract virtual machines
  • 4. this is a talk about VMs system virtualisation hardware emulation abstract virtual machines
  • 6. this is a talk about VMs system virtualisation hardware emulation abstract virtual machines
  • 8. this is a talk about VMs system virtualisation hardware emulation abstract virtual machines
  • 9. inspired by hardware discrete components processors storage communications
  • 11.
  • 12.
  • 13.
  • 14. #include <stdio.h> #define STACK_MAX 100 typedef enum { STACK_OK = 0, STACK_OVERFLOW, STACK_UNDERFLOW } STACK_STATUS; typedef struct stack STACK; struct stack { int data[STACK_MAX]; int size; }; STACK *NewStack() { STACK s; s.size = 0; return &s; } STACK_STATUS push(STACK *s, int data) { if (s->size < STACK_MAX) { s->data[s->size++] = data; return STACK_OK; } return STACK_OVERFLOW; } STACK_STATUS pop(STACK *s, int *r) { if (s->size > 0) { *r = s->data[s->size - 1]; s->size--; return STACK_OK; } return STACK_UNDERFLOW; } int main() { int l, r; STACK *s = NewStack(); push(s, 1); push(s, 3); pop(s, &l); pop(s, &r); printf("%d + %d = %dn", l, r, l + r); } c: array stack
  • 15. package main import "fmt" type stack_status int const ( STACK_OK = stack_status(iota) STACK_OVERFLOW STACK_UNDERFLOW ) type stack struct { data []int } func (s *stack) Push(data int) { s.data = append(s.data, data) } func (s *stack) Pop() (int, stack_status) { if s == nil || len(s.data) < 1 { return 0, STACK_UNDERFLOW } sp := len(s.data) - 1 r := s.data[sp] s.data = s.data[:sp] return r, STACK_OK } func main() { s := new(stack) s.Push(1) s.Push(3) l, _ := s.Pop() r, _ := s.Pop() fmt.Printf("%d + %d = %dn", l, r, l+r) } go: array stack
  • 16. #include <stdio.h> #include <stdlib.h> typedef struct stack STACK; struct stack { int data; STACK *next; }; STACK *push(STACK *s, int data) { STACK *r = malloc(sizeof(STACK)); r->data = data; r->next = s; return r; } STACK *pop(STACK *s, int *r) { if (s == NULL) exit(1); *r = s->data; return s->next; } int main() { int l, r; STACK *s = push(NULL, 1); s = push(s, 3); pop(pop(s, &r), &l); printf("%d + %d = %dn", l, r, l + r); } c: functional cactus stack
  • 17. package main import "fmt" type stack struct { data int tail *stack } func (s *stack) Push(v int) (r *stack) { r = &stack{data: v, tail: s} return } func (s *stack) Pop() (v int, r *stack) { return s.data, s.tail } func main() { var l, r int var s *stack s = s.Push(1).Push(3) l, s = s.Pop() r, s = s.Pop() fmt.Printf("%d + %d = %dn", l, r, l+r) } go: functional cactus stack
  • 18. #include <stdio.h> #include <stdlib.h> typedef struct stack STACK; struct stack { int data; STACK *next; }; STACK *push(STACK *s, int data) { STACK *r = malloc(sizeof(STACK)); r->data = data; r->next = s; return r; } STACK *pop(STACK *s, int *r) { if (s == NULL) exit(1); *r = s->data; return s->next; } int sum(STACK *tos) { int a, p; a = 0; for (; tos != NULL;) { tos = pop(tos, &p); a += p; } return a; } int main() { STACK *s1 = push(NULL, 7); STACK *s2 = push(push(s1, 7), 11); s1 = push(push(push(s1, 2), 9), 4); STACK *s3 = push(s1, 17); s1 = push(s1, 3); printf("sum = %dn", sum(s1)); printf("sum = %dn", sum(s2)); printf("sum = %dn", sum(s3)); } c: functional cactus stack
  • 19. package main import "fmt" type stack struct { data int tail *stack } func (s *stack) Push(v int) (r *stack) { r = &stack{data: v, tail: s} return } func (s *stack) Pop() (v int, r *stack) { return s.data, s.tail } func (s *stack) Sum() (r int) { for p := 0; s != nil; r += p { p, s = s.Pop() } return } func main() { var s1, s2, s3 *stack s1 = s1.Push(7) s2 = s1.Push(7).Push(11) s1 = s1.Push(2).Push(9).Push(4) s3 = s1.Push(17) s1 = s1.Push(3) fmt.Printf("sum = %vn", s1.Sum()) fmt.Printf("sum = %vn", s2.Sum()) fmt.Printf("sum = %vn", s3.Sum()) } go: functional cactus stack
  • 21. dispatch loops read next instruction via a program counter determine the operation to perform execute the operation and adjust machine state
  • 22. switch interpreter instructions stored sequentially in memory each represented by a token or opcode available in all implementation languages tokens can be compact - often single bytes
  • 23. #include <stdio.h> #include <stdlib.h> typedef struct stack STACK; struct stack { int data; STACK *next; }; STACK *push(STACK *s, int data) { STACK *r = malloc(sizeof(STACK)); r->data = data; r->next = s; return r; } STACK *pop(STACK *s, int *r) { if (s == NULL) exit(1); *r = s->data; return s->next; } typedef enum { PUSH = 0, ADD, PRINT, EXIT } opcodes; STACK *S; void interpret(int *PC) { int l, r; while (1) { switch(*PC++) { case PUSH: S = push(S, *PC++); break; case ADD: S = pop(S, &l); S = pop(S, &r); S = push(S, l + r); break; case PRINT: printf(“%d + %d = %dn, l, r, S->data); break; case EXIT: return; } } } int main() { int program [] = { (int)PUSH, 13, (int)PUSH, 28, (int)ADD, PRINT, EXIT, }; interpret(program); } c: switch interpreter
  • 24. #include <stdio.h> #include <stdlib.h> typedef struct stack STACK; struct stack { int data; STACK *next; }; STACK *push(STACK *s, int data) { STACK *r = malloc(sizeof(STACK)); r->data = data; r->next = s; return r; } STACK *pop(STACK *s, int *r) { if (s == NULL) exit(1); *r = s->data; return s->next; } typedef enum { PUSH = 0, ADD, PRINT, EXIT } opcodes; STACK *S; #define READ_OPCODE *PC++ void interpret(int *PC) { int l, r; while (1) { switch(READ_OPCODE) { case PUSH: S = push(S, READ_OPCODE); break; case ADD: S = pop(S, &l); S = pop(S, &r); S = push(S, l + r); break; case PRINT: printf(“%d + %d = %dn, l, r, S->data); break; case EXIT: return; } } } int main() { int program [] = { (int)PUSH, 13, (int)PUSH, 28, (int)ADD, PRINT, EXIT, }; interpret(program); } c: switch interpreter
  • 25. package main import "fmt" func main() { var program = []interface{}{ PUSH, 13, PUSH, 28, ADD, PRINT, EXIT, } interpret(program) } type stack struct { data int tail *stack } func (s *stack) Push(v int) (r *stack) { r = &stack{data: v, tail: s} return } func (s *stack) Pop() (v int, r *stack) { return s.data, s.tail } type OPCODE int const ( PUSH = OPCODE(iota) ADD PRINT EXIT ) func interpret(p []interface{}) { var l, r int S := new(stack) for PC := 0; ; PC++ { if op, ok := p[PC].(OPCODE); ok { switch op { case PUSH: PC++ S = S.Push(p[PC].(int)) case ADD: l, S, = S.Pop() r, S = S.Pop() S = S.Push(l + r) case PRINT: fmt.Printf("%v + %v = %vn", l, r, S.data) case EXIT: return } } else { return } } } go: switch interpreter
  • 26. direct call threading instructions stored sequentially in memory each represented by a pointer to a function not available in all languages instructions each require a machine word
  • 27. #include <stdio.h> #include <stdlib.h> typedef struct stack STACK; struct stack { int data; STACK *next; }; STACK *push(STACK *s, int data) { STACK *r = malloc(sizeof(STACK)); r->data = data; r->next = s; return r; } STACK *pop(STACK *s, int *r) { if (s == NULL) exit(1); *r = s->data; return s->next; } typedef void (*opcode)(); STACK *S; opcode *PC; void op_push() { S = push(S, (int)(long)(*PC++)); } void op_add_and_print() { int l, r; S = pop(S, &l); S = pop(S, &r); S = push(S, l + r); printf("%d + %d = %dn", l, r, S->data); } void op_exit() { exit(0); } int main() { opcode program [] = { op_push, (opcode)(long)13, op_push, (opcode)(long)28, op_add_and_print, op_exit }; PC = program; while (1) { (*PC++)(); } } c: direct call-threaded interpreter
  • 28. #include <stdio.h> #include <stdlib.h> typedef struct stack STACK; struct stack { int data; STACK *next; }; STACK *push(STACK *s, int data) { STACK *r = malloc(sizeof(STACK)); r->data = data; r->next = s; return r; } STACK *pop(STACK *s, int *r) { if (s == NULL) exit(1); *r = s->data; return s->next; } typedef void (*opcode)(); STACK *S; opcode *PC; #define READ_OPCODE *PC++ void op_push() { S = push(S, (int)(long)(READ_OPCODE)); } void op_add_and_print() { int l, r; S = pop(S, &l); S = pop(S, &r); S = push(S, l + r); printf("%d + %d = %dn", l, r, S->data); } void op_exit() { exit(0); } int main() { opcode program [] = { op_push, (opcode)(long)13, op_push, (opcode)(long)28, op_add_and_print, op_exit }; PC = program; while (1) { (READ_OPCODE)(); } } c: direct call-threaded interpreter
  • 29. package main import "fmt" import "os" func main() { p := new(Interpreter) p.m = []interface{}{ p.Push, 13, p.Push, 28, p.Add, p.Print, p.Exit, } p.Run() } type stack struct { data int tail *stack } func (s *stack) Push(v int) (r *stack) { r = &stack{data: v, tail: s} return } func (s *stack) Pop() (v int, r *stack) { return s.data, s.tail } type Interpreter struct { S *stack l, r, PC int m []interface{} } func (i *Interpreter) opcode() func() { return i.m[i.PC].(func()) } func (i *Interpreter) operand() int { return i.m[i.PC].(int) } func (i *Interpreter) Run() { for { i.opcode()() i.PC++ } } func (i *Interpreter) Push() { i.PC++ i.S = i.S.Push(i.operand()) } func (i *Interpreter) Add() { i.l, i.S = i.S.Pop() i.r, i.S = i.S.Pop() i.S = i.S.Push(i.l + i.r) } func (i *Interpreter) Print() { fmt.Printf("%v + %v = %vn", i.l, i.r, i.S.data) } func (i *Interpreter) Exit() { os.Exit(0) } go: direct call-threaded interpreter
  • 30. indirect threading instructions stored sequentially in memory each represented by a local jump label gcc/clang specific C extension instructions indirectly load successor
  • 31. #include <stdio.h> #include <stdlib.h> typedef struct stack STACK; struct stack { int data; STACK *next; }; STACK *push(STACK *s, int data) { STACK *r = malloc(sizeof(STACK)); r->data = data; r->next = s; return r; } STACK *pop(STACK *s, int *r) { if (s == NULL) exit(1); *r = s->data; return s->next; } typedef enum { PUSH = 0, ADD, EXIT } opcodes; STACK *S; void interpret(int *program) { static void *opcodes [] = { &&op_push, &&op_add, &&op_print, &&op_exit }; int l, r; int *PC = program; goto *opcodes[*PC++]; op_push: S = push(S, *PC++); goto *opcodes[*PC++]; op_add: S = pop(S, &l); S = pop(S, &r); S = push(S, l + r); goto *opcodes[*PC++]; op_print: printf("%d + %d = %dn", l, r, S->data); goto *opcodes[*PC++]; op_exit: return; } int main() { int program [] = { PUSH, 13, PUSH, 28, ADD, EXIT }; interpret(program); } c: indirect-threaded interpreter
  • 32. #include <stdio.h> #include <stdlib.h> typedef struct stack STACK; struct stack { int data; STACK *next; }; STACK *push(STACK *s, int data) { STACK *r = malloc(sizeof(STACK)); r->data = data; r->next = s; return r; } STACK *pop(STACK *s, int *r) { if (s == NULL) exit(1); *r = s->data; return s->next; } typedef enum { PUSH = 0, ADD, PRINT, EXIT } opcodes; STACK *S; #define READ_OPCODE *PC++ #define EXECUTE_OPCODE goto *opcodes[READ_OPCODE]; #define PRIMITIVE(name, body) name: body; EXECUTE_OPCODE void interpret(int *program) { static void *opcodes [] = { &&op_push, &&op_add, &&op_print, &&op_exit }; int l, r; int *PC = program; EXECUTE_OPCODE; PRIMITIVE(op_push, S = push(S, READ_OPCODE)) PRIMITIVE(op_add, S = pop(S, &l); S = pop(S, &r); S = push(S, l + r); ) PRIMITIVE(op_print, printf("%d + %d = %dn", l, r, S->data)) PRIMITIVE(op_exit, return) } int main() { int program [] = { PUSH, 13, PUSH, 28, ADD, PRINT, EXIT }; interpret(program); } c: indirect-threaded interpreter
  • 33. direct threading instructions stored sequentially in memory each represented by a local jump label gcc/clang specific C extension instructions directly load successors
  • 34. #include <stdio.h> #include <stdlib.h> typedef struct stack STACK; struct stack { int data; STACK *next; }; STACK *push(STACK *s, int data) { STACK *r = malloc(sizeof(STACK)); r->data = data; r->next = s; return r; } STACK *pop(STACK *s, int *r) { if (s == NULL) exit(1); *r = s->data; return s->next; } typedef enum { PUSH = 0, ADD, PRINT, EXIT } opcodes; STACK *S; void **compile(int *PC, int words, void *despatch_table[]) { static void *compiler [] = { &&comp_push, &&comp_add, &&comp_print, &&comp_exit }; if (words < 1) return NULL; void **program = malloc(sizeof(void *) * words); void **cp = program; goto *compiler[*PC++]; comp_push: *cp++ = despatch_table[PUSH]; *cp++ = (void *)(long)*PC++; words -= 2; if (words == 0) return program; goto *compiler[*PC++]; comp_add: *cp++ = despatch_table[ADD]; words--; if (words == 0) return program; goto *compiler[*PC++]; comp_print: *cp++ = despatch_table[PRINT]; words--; if (words == 0) return program; goto *compiler[*PC++]; comp_exit: *cp++ = despatch_table[EXIT]; words--; if (words == 0) return program; goto *compiler[*PC++]; } c: direct-threaded interpreter (1)
  • 35. void interpret(int *PC, int words) { static void *despatch_table[] = { &&op_push, &&op_add, &&op_print, &&op_exit }; int l, r; void **program = compile(PC, words, despatch_table); if (program == NULL) exit(1); goto **program++; op_push: S = push(S, (int)(long)*program++); goto **program++; op_add: S = pop(S, &l); S = pop(S, &r); S = push(S, l + r); goto **program++; op_print: printf("%d + %d = %dn", l, r, S->data); goto **program++; op_exit: return; } int main() { int program[] = { PUSH, 13, PUSH, 28, ADD, PRINT, EXIT }; interpret(program, 7); } c: direct-threaded interpreter (2)
  • 36. #include <stdio.h> #include <stdlib.h> typedef struct stack STACK; struct stack { int data; STACK *next; }; STACK *push(STACK *s, int data) { STACK *r = malloc(sizeof(STACK)); r->data = data; r->next = s; return r; } STACK *pop(STACK *s, int *r) { if (s == NULL) exit(1); *r = s->data; return s->next; } typedef enum { PUSH = 0, ADD, PRINT, EXIT } opcodes; STACK *S; #define COMPILE(body) COMPILE_NEXT_OPCODE body #define COMPILE_NEXT_OPCODE if (words < 1) return program; goto *compiler[*PC++]; #define DESCRIBE_PRIMITIVE(name, body) name: body; COMPILE_NEXT_OPCODE #define WRITE_OPCODE(value) *cp++ = value; words--; void **compile(int *PC, int words, void *despatch_table[]) { static void *compiler[] = { &&push, &&add, &&print, &&exit }; void **program = malloc(sizeof(void *) * words); void **cp = program; COMPILE( DESCRIBE_PRIMITIVE(push, WRITE_OPCODE(despatch_table[PUSH]) WRITE_OPCODE((void *)(long)*PC++)) DESCRIBE_PRIMITIVE(add, WRITE_OPCODE(despatch_table[ADD])) DESCRIBE_PRIMITIVE(print, WRITE_OPCODE(despatch_table[PRINT])) DESCRIBE_PRIMITIVE(exit, WRITE_OPCODE(despatch_table[EXIT])) ) } c: direct-threaded interpreter (1)
  • 37. #define READ_OPCODE *program++ #define EXECUTE_OPCODE goto *READ_OPCODE; #define PRIMITIVE(name, body) name: body; EXECUTE_OPCODE void interpret(int *PC, int words) { static void *despatch_table[] = { &&push, &&add, &&print, &&exit }; int l, r; void **program = compile(PC, words, despatch_table); if (program == NULL) exit(1); EXECUTE( PRIMITIVE(push, S = push(S, (int)(long)READ_OPCODE)) PRIMITIVE(add, S = pop(S, &l); S = pop(S, &r); S = push(S, l + r)) PRIMITIVE(print, printf("%d + %d = %dn", l, r, S->data)) PRIMITIVE(exit, return) ) } int main() { int program[] = { PUSH, 13, PUSH, 28, ADD, PRINT, EXIT }; interpret(program, 7); } c: direct-threaded interpreter (2)