on master help sign in
Starting to make new RTS work
commit204d938cab75f80fcd3548e12b1a1fe9afd9173b authorEdwin Brady <eb@cs.st-andrews.ac.uk> dateThu 30 Aug 2012, 17:17 (14 years ago) parent1a7ae4d
3 files changed+218−95
iif/ctest.c+99 rts/closure.c+48−43 rts/closure.h+71−52
iif/ctest.cnew file+99
@@ -0,0 +1,99 @@
1+#include <closure.h>
2+
3+void plus(VM* vm, VAL* oldbase) {
4+ INITFRAME;
5+ RESERVE(2);
6+ ADDTOP(2);
7+
8+ switch(TAG(LOC(0))) {
9+ case 0:
10+// PROJECT(vm, LOC(0), 2, 0);
11+ RVAL = LOC(1);
12+ TOPBASE(0);
13+ REBASE;
14+ break;
15+ case 1:
16+ PROJECT(vm, LOC(0), 2, 1);
17+ RESERVE(2);
18+ TOP(0) = LOC(2);
19+ TOP(1) = LOC(1);
20+ STOREOLD;
21+ BASETOP(0);
22+ ADDTOP(2);
23+ CALL(plus);
24+ LOC(3) = RVAL;
25+ RVAL = MKCON(vm, 1, 1, LOC(3));
26+ TOPBASE(0);
27+ REBASE;
28+ break;
29+ }
30+}
31+
32+void natToInt(VM* vm, VAL* oldbase) {
33+ INITFRAME;
34+ RESERVE(3);
35+ ADDTOP(3);
36+
37+ switch(TAG(LOC(0))) {
38+ case 0:
39+ // PROJECT(vm, LOC(0), 2, 0);
40+ RVAL = MKINT(0);
41+ TOPBASE(0);
42+ REBASE;
43+ break;
44+ case 1:
45+ PROJECT(vm, LOC(0), 1, 1);
46+ RESERVE(1);
47+ TOP(0) = LOC(1);
48+ STOREOLD;
49+ BASETOP(0);
50+ ADDTOP(1);
51+ CALL(natToInt);
52+ LOC(2) = RVAL;
53+ RVAL = ADD(LOC(2), MKINT(1));
54+ TOPBASE(0);
55+ REBASE;
56+ break;
57+ }
58+}
59+
60+int main() {
61+ INITFRAME;
62+ VM* vm = init_vm(100,100);
63+
64+ RESERVE(2);
65+ ADDTOP(2);
66+
67+ LOC(0) = MKCON(vm, 0, 0);
68+ LOC(0) = MKCON(vm, 1, 1, LOC(0));
69+ LOC(0) = MKCON(vm, 1, 1, LOC(0));
70+
71+ dumpVal(LOC(0));
72+ printf("\n");
73+
74+ LOC(1) = MKCON(vm, 0, 0);
75+ LOC(1) = MKCON(vm, 1, 1, LOC(1));
76+ LOC(1) = MKCON(vm, 1, 1, LOC(1));
77+
78+ RESERVE(2);
79+ TOP(0) = LOC(0);
80+ TOP(1) = LOC(1);
81+
82+ STOREOLD;
83+ BASETOP(0);
84+ ADDTOP(2);
85+ CALL(plus);
86+ LOC(0) = RVAL;
87+
88+ RESERVE(1);
89+ TOP(0) = LOC(0);
90+ STOREOLD;
91+ BASETOP(0);
92+ ADDTOP(1);
93+ CALL(natToInt);
94+ LOC(0) = RVAL;
95+
96+ printf("%ld\n", GETINT(LOC(0)));
97+
98+ printf("%d %d\n", vm->valstack, vm->valstack_base);
99+}
rts/closure.c+48−43
@@ -2,6 +2,7 @@
22#include <stdio.h>
33#include <string.h>
44#include <unistd.h>
5+#include <stdarg.h>
56
67#include "closure.h"
78
@@ -12,13 +13,15 @@ VM* init_vm(int stack_size, size_t heap_size) {
1213
1314 VM* vm = malloc(sizeof(VM));
1415 vm -> valstack = valstack;
15− vm -> valstack_ptr = valstack;
16+ vm -> valstack_top = valstack;
17+ vm -> valstack_base = valstack;
1618 vm -> intstack = intstack;
1719 vm -> intstack_ptr = intstack;
1820 vm -> floatstack = floatstack;
1921 vm -> floatstack_ptr = floatstack;
2022 vm -> stack_max = stack_size;
2123 vm -> heap = malloc(heap_size);
24+ vm -> heap_next = vm -> heap;
2225 vm -> ret = NULL;
2326 return vm;
2427}
@@ -27,78 +30,80 @@ void* allocate(VM* vm, int size) {
2730 return malloc(size); // TMP!
2831}
2932
30−void* allocThunk(VM* vm, int argspace) {
31− Closure* cl = allocate(vm, sizeof(ClosureType) +
32− sizeof(VAL) * (argspace + 1) +
33− sizeof(int) * 2);
34− cl -> ty = THUNK;
35− return (void*)cl;
36−}
37−
3833void* allocCon(VM* vm, int arity) {
3934 Closure* cl = allocate(vm, sizeof(ClosureType) +
40− sizeof(int) +
41− sizeof(VAL) * arity);
35+ sizeof(con));
4236 cl -> ty = CON;
37+ if (arity == 0) {
38+ cl -> info.c.args = NULL;
39+ } else {
40+ cl -> info.c.args = allocate(vm, sizeof(VAL)*arity);
41+ }
4342 return (void*)cl;
4443}
4544
46−VAL mkInt(VM* vm, int val) {
47− Closure* cl = allocate(vm, sizeof(ClosureType) + sizeof(int));
48− cl -> ty = INT;
49− cl -> info.i = val;
50− return cl;
51−}
52−
53−VAL mkFloat(VM* vm, double val) {
45+VAL MKFLOAT(VM* vm, double val) {
5446 Closure* cl = allocate(vm, sizeof(ClosureType) + sizeof(double));
5547 cl -> ty = FLOAT;
5648 cl -> info.f = val;
5749 return cl;
5850}
5951
60−VAL mkStr(VM* vm, char* str) {
61− Closure* cl = allocate(vm, sizeof(ClosureType) + sizeof(char*) * strlen(str));
52+VAL MKSTR(VM* vm, char* str) {
53+ Closure* cl = allocate(vm, sizeof(ClosureType) + sizeof(char*));
6254 cl -> ty = STRING;
55+ cl -> info.str = allocate(vm, sizeof(char)*strlen(str)+1);
6356 strcpy(cl -> info.str, str);
6457 return cl;
6558}
6659
67−VAL mkThunk(VM* vm, func fn, int args, int arity) {
60+VAL MKCON(VM* vm, int tag, int arity, ...) {
61+ Closure* cl;
6862 int i;
69− Closure* cl = allocThunk(vm, arity);
70− cl -> info.t.fn = fn;
71− cl -> info.t.arity = arity;
72− cl -> info.t.numargs = args;
73− VAL** argptr = &(cl -> info.t.args);
74−
75− for (i = 0; i < args; ++i) {
76− VAL* v = POP;
77− *argptr++ = v;
78− }
79−}
63+ va_list args;
8064
81−VAL mkCon(VM* vm, int tag, int arity) {
82− Closure* cl = allocCon(vm, arity);
65+ va_start(args, arity);
8366
84− int i;
67+ cl = allocCon(vm, arity);
8568 cl -> info.c.tag = tag;
86− VAL** argptr = &(cl -> info.c.args);
69+ cl -> info.c.arity = arity;
70+ VAL* argptr = (VAL*)(cl -> info.c.args);
8771
8872 for (i = 0; i < arity; ++i) {
89− VAL* v = POP;
90− *argptr++ = v;
73+ VAL v = va_arg(args, VAL);
74+ *argptr = v;
75+ argptr++;
9176 }
92−}
77+ va_end(args);
9378
94−// if 'update' is set, update the value at the top of the stack
95−// otherwise, replace it with a new value
79+ return cl;
80+}
9681
97−void EVAL(int update) {
82+void PROJECT(VM* vm, VAL r, int loc, int arity) {
83+ int i;
84+ VAL* argptr = (VAL*)(r -> info.c.args);
9885
86+ for(i = 0; i < arity; ++i) {
87+ LOC(i+loc) = *argptr++;
88+ }
89+}
90+
91+void dumpVal(VAL v) {
92+ int i;
93+ switch(v->ty) {
94+ case CON:
95+ printf("%d[", v->info.c.tag);
96+ for(i = 0; i < v->info.c.arity; ++i) {
97+ VAL* args = (VAL*)v->info.c.args;
98+ dumpVal(args[i]);
99+ }
100+ printf("] ");
101+ }
102+
99103}
100104
101105void stackOverflow() {
102106 fprintf(stderr, "Stack overflow");
103107 exit(-1);
104108}
109+
rts/closure.h+71−52
@@ -1,88 +1,107 @@
11#ifndef _CLOSURE_H
22#define _CLOSURE_H
33
4+#include <stdlib.h>
5+#include <stdio.h>
6+#include <string.h>
7+#include <unistd.h>
8+#include <stdarg.h>
49
510// Closures
6−typedef void* VAL;
11+
12+typedef enum {
13+ CON, INT, FLOAT, STRING, UNIT, PTR
14+} ClosureType;
15+
16+typedef struct {
17+ int tag;
18+ int arity;
19+ void* args;
20+} con;
21+
22+typedef struct {
23+ ClosureType ty;
24+ union {
25+ con c;
26+ int i;
27+ double f;
28+ char* str;
29+ void* ptr;
30+ } info;
31+} Closure;
32+
33+typedef Closure* VAL;
734
835typedef struct {
936 VAL* valstack;
1037 int* intstack;
1138 double* floatstack;
12− VAL* valstack_ptr;
39+ VAL* valstack_top;
40+ VAL* valstack_base;
1341 int* intstack_ptr;
1442 double* floatstack_ptr;
1543 void* heap;
44+ void* heap_next;
1645 int stack_max;
1746 VAL ret;
1847} VM;
1948
2049VM* init_vm(int stack_size, size_t heap_size);
2150
22−// Functions all take a pointer to their VM, and return nothing.
23−typedef void(*func)(VM*);
51+// Functions all take a pointer to their VM, and previous stack base,
52+// and return nothing.
53+typedef void(*func)(VM*, VAL*);
2454
25−#define EXTEND(n) if (vm->valstack_ptr-vm->valstack + n < vm -> stack_max) \
26− { vm->valstack_ptr+=(n) } else { stackOverflow(vm); }
27−#define CLEAR(n) vm->valstack_ptr-=(n)
28−#define SLIDE(drop, keep) \
29− for (i=1; i<=keep; ++i) { \
30− *(vm->valstack_ptr-i-drop) = *(vm->valstack_ptr-i); \
31− } \
32− vm->valstack_ptr-=(drop)
55+// Register access
3356
34−typedef enum {
35− THUNK, CON, INT, FLOAT, STRING, UNIT, PTR
36−} ClosureType;
57+#define RVAL (vm->ret)
58+#define LOC(x) (*(vm->valstack_base + (x)))
59+#define TOP(x) (*(vm->valstack_top + (x)))
3760
38−typedef struct {
39− VAL fn;
40− int arity;
41− int numargs;
42− VAL* args;
43−} thunk;
61+// Retrieving values
4462
45−typedef struct {
46− int tag;
47− VAL* args;
48−} con;
63+#define GETSTR(x) (((VAL)(x))->info.str)
64+#define GETPTR(x) (((void*)(x))->info.ptr)
65+#define GETFLOAT(x) (((double)(x))->info.f)
4966
50−typedef struct {
51− ClosureType ty;
52− union {
53− thunk t;
54− con c;
55− int i;
56− double f;
57− char* str;
58− void* ptr;
59− } info;
60−} Closure;
67+#define TAG(x) ((x)->info.c.tag)
68+
69+// Integers, floats and operators
6170
62−// Stack manipulation instructions
71+typedef intptr_t i_int;
6372
64−#define PUSH(i) *(vm->valstack_ptr++) = i;
65−#define POP --vm->valstack_ptr;
73+#define MKINT(x) ((void*)((x)<<1)+1)
74+#define GETINT(x) ((i_int)(x)>>1)
75+#define ISINT(x) ((((i_int)x)&1) == 1)
6676
67−#define PUSHINT(i) *(vm->intstack_ptr++) = i;
68−#define POPINT --vm->intstack_ptr;
77+#define INTOP(op,x,y) MKINT((i_int)((((i_int)x)>>1) op (((i_int)y)>>1)))
78+#define FLOATOP(op,x,y) MKFLOAT(((GETFLOAT(x)) op (GETFLOAT(y))))
79+#define FLOATBOP(op,x,y) MKINT((i_int)(((GETFLOAT(x)) op (GETFLOAT(y)))))
80+#define ADD(x,y) (void*)(((i_int)x)+(((i_int)y)-1))
81+#define MULT(x,y) (MKINT((((i_int)x)>>1) * (((i_int)y)>>1)))
6982
70−#define PUSHFLOAT(i) *(vm->floatstack_ptr++) = i;
71−#define POPFLOAT --vm->floatstack_ptr;
83+// Stack management
7284
73−#define DISCARD(n) vm->valstack_ptr-=n;
74−#define DISCARDINT(n) vm->intstack_ptr-=n;
75−#define DISCARDFLOAT(n) vm->floatstack_ptr-=n;
85+#define INITFRAME VAL* myoldbase
86+#define REBASE vm->valstack_base = oldbase
87+#define RESERVE(x)
88+#define ADDTOP(x) vm->valstack_top += (x)
89+#define TOPBASE(x) vm->valstack_top = vm->valstack_base + (x)
90+#define BASETOP(x) vm->valstack_base = vm->valstack_top + (x)
91+#define STOREOLD myoldbase = vm->valstack_base
92+
93+#define CALL(f) f(vm, myoldbase);
94+#define TAILCALL(f) f(vm, oldbase);
7695
7796// Creating new values (each value placed at the top of the stack)
78−VAL mkInt(VM* vm, int val);
79−VAL mkFloat(VM* vm, double val);
80−VAL mkStr(VM* vm, char* str);
97+VAL MKFLOAT(VM* vm, double val);
98+VAL MKSTR(VM* vm, char* str);
99+
100+VAL MKCON(VM* vm, int tag, int arity, ...);
81101
82−VAL mkThunk(VM* vm, func fn, int args, int arity);
83−VAL mkCon(VM* vm, int tag, int arity);
102+void PROJECT(VM* vm, VAL r, int loc, int arity);
84103
85−void EVAL(int update);
104+void dumpVal(VAL r);
86105
87106// Handle stack overflow.
88107// Just reports an error and exits.