Monstrous commit smh, made a custom ssa intermediate representation to remove some stack ops, glendasay is about 40% faster (and i'm sure the other ones have some improvement too)
This commit is contained in:
parent
f738034ce4
commit
ca1ee83377
24 changed files with 1018 additions and 176 deletions
|
|
@ -34,7 +34,7 @@ targets = {
|
|||
for f in p:lines() do
|
||||
base = f:match("([^/]+)%.c$")
|
||||
obj = "build/"..base..".o"
|
||||
cc = "cc -c '"..f.."' -o '"..obj.."' "..includes
|
||||
cc = "cc -c -O3 '"..f.."' -o '"..obj.."' "..includes
|
||||
e,h,c = execute(cc)
|
||||
if c ~= 0 and c ~= nil then
|
||||
print("Compilation Error")
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ targets = {
|
|||
for f in p:lines() do
|
||||
base = f:match("([^/]+)%.c$")
|
||||
obj = "build/"..base..".o"
|
||||
cc = "cc -c '"..f.."' -o '"..obj.."' "..includes
|
||||
cc = "cc -c -ggdb '"..f.."' -o '"..obj.."' "..includes
|
||||
e,h,c = execute(cc)
|
||||
if c ~= 0 and c ~= nil then
|
||||
print("Compilation Error")
|
||||
|
|
|
|||
1
flagpole/fvm.inc
Symbolic link
1
flagpole/fvm.inc
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
../tests/fvm.inc
|
||||
|
|
@ -64,7 +64,7 @@ proc putuint
|
|||
1 @divisor
|
||||
|
||||
while &val &divisor u/ 9 u> do
|
||||
10 &divisor u* @divisor
|
||||
&divisor 10 u* @divisor
|
||||
endwhile
|
||||
|
||||
while &divisor 0 u> do
|
||||
|
|
@ -90,7 +90,7 @@ proc puts
|
|||
dup ld8 :putchar
|
||||
1 u+
|
||||
endwhile
|
||||
pop
|
||||
drop
|
||||
endproc
|
||||
|
||||
proc newline
|
||||
|
|
|
|||
5
flagpole/irtests/2vars.fp
Normal file
5
flagpole/irtests/2vars.fp
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
proc main
|
||||
2 @a
|
||||
3 @b
|
||||
&a &b u+
|
||||
endproc
|
||||
13
flagpole/irtests/cat.fp
Normal file
13
flagpole/irtests/cat.fp
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
proc putchar
|
||||
0xCFFFFFFFFFFFFFFD st8
|
||||
endproc
|
||||
|
||||
proc getchar
|
||||
0xCFFFFFFFFFFFFFFE ld8
|
||||
endproc
|
||||
|
||||
proc main
|
||||
while 1 do
|
||||
:getchar :putchar
|
||||
endwhile
|
||||
endproc
|
||||
11
flagpole/irtests/cat1.fp
Normal file
11
flagpole/irtests/cat1.fp
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
proc putchar
|
||||
0xCFFFFFFFFFFFFFFD st8
|
||||
endproc
|
||||
|
||||
proc getchar
|
||||
0xCFFFFFFFFFFFFFFE ld8
|
||||
endproc
|
||||
|
||||
proc main
|
||||
:getchar :putchar
|
||||
endproc
|
||||
10
flagpole/irtests/divgrow.fp
Normal file
10
flagpole/irtests/divgrow.fp
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
$inc fvmstd.fp
|
||||
|
||||
proc main
|
||||
1 @divisor
|
||||
while &divisor 100 u< do
|
||||
0x31 :putchar
|
||||
&divisor 10 u* @divisor
|
||||
endwhile
|
||||
0x32 :putchar
|
||||
endproc
|
||||
3
flagpole/irtests/dumbstring.fp
Normal file
3
flagpole/irtests/dumbstring.fp
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
proc main
|
||||
"String" 1 u+
|
||||
endproc
|
||||
5
flagpole/irtests/eq.fp
Normal file
5
flagpole/irtests/eq.fp
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
proc main
|
||||
1
|
||||
2 1 u-
|
||||
==
|
||||
endproc
|
||||
6
flagpole/irtests/gt.fp
Normal file
6
flagpole/irtests/gt.fp
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
proc main
|
||||
5
|
||||
if 5 3 u> then
|
||||
drop 3
|
||||
endif
|
||||
endproc
|
||||
7
flagpole/irtests/hex.fp
Normal file
7
flagpole/irtests/hex.fp
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
proc putchar
|
||||
0xCFFFFFFFFFFFFFFD st8
|
||||
endproc
|
||||
|
||||
proc main
|
||||
0x48 :putchar
|
||||
endproc
|
||||
10
flagpole/irtests/loop.fp
Normal file
10
flagpole/irtests/loop.fp
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
$inc fvmstd.fp
|
||||
|
||||
proc main
|
||||
1 @i
|
||||
0x30 :putchar
|
||||
while &i 10 u< do
|
||||
0x30 :putchar
|
||||
&i 1 u+ @i
|
||||
endwhile
|
||||
endproc
|
||||
5
flagpole/irtests/num.fp
Normal file
5
flagpole/irtests/num.fp
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
$inc fvmstd.fp
|
||||
|
||||
proc main
|
||||
4 :putuint
|
||||
endproc
|
||||
5
flagpole/irtests/putuint.fp
Normal file
5
flagpole/irtests/putuint.fp
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
$inc fvmstd.fp
|
||||
|
||||
proc main
|
||||
23 :putuint
|
||||
endproc
|
||||
3
flagpole/irtests/uadd.fp
Normal file
3
flagpole/irtests/uadd.fp
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
proc main
|
||||
34 35 u+
|
||||
endproc
|
||||
3
flagpole/irtests/usub.fp
Normal file
3
flagpole/irtests/usub.fp
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
proc main
|
||||
500 80 u-
|
||||
endproc
|
||||
4
flagpole/irtests/var.fp
Normal file
4
flagpole/irtests/var.fp
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
proc main
|
||||
0x40 @a
|
||||
&a 2 u+
|
||||
endproc
|
||||
14
flagpole/irtests/varmover.fp
Normal file
14
flagpole/irtests/varmover.fp
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
$inc fvmstd.fp
|
||||
|
||||
proc main
|
||||
2 @a
|
||||
4 @b
|
||||
3 @a
|
||||
8 @c
|
||||
&b @a
|
||||
&c @a
|
||||
|
||||
&a 0x30 u+ :putchar
|
||||
&b 0x30 u+ :putchar
|
||||
&c 0x30 u+ :putchar
|
||||
endproc
|
||||
285
flagpole/src/ir.c
Normal file
285
flagpole/src/ir.c
Normal file
|
|
@ -0,0 +1,285 @@
|
|||
#include "lazy.h"
|
||||
#include "ir.h"
|
||||
|
||||
void IRLoadValue(IRValue v, int reg, IRValue *registers) {
|
||||
if (v.typ == IRVAL_VIRTUAL) {
|
||||
for (int i = 1; i < 96; ++i) {
|
||||
if (registers[i].typ == IRVAL_VIRTUAL && registers[i].val == v.val) {
|
||||
printf(" Mov64 %d, %d\n", reg, i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (v.typ == IRVAL_STACK) {
|
||||
for (int i = 1; i < 96; ++i) {
|
||||
if (registers[i].typ == IRVAL_STACK && registers[i].val == v.val) {
|
||||
printf(" Mov64 %d, %d\n", reg, i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (v.typ == IRVAL_MEMORY) {
|
||||
printf(" MovI64 103, 0x%016lX\n", v.val);
|
||||
printf(" Ld64 %d, 103\n", reg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (v.typ == IRVAL_CONSTANT) {
|
||||
printf(" MovI64 %d, 0x%016lX\n", reg, v.val);
|
||||
}
|
||||
}
|
||||
|
||||
void IRStoreValue(IRValue v, int reg, int *regalloc, IRValue *registers) {
|
||||
if (v.typ == IRVAL_VIRTUAL) {
|
||||
int r = (*regalloc)++;
|
||||
registers[r] = v;
|
||||
printf(" Mov64 %d, %d\n", r, reg);
|
||||
}
|
||||
|
||||
if (v.typ == IRVAL_STACK) {
|
||||
assert(0 && "Don't write directly to the stack pooks <3");
|
||||
}
|
||||
|
||||
if (v.typ == IRVAL_MEMORY) {
|
||||
printf(" MovI64 123, 0x%016lX\n", v.val);
|
||||
printf(" St64 %d, 123\n", reg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (v.typ == IRVAL_CONSTANT) {
|
||||
// Escape for non returning operations
|
||||
}
|
||||
}
|
||||
|
||||
void IRComplete(void *statements_v, void *vstack_v) {
|
||||
Lz_DA(IRStatement) *statements = statements_v;
|
||||
Lz_DA(IRValue) *vstack = vstack_v;
|
||||
int regalloc = 1; // Current register for allocating things
|
||||
// If you manage to hit 95 registers
|
||||
// You deserve for your compiler to fail
|
||||
IRValue registers[96];
|
||||
int deepestStack = 0;
|
||||
for (int i = 0; i < statements->cnt; ++i) {
|
||||
if (statements->data[i].arg1.typ == IRVAL_STACK) {
|
||||
if (statements->data[i].arg1.val > deepestStack) {
|
||||
deepestStack = statements->data[i].arg1.val;
|
||||
}
|
||||
}
|
||||
if (statements->data[i].arg2.typ == IRVAL_STACK) {
|
||||
if (statements->data[i].arg2.val > deepestStack) {
|
||||
deepestStack = statements->data[i].arg2.val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < deepestStack; ++i) {
|
||||
int reg = regalloc++;
|
||||
printf(" popstack %d\n", reg);
|
||||
registers[reg] = (IRValue) {
|
||||
.typ = IRVAL_STACK,
|
||||
.val = i+1
|
||||
};
|
||||
}
|
||||
|
||||
int count;
|
||||
lz_da_foreach(IRStatement, s, *statements) {
|
||||
++count;
|
||||
printf("; Using ir-operation %d\n", s->op);
|
||||
switch (s->op) {
|
||||
case IR_UADD: {
|
||||
IRLoadValue(s->arg1, 101, registers);
|
||||
IRLoadValue(s->arg2, 100, registers);
|
||||
printf(" AddR64 100, 101\n");
|
||||
IRStoreValue(s->dst, 100, ®alloc, registers);
|
||||
break;
|
||||
}
|
||||
case IR_USUB: {
|
||||
IRLoadValue(s->arg2, 100, registers);
|
||||
IRLoadValue(s->arg1, 101, registers);
|
||||
printf(" SubR64 100, 101\n");
|
||||
IRStoreValue(s->dst, 100, ®alloc, registers);
|
||||
break;
|
||||
}
|
||||
case IR_UMUL: {
|
||||
IRLoadValue(s->arg2, 100, registers);
|
||||
IRLoadValue(s->arg1, 101, registers);
|
||||
printf(" MulR64 100, 101\n");
|
||||
IRStoreValue(s->dst, 100, ®alloc, registers);
|
||||
break;
|
||||
}
|
||||
case IR_UDIV: {
|
||||
IRLoadValue(s->arg2, 100, registers);
|
||||
IRLoadValue(s->arg1, 101, registers);
|
||||
printf(" DivR64 100, 101\n");
|
||||
IRStoreValue(s->dst, 100, ®alloc, registers);
|
||||
break;
|
||||
}
|
||||
case IR_UMOD: {
|
||||
IRLoadValue(s->arg2, 100, registers);
|
||||
IRLoadValue(s->arg1, 101, registers);
|
||||
printf(" ModR64 100, 101\n");
|
||||
IRStoreValue(s->dst, 100, ®alloc, registers);
|
||||
break;
|
||||
}
|
||||
case IR_AND: {
|
||||
IRLoadValue(s->arg2, 100, registers);
|
||||
IRLoadValue(s->arg1, 101, registers);
|
||||
printf(" AndR64 100, 101\n");
|
||||
IRStoreValue(s->dst, 100, ®alloc, registers);
|
||||
break;
|
||||
}
|
||||
case IR_XOR: {
|
||||
IRLoadValue(s->arg2, 100, registers);
|
||||
IRLoadValue(s->arg1, 101, registers);
|
||||
printf(" XorR64 100, 101\n");
|
||||
IRStoreValue(s->dst, 100, ®alloc, registers);
|
||||
break;
|
||||
}
|
||||
case IR_OR: {
|
||||
IRLoadValue(s->arg2, 100, registers);
|
||||
IRLoadValue(s->arg1, 101, registers);
|
||||
printf(" OrR64 100, 101\n");
|
||||
IRStoreValue(s->dst, 100, ®alloc, registers);
|
||||
break;
|
||||
}
|
||||
case IR_NOT: {
|
||||
IRLoadValue(s->arg1, 101, registers);
|
||||
printf(" Not64 101\n");
|
||||
IRStoreValue(s->dst, 101, ®alloc, registers);
|
||||
break;
|
||||
}
|
||||
case IR_IMUL: {
|
||||
IRLoadValue(s->arg2, 100, registers);
|
||||
IRLoadValue(s->arg1, 101, registers);
|
||||
printf(" IMulR64 100, 101\n");
|
||||
IRStoreValue(s->dst, 100, ®alloc, registers);
|
||||
break;
|
||||
}
|
||||
case IR_IDIV: {
|
||||
IRLoadValue(s->arg2, 100, registers);
|
||||
IRLoadValue(s->arg1, 101, registers);
|
||||
printf(" IDivR64 100, 101\n");
|
||||
IRStoreValue(s->dst, 100, ®alloc, registers);
|
||||
break;
|
||||
}
|
||||
case IR_IMOD: {
|
||||
IRLoadValue(s->arg2, 100, registers);
|
||||
IRLoadValue(s->arg1, 101, registers);
|
||||
printf(" IModR64 100, 101\n");
|
||||
IRStoreValue(s->dst, 100, ®alloc, registers);
|
||||
break;
|
||||
}
|
||||
case IR_ST8: {
|
||||
IRLoadValue(s->arg2, 100, registers);
|
||||
IRLoadValue(s->arg1, 101, registers);
|
||||
printf(" St8 100, 101\n");
|
||||
break;
|
||||
}
|
||||
case IR_SWAP: {
|
||||
IRLoadValue(s->arg2, 100, registers);
|
||||
IRLoadValue(s->arg1, 101, registers);
|
||||
IRStoreValue(s->arg1, 100, ®alloc, registers);
|
||||
IRStoreValue(s->arg2, 101, ®alloc, registers);
|
||||
break;
|
||||
}
|
||||
case IR_NOP: {
|
||||
IRLoadValue(s->arg1, 100, registers);
|
||||
IRStoreValue(s->dst, 100, ®alloc, registers);
|
||||
break;
|
||||
}
|
||||
case IR_LD8: {
|
||||
IRLoadValue(s->arg1, 101, registers);
|
||||
printf(" Ld8 100, 101\n");
|
||||
IRStoreValue(s->dst, 100, ®alloc, registers);
|
||||
break;
|
||||
}
|
||||
case IR_EQ: {
|
||||
IRLoadValue(s->arg2, 100, registers);
|
||||
IRLoadValue(s->arg1, 101, registers);
|
||||
printf(" Cmp64 100, 101\n");
|
||||
printf(" JmpIZ eq_%d\n", count);
|
||||
printf(" MovI64 99, 0\n");
|
||||
printf(" Jmp cmpdone_%d\n", count);
|
||||
printf("eq_%d:\n", count);
|
||||
printf(" MovI64 99, 1\n");
|
||||
printf("cmpdone_%d:\n",count);
|
||||
IRStoreValue(s->dst, 99, ®alloc, registers);
|
||||
break;
|
||||
}
|
||||
case IR_ULT: {
|
||||
IRLoadValue(s->arg2, 100, registers);
|
||||
IRLoadValue(s->arg1, 101, registers);
|
||||
printf(" Cmp64 100, 101\n");
|
||||
printf(" JmpIN eq_%d\n", count);
|
||||
printf(" MovI64 99, 0\n");
|
||||
printf(" Jmp cmpdone_%d\n", count);
|
||||
printf("eq_%d:\n", count);
|
||||
printf(" MovI64 99, 1\n");
|
||||
printf("cmpdone_%d:\n", count);
|
||||
IRStoreValue(s->dst, 99, ®alloc, registers);
|
||||
break;
|
||||
}
|
||||
case IR_UGT: {
|
||||
IRLoadValue(s->arg2, 100, registers);
|
||||
IRLoadValue(s->arg1, 101, registers);
|
||||
printf(" Cmp64 100, 101\n");
|
||||
printf(" JmpIP eq_%d\n", count);
|
||||
printf(" MovI64 99, 0\n");
|
||||
printf(" Jmp cmpdone_%d\n", count);
|
||||
printf("eq_%d:\n", count);
|
||||
printf(" MovI64 99, 1\n");
|
||||
printf("cmpdone_%d:\n",count);
|
||||
IRStoreValue(s->dst, 99, ®alloc, registers);
|
||||
break;
|
||||
}
|
||||
case IR_ILT: {
|
||||
IRLoadValue(s->arg2, 100, registers);
|
||||
IRLoadValue(s->arg1, 101, registers);
|
||||
printf(" ICmp64 100, 101\n");
|
||||
printf(" JmpIN eq_%d\n", count);
|
||||
printf(" MovI64 99, 0\n");
|
||||
printf(" Jmp cmpdone_%d\n", count);
|
||||
printf("eq_%d:\n", count);
|
||||
printf(" MovI64 99, 1\n");
|
||||
printf("cmpdone_%d:\n",count);
|
||||
IRStoreValue(s->dst, 99, ®alloc, registers);
|
||||
break;
|
||||
}
|
||||
case IR_IGT: {
|
||||
IRLoadValue(s->arg2, 100, registers);
|
||||
IRLoadValue(s->arg1, 101, registers);
|
||||
printf(" ICmp64 100, 101\n");
|
||||
printf(" JmpIP eq_%d\n", count);
|
||||
printf(" MovI64 99, 0\n");
|
||||
printf(" Jmp cmpdone_%d\n", count);
|
||||
printf("eq_%d:\n", count);
|
||||
printf(" MovI64 99, 1\n");
|
||||
printf("cmpdone_%d:\n",count);
|
||||
IRStoreValue(s->dst, 99, ®alloc, registers);
|
||||
break;
|
||||
}
|
||||
case IR_STR: {
|
||||
IRStoreValue(s->dst, 100, ®alloc, registers);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lz_da_foreach(IRValue, v, *vstack) {
|
||||
if (v->typ == IRVAL_CONSTANT) {
|
||||
printf(" MovI64 123, 0x%016lX\n", v->val);
|
||||
printf(" pushstack 123\n");
|
||||
continue;
|
||||
}
|
||||
for (int i = 0; i < 96; ++i) {
|
||||
if (registers[i].typ == v->typ && registers[i].val == v->val) {
|
||||
printf(" pushstack %d\n",i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
vstack->cnt = 0;
|
||||
statements->cnt = 0;
|
||||
}
|
||||
51
flagpole/src/ir.h
Normal file
51
flagpole/src/ir.h
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
|
||||
typedef enum {
|
||||
IRVAL_VIRTUAL,
|
||||
IRVAL_STACK,
|
||||
IRVAL_MEMORY,
|
||||
IRVAL_ARG,
|
||||
IRVAL_CONSTANT
|
||||
} IRValKind;
|
||||
|
||||
typedef struct {
|
||||
IRValKind typ;
|
||||
uint64_t val;
|
||||
} IRValue;
|
||||
|
||||
typedef enum {
|
||||
IR_NOP,
|
||||
IR_SWAP,
|
||||
IR_UADD,
|
||||
IR_USUB,
|
||||
IR_UMUL,
|
||||
IR_UDIV,
|
||||
IR_UMOD,
|
||||
IR_IADD,
|
||||
IR_ISUB,
|
||||
IR_IMUL,
|
||||
IR_IDIV,
|
||||
IR_IMOD,
|
||||
IR_UGT,
|
||||
IR_ULT,
|
||||
IR_IGT,
|
||||
IR_ILT,
|
||||
IR_EQ,
|
||||
IR_NOT,
|
||||
IR_AND,
|
||||
IR_OR,
|
||||
IR_XOR,
|
||||
IR_LD8,
|
||||
IR_LD64,
|
||||
IR_ST8,
|
||||
IR_ST64,
|
||||
IR_STR,
|
||||
} IROperation;
|
||||
|
||||
typedef struct {
|
||||
IRValue dst;
|
||||
IROperation op;
|
||||
IRValue arg1;
|
||||
IRValue arg2;
|
||||
} IRStatement;
|
||||
|
||||
void IRComplete(void *statements_v, void *vstack_v);
|
||||
|
|
@ -5,6 +5,7 @@
|
|||
#include "lazy.h"
|
||||
#include "token.h"
|
||||
#include "var.h"
|
||||
#include "ir.h"
|
||||
|
||||
bool is_int_literal(Lz_SB *sb) {
|
||||
for (int i = 0; i < sb->cnt; ++i) {
|
||||
|
|
@ -78,6 +79,24 @@ void commentStack(void *stack) {
|
|||
printf("\n");
|
||||
}
|
||||
|
||||
static inline uint64_t lz_sb_readhex(Lz_SB *sb) {
|
||||
Lz_SB clone = *sb;
|
||||
clone.data += 2;
|
||||
clone.cnt -= 2;
|
||||
uint64_t val = 0;
|
||||
lz_da_foreach(char, c, clone) {
|
||||
val *= 0x10;
|
||||
if (*c >= '0' && *c <= '9') {
|
||||
val += *c - '0';
|
||||
} else if (*c >= 'A' && *c <= 'F') {
|
||||
val += *c - 'A' + 10;
|
||||
} else if (*c >= 'a' && *c <= 'f') {
|
||||
val += *c - 'a' + 10;
|
||||
}
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline bool isKW(Lz_SB *sb) {
|
||||
return
|
||||
SBeq(sb, "proc")
|
||||
|
|
@ -117,6 +136,28 @@ static inline bool isKW(Lz_SB *sb) {
|
|||
;
|
||||
}
|
||||
|
||||
#define IR_GET_2_ARGS \
|
||||
IRValue x1, x2; \
|
||||
if (irVStack.cnt >= 2) { \
|
||||
x1 = lz_da_pop(irVStack); \
|
||||
x2 = lz_da_pop(irVStack); \
|
||||
} else if (irVStack.cnt == 1) { \
|
||||
x1 = lz_da_pop(irVStack); \
|
||||
x2 = (IRValue) { \
|
||||
.typ = IRVAL_STACK, \
|
||||
.val = ++vstackUnderflows \
|
||||
}; \
|
||||
} else if (irVStack.cnt == 0) { \
|
||||
x1 = (IRValue) { \
|
||||
.typ = IRVAL_STACK, \
|
||||
.val = ++vstackUnderflows \
|
||||
}; \
|
||||
x2 = (IRValue) { \
|
||||
.typ = IRVAL_STACK, \
|
||||
.val = ++vstackUnderflows \
|
||||
}; \
|
||||
}
|
||||
|
||||
int main(uint argc, char **argv) {
|
||||
int opt;
|
||||
Lz_DA(FILE *) inpfiles = {};
|
||||
|
|
@ -152,24 +193,28 @@ int main(uint argc, char **argv) {
|
|||
Lz_DA(int) labelStack = {0};
|
||||
uint64_t allocHead = 0x7000000000000000;
|
||||
char funcName[128];
|
||||
Lz_DA(Variable) vars;
|
||||
Lz_DA(Variable) vars = {0};
|
||||
char newchar;
|
||||
Lz_DA(IRStatement) irStatements = {0};
|
||||
Lz_DA(IRValue) irVStack = {0};
|
||||
int irVCount = 0;
|
||||
int vstackUnderflows = 0;
|
||||
printf("include 'fvm.inc'\n");
|
||||
printf("define STACK_START 0x6000000000000000\n");
|
||||
printf("define STACK_SP 125\n");
|
||||
printf("define STACK_INC 126\n");
|
||||
printf("org 0x4000000000000000\n");
|
||||
printf(" MovI64 STACK_SP, STACK_START\n");
|
||||
printf(" MovI64 STACK_INC, 8\n");
|
||||
printf(" Call __fp_user_main\n");
|
||||
printf(" Halt\n");
|
||||
printf("macro pushstack reg\n");
|
||||
printf(" MovI64 124, 8\n");
|
||||
printf(" SubR64 STACK_SP, 124\n");
|
||||
printf(" SubR64 STACK_SP, STACK_INC\n");
|
||||
printf(" St64 reg, STACK_SP\n");
|
||||
printf("end macro\n\n");
|
||||
printf("macro popstack reg\n");
|
||||
printf(" MovI64 124, 8\n");
|
||||
printf(" Ld64 reg, STACK_SP\n");
|
||||
printf(" AddR64 STACK_SP, 124\n");
|
||||
printf(" AddR64 STACK_SP, STACK_INC\n");
|
||||
printf("end macro\n\n");
|
||||
// Genuinely idk why goto is possessing me today
|
||||
compileStart:
|
||||
|
|
@ -182,32 +227,32 @@ compileStart:
|
|||
if (tokenAccumulator.cnt == 0) continue;
|
||||
if (is_int_literal(&tokenAccumulator)) {
|
||||
currTokenKind = TOKEN_INTLIT;
|
||||
goto codegen;
|
||||
goto codegenIR;
|
||||
} else if (is_float_literal(&tokenAccumulator)) {
|
||||
currTokenKind = TOKEN_FLOATLIT;
|
||||
goto codegen;
|
||||
goto codegenIR;
|
||||
} else if (is_double_literal(&tokenAccumulator)) {
|
||||
currTokenKind = TOKEN_DOUBLELIT;
|
||||
goto codegen;
|
||||
goto codegenIR;
|
||||
} else if (is_hex_literal(&tokenAccumulator)) {
|
||||
currTokenKind = TOKEN_HEXLIT;
|
||||
goto codegen;
|
||||
goto codegenIR;
|
||||
} else if (is_bin_literal(&tokenAccumulator)) {
|
||||
currTokenKind = TOKEN_BINLIT;
|
||||
goto codegen;
|
||||
goto codegenIR;
|
||||
} else {
|
||||
currTokenKind = TOKEN_IDENTIFIER;
|
||||
if (isKW(&tokenAccumulator)) {
|
||||
currTokenKind = TOKEN_KEYWORD;
|
||||
}
|
||||
goto codegen;
|
||||
goto codegenIR;
|
||||
}
|
||||
}
|
||||
if (newchar == '"') {
|
||||
if (isQuote) {
|
||||
currTokenKind = TOKEN_STRINGLIT;
|
||||
isQuote = false;
|
||||
goto codegen;
|
||||
goto codegenIR;
|
||||
} else {
|
||||
if (tokenAccumulator.cnt != 0) {
|
||||
fprintf(stderr, "error %d\n", __LINE__);
|
||||
|
|
@ -220,7 +265,8 @@ compileStart:
|
|||
}
|
||||
lz_da_append(tokenAccumulator, newchar);
|
||||
continue;
|
||||
codegen:
|
||||
// Names suck but this also generates some asm for blocks
|
||||
codegenIR:
|
||||
//printf("I must gen code i am now Amista Azozin\n");
|
||||
//fprintf(stderr,"Token type: %d\n", currTokenKind);
|
||||
//fprintf(stderr,"Tok: "LZ_STR_FMT"\n", LZ_STR_PRINTF(tokenAccumulator));
|
||||
|
|
@ -232,6 +278,8 @@ codegen:
|
|||
break;
|
||||
}
|
||||
if (SBeq(&tokenAccumulator, "endproc")) {
|
||||
IRComplete(&irStatements, &irVStack);
|
||||
vstackUnderflows = 0;
|
||||
printf(" Ret\n");
|
||||
printf("\n\n");
|
||||
if (labelStack.cnt != 0) {
|
||||
|
|
@ -243,53 +291,113 @@ codegen:
|
|||
break;
|
||||
}
|
||||
if (SBeq(&tokenAccumulator, "return")) {
|
||||
IRComplete(&irStatements, &irVStack);
|
||||
vstackUnderflows = 0;
|
||||
printf(" Ret\n");
|
||||
break;
|
||||
}
|
||||
if (SBeq(&tokenAccumulator, "ld8")) {
|
||||
printf(" popstack 101\n");
|
||||
printf(" Ld8 102, 101\n");
|
||||
printf(" pushstack 102\n");
|
||||
IRValue x1;
|
||||
if (irVStack.cnt >= 1) {
|
||||
x1 = lz_da_pop(irVStack);
|
||||
} else if (irVStack.cnt == 0) {
|
||||
x1 = (IRValue) {
|
||||
.typ = IRVAL_STACK,
|
||||
.val = 1
|
||||
};
|
||||
}
|
||||
IRValue dstReg = (IRValue) {
|
||||
.typ = IRVAL_VIRTUAL,
|
||||
.val = ++irVCount
|
||||
};
|
||||
IRStatement s = (IRStatement) {
|
||||
.dst = dstReg,
|
||||
.op = IR_LD8,
|
||||
.arg1 = x1
|
||||
};
|
||||
lz_da_append(irVStack, dstReg);
|
||||
lz_da_append(irStatements, s);
|
||||
break;
|
||||
}
|
||||
if (SBeq(&tokenAccumulator, "st8")) {
|
||||
printf(" popstack 101\n");
|
||||
printf(" popstack 102\n");
|
||||
printf(" St8 102, 101\n");
|
||||
IR_GET_2_ARGS
|
||||
IRValue dstReg = (IRValue) {
|
||||
.typ = IRVAL_CONSTANT,
|
||||
};
|
||||
IRStatement s = (IRStatement) {
|
||||
.dst = dstReg,
|
||||
.op = IR_ST8,
|
||||
.arg1 = x1,
|
||||
.arg2 = x2
|
||||
};
|
||||
lz_da_append(irStatements, s);
|
||||
break;
|
||||
}
|
||||
if (SBeq(&tokenAccumulator, "dup")) {
|
||||
if (irVStack.cnt != 0) {
|
||||
IRValue v = lz_da_pop(irVStack);
|
||||
lz_da_append(irVStack, v);
|
||||
lz_da_append(irVStack, v);
|
||||
} else {
|
||||
printf(" popstack 106\n");
|
||||
printf(" pushstack 106\n");
|
||||
printf(" pushstack 106\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (SBeq(&tokenAccumulator, "swap")) {
|
||||
printf(" popstack 118\n");
|
||||
printf(" popstack 119\n");
|
||||
printf(" pushstack 118\n");
|
||||
printf(" pushstack 119\n");
|
||||
IRValue x1, x2;
|
||||
if (irVStack.cnt >= 2) {
|
||||
x1 = lz_da_pop(irVStack);
|
||||
x2 = lz_da_pop(irVStack);
|
||||
} else if (irVStack.cnt == 1) {
|
||||
x1 = lz_da_pop(irVStack);
|
||||
x2 = (IRValue) {
|
||||
.typ = IRVAL_STACK,
|
||||
.val = ++vstackUnderflows
|
||||
};
|
||||
} else if (irVStack.cnt == 0) {
|
||||
x1 = (IRValue) {
|
||||
.typ = IRVAL_STACK,
|
||||
.val = ++vstackUnderflows
|
||||
};
|
||||
x2 = (IRValue) {
|
||||
.typ = IRVAL_STACK,
|
||||
.val = ++vstackUnderflows
|
||||
};
|
||||
}
|
||||
lz_da_append(irVStack, x1);
|
||||
lz_da_append(irVStack, x2);
|
||||
break;
|
||||
}
|
||||
if (SBeq(&tokenAccumulator, "drop")) {
|
||||
if (irVStack.cnt != 0)
|
||||
lz_da_pop(irVStack);
|
||||
else
|
||||
printf(" popstack 118\n");
|
||||
break;
|
||||
}
|
||||
if (SBeq(&tokenAccumulator, "while")) {
|
||||
IRComplete(&irStatements, &irVStack);
|
||||
lz_da_append(labelStack, counter);
|
||||
commentStack(&labelStack);
|
||||
printf("__whilehead_%d:\n", counter);
|
||||
break;
|
||||
}
|
||||
if (SBeq(&tokenAccumulator, "do")) {
|
||||
IRComplete(&irStatements, &irVStack);
|
||||
vstackUnderflows = 0;
|
||||
int lbl = lz_da_pop(labelStack);
|
||||
lz_da_append(labelStack, lbl);
|
||||
// TODO: Change flag setting to IR's job
|
||||
printf(" popstack 108\n");
|
||||
printf(" RSetF 108\n");
|
||||
printf(" JmpIE __whiletail_%d\n", lbl);
|
||||
break;
|
||||
}
|
||||
if (SBeq(&tokenAccumulator, "endwhile")) {
|
||||
IRComplete(&irStatements, &irVStack);
|
||||
vstackUnderflows = 0;
|
||||
int lbl = lz_da_pop(labelStack);
|
||||
commentStack(&labelStack);
|
||||
printf(" Jmp __whilehead_%d\n", lbl);
|
||||
|
|
@ -302,6 +410,8 @@ codegen:
|
|||
break;
|
||||
}
|
||||
if (SBeq(&tokenAccumulator, "then")) {
|
||||
IRComplete(&irStatements, &irVStack);
|
||||
vstackUnderflows = 0;
|
||||
commentStack(&labelStack);
|
||||
int lbl = lz_da_pop(labelStack);
|
||||
lz_da_append(labelStack, lbl);
|
||||
|
|
@ -312,177 +422,322 @@ codegen:
|
|||
}
|
||||
|
||||
if (SBeq(&tokenAccumulator, "endif")) {
|
||||
IRComplete(&irStatements, &irVStack);
|
||||
vstackUnderflows = 0;
|
||||
commentStack(&labelStack);
|
||||
int lbl = lz_da_pop(labelStack);
|
||||
printf("__iftail_%d:\n", lbl);
|
||||
break;
|
||||
}
|
||||
if (SBeq(&tokenAccumulator, "==")) {
|
||||
// Hacked like crazy...
|
||||
printf(" popstack 110\n");
|
||||
printf(" popstack 111\n");
|
||||
printf(" Cmp64 110, 111\n");
|
||||
printf(" JmpIZ __Eq%d\n", counter);
|
||||
printf(" MovI64 112, 0\n");
|
||||
printf(" Jmp __DoneEqCheck%d\n", counter);
|
||||
printf("__Eq%d:\n", counter);
|
||||
printf(" MovI64 112, 1\n");
|
||||
printf("__DoneEqCheck%d:\n", counter);
|
||||
printf(" pushstack 112\n");
|
||||
IR_GET_2_ARGS
|
||||
IRValue dstReg = (IRValue) {
|
||||
.typ = IRVAL_VIRTUAL,
|
||||
.val = ++irVCount
|
||||
};
|
||||
IRStatement s = (IRStatement) {
|
||||
.dst = dstReg,
|
||||
.op = IR_EQ,
|
||||
.arg1 = x1,
|
||||
.arg2 = x2
|
||||
};
|
||||
lz_da_append(irVStack, dstReg);
|
||||
lz_da_append(irStatements, s);
|
||||
break;
|
||||
}
|
||||
if (SBeq(&tokenAccumulator, "not")) {
|
||||
printf(" popstack 96\n");
|
||||
printf(" Not64 96\n");
|
||||
printf(" pushstack 96\n");
|
||||
IRValue x1;
|
||||
if (irVStack.cnt >= 1) {
|
||||
x1 = lz_da_pop(irVStack);
|
||||
} else if (irVStack.cnt == 0) {
|
||||
x1 = (IRValue) {
|
||||
.typ = IRVAL_STACK,
|
||||
.val = 1
|
||||
};
|
||||
}
|
||||
IRValue dstReg = (IRValue) {
|
||||
.typ = IRVAL_VIRTUAL,
|
||||
.val = ++irVCount
|
||||
};
|
||||
IRStatement s = (IRStatement) {
|
||||
.dst = dstReg,
|
||||
.op = IR_NOT,
|
||||
.arg1 = x1
|
||||
};
|
||||
lz_da_append(irVStack, dstReg);
|
||||
lz_da_append(irStatements, s);
|
||||
break;
|
||||
}
|
||||
if (SBeq(&tokenAccumulator, "band")) {
|
||||
printf(" popstack 97\n");
|
||||
printf(" popstack 98\n");
|
||||
printf(" AndR64 98, 97\n");
|
||||
printf(" pushstack 98\n");
|
||||
IR_GET_2_ARGS
|
||||
IRValue dstReg = (IRValue) {
|
||||
.typ = IRVAL_VIRTUAL,
|
||||
.val = ++irVCount
|
||||
};
|
||||
IRStatement s = (IRStatement) {
|
||||
.dst = dstReg,
|
||||
.op = IR_AND,
|
||||
.arg1 = x1,
|
||||
.arg2 = x2
|
||||
};
|
||||
lz_da_append(irVStack, dstReg);
|
||||
lz_da_append(irStatements, s);
|
||||
break;
|
||||
}
|
||||
if (SBeq(&tokenAccumulator, "bor")) {
|
||||
printf(" popstack 97\n");
|
||||
printf(" popstack 98\n");
|
||||
printf(" OrR64 98, 97\n");
|
||||
printf(" pushstack 98\n");
|
||||
IR_GET_2_ARGS
|
||||
IRValue dstReg = (IRValue) {
|
||||
.typ = IRVAL_VIRTUAL,
|
||||
.val = ++irVCount
|
||||
};
|
||||
IRStatement s = (IRStatement) {
|
||||
.dst = dstReg,
|
||||
.op = IR_OR,
|
||||
.arg1 = x1,
|
||||
.arg2 = x2
|
||||
};
|
||||
lz_da_append(irVStack, dstReg);
|
||||
lz_da_append(irStatements, s);
|
||||
break;
|
||||
}
|
||||
if (SBeq(&tokenAccumulator, "xor")) {
|
||||
printf(" popstack 97\n");
|
||||
printf(" popstack 98\n");
|
||||
printf(" xorR64 98, 97\n");
|
||||
printf(" pushstack 98\n");
|
||||
IR_GET_2_ARGS
|
||||
IRValue dstReg = (IRValue) {
|
||||
.typ = IRVAL_VIRTUAL,
|
||||
.val = ++irVCount
|
||||
};
|
||||
IRStatement s = (IRStatement) {
|
||||
.dst = dstReg,
|
||||
.op = IR_XOR,
|
||||
.arg1 = x1,
|
||||
.arg2 = x2
|
||||
};
|
||||
lz_da_append(irVStack, dstReg);
|
||||
lz_da_append(irStatements, s);
|
||||
break;
|
||||
}
|
||||
if (SBeq(&tokenAccumulator, "u+")) {
|
||||
printf(" popstack 97\n");
|
||||
printf(" popstack 98\n");
|
||||
printf(" AddR64 98, 97\n");
|
||||
printf(" pushstack 98\n");
|
||||
IR_GET_2_ARGS
|
||||
IRValue dstReg = (IRValue) {
|
||||
.typ = IRVAL_VIRTUAL,
|
||||
.val = ++irVCount
|
||||
};
|
||||
IRStatement s = (IRStatement) {
|
||||
.dst = dstReg,
|
||||
.op = IR_UADD,
|
||||
.arg1 = x1,
|
||||
.arg2 = x2
|
||||
};
|
||||
lz_da_append(irVStack, dstReg);
|
||||
lz_da_append(irStatements, s);
|
||||
break;
|
||||
}
|
||||
if (SBeq(&tokenAccumulator, "u-")) {
|
||||
printf(" popstack 97\n");
|
||||
printf(" popstack 98\n");
|
||||
printf(" SubR64 98, 97\n");
|
||||
printf(" pushstack 98\n");
|
||||
IR_GET_2_ARGS
|
||||
IRValue dstReg = (IRValue) {
|
||||
.typ = IRVAL_VIRTUAL,
|
||||
.val = ++irVCount
|
||||
};
|
||||
IRStatement s = (IRStatement) {
|
||||
.dst = dstReg,
|
||||
.op = IR_USUB,
|
||||
.arg1 = x1,
|
||||
.arg2 = x2
|
||||
};
|
||||
lz_da_append(irVStack, dstReg);
|
||||
lz_da_append(irStatements, s);
|
||||
break;
|
||||
}
|
||||
if (SBeq(&tokenAccumulator, "u*")) {
|
||||
printf(" popstack 97\n");
|
||||
printf(" popstack 98\n");
|
||||
printf(" MulR64 98, 97\n");
|
||||
printf(" pushstack 98\n");
|
||||
IR_GET_2_ARGS
|
||||
IRValue dstReg = (IRValue) {
|
||||
.typ = IRVAL_VIRTUAL,
|
||||
.val = ++irVCount
|
||||
};
|
||||
IRStatement s = (IRStatement) {
|
||||
.dst = dstReg,
|
||||
.op = IR_UMUL,
|
||||
.arg1 = x1,
|
||||
.arg2 = x2
|
||||
};
|
||||
lz_da_append(irVStack, dstReg);
|
||||
lz_da_append(irStatements, s);
|
||||
break;
|
||||
}
|
||||
if (SBeq(&tokenAccumulator, "u/")) {
|
||||
printf(" popstack 97\n");
|
||||
printf(" popstack 98\n");
|
||||
printf(" DivR64 98, 97\n");
|
||||
printf(" pushstack 98\n");
|
||||
IR_GET_2_ARGS
|
||||
IRValue dstReg = (IRValue) {
|
||||
.typ = IRVAL_VIRTUAL,
|
||||
.val = ++irVCount
|
||||
};
|
||||
IRStatement s = (IRStatement) {
|
||||
.dst = dstReg,
|
||||
.op = IR_UDIV,
|
||||
.arg1 = x1,
|
||||
.arg2 = x2
|
||||
};
|
||||
lz_da_append(irVStack, dstReg);
|
||||
lz_da_append(irStatements, s);
|
||||
break;
|
||||
}
|
||||
if (SBeq(&tokenAccumulator, "u%")) {
|
||||
printf(" popstack 97\n");
|
||||
printf(" popstack 98\n");
|
||||
printf(" ModR64 98, 97\n");
|
||||
printf(" pushstack 98\n");
|
||||
IR_GET_2_ARGS
|
||||
IRValue dstReg = (IRValue) {
|
||||
.typ = IRVAL_VIRTUAL,
|
||||
.val = ++irVCount
|
||||
};
|
||||
IRStatement s = (IRStatement) {
|
||||
.dst = dstReg,
|
||||
.op = IR_UMOD,
|
||||
.arg1 = x1,
|
||||
.arg2 = x2
|
||||
};
|
||||
lz_da_append(irVStack, dstReg);
|
||||
lz_da_append(irStatements, s);
|
||||
break;
|
||||
}
|
||||
if (SBeq(&tokenAccumulator, "u>")) {
|
||||
printf(" popstack 97\n");
|
||||
printf(" popstack 98\n");
|
||||
printf(" Cmp64 98, 97\n");
|
||||
printf(" JmpIP __Cmp%d\n", counter);
|
||||
printf(" MovI64 112, 0\n");
|
||||
printf(" Jmp __DoneCmp%d\n", counter);
|
||||
printf("__Cmp%d:\n", counter);
|
||||
printf(" MovI64 112, 1\n");
|
||||
printf("__DoneCmp%d:\n", counter);
|
||||
printf(" pushstack 112\n");
|
||||
IR_GET_2_ARGS
|
||||
IRValue dstReg = (IRValue) {
|
||||
.typ = IRVAL_VIRTUAL,
|
||||
.val = ++irVCount
|
||||
};
|
||||
IRStatement s = (IRStatement) {
|
||||
.dst = dstReg,
|
||||
.op = IR_UGT,
|
||||
.arg1 = x1,
|
||||
.arg2 = x2
|
||||
};
|
||||
lz_da_append(irVStack, dstReg);
|
||||
lz_da_append(irStatements, s);
|
||||
break;
|
||||
}
|
||||
if (SBeq(&tokenAccumulator, "u<")) {
|
||||
printf(" popstack 97\n");
|
||||
printf(" popstack 98\n");
|
||||
printf(" Cmp64 98, 97\n");
|
||||
printf(" JmpIN __Cmp%d\n", counter);
|
||||
printf(" MovI64 112, 0\n");
|
||||
printf(" Jmp __DoneCmp%d\n", counter);
|
||||
printf("__Cmp%d:\n", counter);
|
||||
printf(" MovI64 112, 1\n");
|
||||
printf("__DoneCmp%d:\n", counter);
|
||||
printf(" pushstack 112\n");
|
||||
IR_GET_2_ARGS
|
||||
IRValue dstReg = (IRValue) {
|
||||
.typ = IRVAL_VIRTUAL,
|
||||
.val = ++irVCount
|
||||
};
|
||||
IRStatement s = (IRStatement) {
|
||||
.dst = dstReg,
|
||||
.op = IR_ULT,
|
||||
.arg1 = x1,
|
||||
.arg2 = x2
|
||||
};
|
||||
lz_da_append(irVStack, dstReg);
|
||||
lz_da_append(irStatements, s);
|
||||
break;
|
||||
}
|
||||
if (SBeq(&tokenAccumulator, "i+")) {
|
||||
printf(" popstack 97\n");
|
||||
printf(" popstack 98\n");
|
||||
printf(" AddR64 98, 97\n");
|
||||
printf(" pushstack 98\n");
|
||||
IR_GET_2_ARGS
|
||||
IRValue dstReg = (IRValue) {
|
||||
.typ = IRVAL_VIRTUAL,
|
||||
.val = ++irVCount
|
||||
};
|
||||
IRStatement s = (IRStatement) {
|
||||
.dst = dstReg,
|
||||
.op = IR_UADD,
|
||||
.arg1 = x1,
|
||||
.arg2 = x2
|
||||
};
|
||||
lz_da_append(irVStack, dstReg);
|
||||
lz_da_append(irStatements, s);
|
||||
break;
|
||||
}
|
||||
if (SBeq(&tokenAccumulator, "i-")) {
|
||||
printf(" popstack 97\n");
|
||||
printf(" popstack 98\n");
|
||||
printf(" SubR64 98, 97\n");
|
||||
printf(" pushstack 98\n");
|
||||
IR_GET_2_ARGS
|
||||
IRValue dstReg = (IRValue) {
|
||||
.typ = IRVAL_VIRTUAL,
|
||||
.val = ++irVCount
|
||||
};
|
||||
IRStatement s = (IRStatement) {
|
||||
.dst = dstReg,
|
||||
.op = IR_USUB,
|
||||
.arg1 = x1,
|
||||
.arg2 = x2
|
||||
};
|
||||
lz_da_append(irVStack, dstReg);
|
||||
lz_da_append(irStatements, s);
|
||||
break;
|
||||
}
|
||||
if (SBeq(&tokenAccumulator, "i*")) {
|
||||
printf(" popstack 97\n");
|
||||
printf(" popstack 98\n");
|
||||
printf(" IMulR64 98, 97\n");
|
||||
printf(" pushstack 98\n");
|
||||
IR_GET_2_ARGS
|
||||
IRValue dstReg = (IRValue) {
|
||||
.typ = IRVAL_VIRTUAL,
|
||||
.val = ++irVCount
|
||||
};
|
||||
IRStatement s = (IRStatement) {
|
||||
.dst = dstReg,
|
||||
.op = IR_IMUL,
|
||||
.arg1 = x1,
|
||||
.arg2 = x2
|
||||
};
|
||||
lz_da_append(irVStack, dstReg);
|
||||
lz_da_append(irStatements, s);
|
||||
break;
|
||||
}
|
||||
if (SBeq(&tokenAccumulator, "i/")) {
|
||||
printf(" popstack 97\n");
|
||||
printf(" popstack 98\n");
|
||||
printf(" IDivR64 98, 97\n");
|
||||
printf(" pushstack 98\n");
|
||||
IR_GET_2_ARGS
|
||||
IRValue dstReg = (IRValue) {
|
||||
.typ = IRVAL_VIRTUAL,
|
||||
.val = ++irVCount
|
||||
};
|
||||
IRStatement s = (IRStatement) {
|
||||
.dst = dstReg,
|
||||
.op = IR_IDIV,
|
||||
.arg1 = x1,
|
||||
.arg2 = x2
|
||||
};
|
||||
lz_da_append(irVStack, dstReg);
|
||||
lz_da_append(irStatements, s);
|
||||
break;
|
||||
}
|
||||
if (SBeq(&tokenAccumulator, "i%")) {
|
||||
printf(" popstack 97\n");
|
||||
printf(" popstack 98\n");
|
||||
printf(" IModR64 98, 97\n");
|
||||
printf(" pushstack 98\n");
|
||||
IR_GET_2_ARGS
|
||||
IRValue dstReg = (IRValue) {
|
||||
.typ = IRVAL_VIRTUAL,
|
||||
.val = ++irVCount
|
||||
};
|
||||
IRStatement s = (IRStatement) {
|
||||
.dst = dstReg,
|
||||
.op = IR_IMOD,
|
||||
.arg1 = x1,
|
||||
.arg2 = x2
|
||||
};
|
||||
lz_da_append(irVStack, dstReg);
|
||||
lz_da_append(irStatements, s);
|
||||
break;
|
||||
}
|
||||
if (SBeq(&tokenAccumulator, "i>")) {
|
||||
printf(" popstack 97\n");
|
||||
printf(" popstack 98\n");
|
||||
printf(" ICmp64 98, 97\n");
|
||||
printf(" JmpIP __Cmp%d\n", counter);
|
||||
printf(" MovI64 112, 0\n");
|
||||
printf(" Jmp __DoneCmp%d\n", counter);
|
||||
printf("__Cmp%d:\n", counter);
|
||||
printf(" MovI64 112, 1\n");
|
||||
printf("__DoneCmp%d:\n", counter);
|
||||
printf(" pushstack 112\n");
|
||||
IR_GET_2_ARGS
|
||||
IRValue dstReg = (IRValue) {
|
||||
.typ = IRVAL_VIRTUAL,
|
||||
.val = ++irVCount
|
||||
};
|
||||
IRStatement s = (IRStatement) {
|
||||
.dst = dstReg,
|
||||
.op = IR_ILT,
|
||||
.arg1 = x1,
|
||||
.arg2 = x2
|
||||
};
|
||||
lz_da_append(irVStack, dstReg);
|
||||
lz_da_append(irStatements, s);
|
||||
break;
|
||||
}
|
||||
if (SBeq(&tokenAccumulator, "i<")) {
|
||||
printf(" popstack 97\n");
|
||||
printf(" popstack 98\n");
|
||||
printf(" ICmp64 98, 97\n");
|
||||
printf(" JmpIN __Cmp%d\n", counter);
|
||||
printf(" MovI64 112, 0\n");
|
||||
printf(" Jmp __DoneCmp%d\n", counter);
|
||||
printf("__Cmp%d:\n", counter);
|
||||
printf(" MovI64 112, 1\n");
|
||||
printf("__DoneCmp%d:\n", counter);
|
||||
printf(" pushstack 112\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (SBeq(&tokenAccumulator, "pop")) {
|
||||
printf(" popstack 113\n");
|
||||
IR_GET_2_ARGS
|
||||
IRValue dstReg = (IRValue) {
|
||||
.typ = IRVAL_VIRTUAL,
|
||||
.val = ++irVCount
|
||||
};
|
||||
IRStatement s = (IRStatement) {
|
||||
.dst = dstReg,
|
||||
.op = IR_IGT,
|
||||
.arg1 = x1,
|
||||
.arg2 = x2
|
||||
};
|
||||
lz_da_append(irVStack, dstReg);
|
||||
lz_da_append(irStatements, s);
|
||||
break;
|
||||
}
|
||||
if (SBeq(&tokenAccumulator, "$inc")) {
|
||||
|
|
@ -511,6 +766,11 @@ codegen:
|
|||
printf("__fp_user_"LZ_STR_FMT":\n",
|
||||
LZ_STR_PRINTF(tokenAccumulator));
|
||||
isProc = false;
|
||||
IRValue arg = (IRValue) {
|
||||
.typ = IRVAL_ARG,
|
||||
.val = 0
|
||||
};
|
||||
|
||||
if (tokenAccumulator.cnt < 127) {
|
||||
memcpy(funcName, tokenAccumulator.data, tokenAccumulator.cnt);
|
||||
funcName[tokenAccumulator.cnt] = 0;
|
||||
|
|
@ -521,6 +781,8 @@ codegen:
|
|||
break;
|
||||
}
|
||||
if (tokenAccumulator.data[0] == ':') {
|
||||
IRComplete(&irStatements, &irVStack);
|
||||
vstackUnderflows = 0;
|
||||
printf(" Call __fp_user_"LZ_STR_FMT"\n",
|
||||
tokenAccumulator.cnt-1,
|
||||
tokenAccumulator.data+1);
|
||||
|
|
@ -553,10 +815,26 @@ codegen:
|
|||
lz_da_append(vars, v);
|
||||
allocHead += 8;
|
||||
}
|
||||
printf(" popstack 120\n");
|
||||
printf(" ; %s:%s\n", funcName, varName);
|
||||
printf(" MovI64 121, 0x%16lX\n", addr);
|
||||
printf(" St64 120, 121\n");
|
||||
IRValue x1;
|
||||
if (irVStack.cnt >= 1) {
|
||||
x1 = lz_da_pop(irVStack);
|
||||
} else if (irVStack.cnt == 0) {
|
||||
x1 = (IRValue) {
|
||||
.typ = IRVAL_STACK,
|
||||
.val = ++vstackUnderflows
|
||||
};
|
||||
}
|
||||
|
||||
IRValue dstReg = (IRValue) {
|
||||
.typ = IRVAL_MEMORY,
|
||||
.val = addr
|
||||
};
|
||||
IRStatement s = (IRStatement) {
|
||||
.dst = dstReg,
|
||||
.op = IR_NOP,
|
||||
.arg1 = x1
|
||||
};
|
||||
lz_da_append(irStatements, s);
|
||||
break;
|
||||
}
|
||||
if (tokenAccumulator.data[0] == '&') {
|
||||
|
|
@ -581,9 +859,23 @@ codegen:
|
|||
varName, funcName);
|
||||
exit(1);
|
||||
}
|
||||
printf(" MovI64 121, 0x%16lX\n", addr);
|
||||
printf(" Ld64 120, 121\n");
|
||||
printf(" pushstack 120\n");
|
||||
|
||||
IRValue dstReg = (IRValue) {
|
||||
.typ = IRVAL_VIRTUAL,
|
||||
.val = ++irVCount
|
||||
};
|
||||
|
||||
IRValue x1 = (IRValue) {
|
||||
.typ = IRVAL_MEMORY,
|
||||
.val = addr
|
||||
};
|
||||
IRStatement s = (IRStatement) {
|
||||
.dst = dstReg,
|
||||
.op = IR_NOP,
|
||||
.arg1 = x1
|
||||
};
|
||||
lz_da_append(irStatements, s);
|
||||
lz_da_append(irVStack, dstReg);
|
||||
break;
|
||||
}
|
||||
// Iirc there's not a general thing for identifiers so just fail?
|
||||
|
|
@ -592,25 +884,58 @@ codegen:
|
|||
exit(0);
|
||||
}
|
||||
case TOKEN_INTLIT: {
|
||||
printf(" MovI64 103, "LZ_STR_FMT"\n",
|
||||
LZ_STR_PRINTF(tokenAccumulator));
|
||||
printf(" pushstack 103\n");
|
||||
uint64_t x = lz_sb_atoll(&tokenAccumulator);
|
||||
IRValue v = (IRValue) {
|
||||
.typ = IRVAL_CONSTANT,
|
||||
.val = x
|
||||
};
|
||||
lz_da_append(irVStack, v);
|
||||
break;
|
||||
}
|
||||
case TOKEN_HEXLIT: {
|
||||
printf(" MovI64 103, "LZ_STR_FMT"\n",
|
||||
LZ_STR_PRINTF(tokenAccumulator));
|
||||
printf(" pushstack 103\n");
|
||||
uint64_t x = lz_sb_readhex(&tokenAccumulator);
|
||||
IRValue v = (IRValue) {
|
||||
.typ = IRVAL_CONSTANT,
|
||||
.val = x
|
||||
};
|
||||
lz_da_append(irVStack, v);
|
||||
break;
|
||||
}
|
||||
case TOKEN_STRINGLIT: {
|
||||
IRValue dstReg = (IRValue) {
|
||||
.typ = IRVAL_VIRTUAL,
|
||||
.val = ++irVCount
|
||||
};
|
||||
// This is a bad way of doing strings tbh
|
||||
printf(" Jmp endstring%d\n", counter);
|
||||
printf("string%d db \""LZ_STR_FMT"\", 0\n",
|
||||
counter,
|
||||
LZ_STR_PRINTF(tokenAccumulator));
|
||||
printf("endstring%d:\n", counter);
|
||||
printf(" MovI64 100, string%d\n", counter);
|
||||
printf(" pushstack 100\n", counter);
|
||||
IRStatement s = (IRStatement) {
|
||||
.dst = dstReg,
|
||||
.op = IR_NOP,
|
||||
.arg1 = IR_STR
|
||||
};
|
||||
lz_da_append(irVStack, dstReg);
|
||||
lz_da_append(irStatements, s);
|
||||
break;
|
||||
|
||||
//IRComplete(&irStatements, &irVStack);
|
||||
//vstackUnderflows = 0;
|
||||
//printf(" Jmp endstring%d\n", counter);
|
||||
//printf("string%d db \""LZ_STR_FMT"\", 0\n",
|
||||
// counter,
|
||||
// LZ_STR_PRINTF(tokenAccumulator));
|
||||
//printf("endstring%d:\n", counter);
|
||||
//printf(" MovI64 100, string%d\n", counter);
|
||||
//printf(" pushstack 100\n", counter);
|
||||
// IRValue v = (IRValue) {
|
||||
// .typ = IRVAL_STACK,
|
||||
// .val = 1
|
||||
// };
|
||||
// lz_da_append(irVStack, v);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
|
|
|
|||
14
flagpole/tests/fibloop.fp
Normal file
14
flagpole/tests/fibloop.fp
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
$inc fvmstd.fp
|
||||
|
||||
proc main
|
||||
92 @N
|
||||
0 @a
|
||||
1 @b
|
||||
while &N 0 u> do
|
||||
&a &b u+ @c
|
||||
&b @a
|
||||
&c @b
|
||||
&N 1 u- @N
|
||||
endwhile
|
||||
&b :putuint :newline
|
||||
endproc
|
||||
100
src/interp.c
100
src/interp.c
|
|
@ -5,9 +5,11 @@
|
|||
#include <assert.h>
|
||||
#define LAZY_IMPL
|
||||
#include "lazy.h"
|
||||
#include <time.h>
|
||||
|
||||
#define PAGE_SIZE 4096
|
||||
#define DEBUG false
|
||||
//#define DEBUG
|
||||
//#define TIME
|
||||
// MMIO is defined between 0xC000000000000000 and 0xD000000000000000
|
||||
// Some of that is still normal memory though
|
||||
#define UART_TX 0xCFFFFFFFFFFFFFFD
|
||||
|
|
@ -122,27 +124,47 @@ int main(int argc, char **argv) {
|
|||
bool positiveFlag = false;
|
||||
bool negativeFlag = false;
|
||||
bool parityFlag = false;
|
||||
#ifdef TIME
|
||||
Lz_HM(unsigned char, uint) instrTimes;
|
||||
Lz_HM(unsigned char, uint) instrCounts;
|
||||
lz_hm_init(instrTimes);
|
||||
lz_hm_init(instrCounts);
|
||||
#endif
|
||||
|
||||
while (1) {
|
||||
unsigned char inst = memory_get8(xPc);
|
||||
if (DEBUG) printf("INST: %02X\n", inst);
|
||||
if (DEBUG) printf("IP: %16lX\n", xPc);
|
||||
#ifdef DEBUG
|
||||
printf("INST: %02X\n", inst);
|
||||
printf("IP: %16lX\n", xPc);
|
||||
#endif
|
||||
size_t inpflag = (inst & 0xE0) >> 5;
|
||||
size_t inpcnt = flag_bytecnt[inpflag];
|
||||
if (DEBUG) printf("Cnt: %zu\n", inpcnt);
|
||||
#ifdef DEBUG
|
||||
printf("Cnt: %zu\n", inpcnt);
|
||||
#endif
|
||||
unsigned char inputs[9];
|
||||
for (size_t i = 0; i < inpcnt; ++i) {
|
||||
inputs[i] = memory_get8(xPc+i+1);
|
||||
if (DEBUG) {
|
||||
#ifdef DEBUG
|
||||
printf("X%d: 0x%8X\n", i, inputs[i]);
|
||||
#endif
|
||||
}
|
||||
#ifdef TIME
|
||||
if (lz_hm_exists(instrCounts, inst)) {
|
||||
uint x = lz_hm_get(instrCounts, inst);
|
||||
lz_hm_remove(instrCounts, inst);
|
||||
lz_hm_add(instrCounts, inst, x+1);
|
||||
} else {
|
||||
lz_hm_add(instrCounts, inst, 1);
|
||||
}
|
||||
clock_t startTime = clock();
|
||||
#endif
|
||||
xPc += 1;
|
||||
xPc += inpcnt;
|
||||
switch (inst) {
|
||||
case 0x00: { // Halt
|
||||
printf("\nHALT\n");
|
||||
exit(0);
|
||||
goto halt;
|
||||
break;
|
||||
}
|
||||
case 0xE9: { // MovI64
|
||||
|
|
@ -156,13 +178,13 @@ int main(int argc, char **argv) {
|
|||
unsigned char x7 = inputs[7];
|
||||
unsigned char x8 = inputs[8];
|
||||
uint64_t val =
|
||||
((uint64_t)x1 << 56) +
|
||||
((uint64_t)x2 << 48) +
|
||||
((uint64_t)x3 << 40) +
|
||||
((uint64_t)x4 << 32) +
|
||||
((uint64_t)x5 << 24) +
|
||||
((uint64_t)x6 << 16) +
|
||||
((uint64_t)x7 << 8) +
|
||||
((uint64_t)x1 << 56) |
|
||||
((uint64_t)x2 << 48) |
|
||||
((uint64_t)x3 << 40) |
|
||||
((uint64_t)x4 << 32) |
|
||||
((uint64_t)x5 << 24) |
|
||||
((uint64_t)x6 << 16) |
|
||||
((uint64_t)x7 << 8) |
|
||||
((uint64_t)x8 << 0);
|
||||
registers[reg] = val;
|
||||
registers[0] = 0;
|
||||
|
|
@ -183,11 +205,11 @@ int main(int argc, char **argv) {
|
|||
case 0x93: { // Ld8
|
||||
unsigned char dst = inputs[0];
|
||||
unsigned char addr = inputs[1];
|
||||
if (DEBUG) {
|
||||
#ifdef DEBUG
|
||||
printf("Ld8\n");
|
||||
printf("Dst val: %8X\n", registers[dst]);
|
||||
printf("Addr val: %8X\n", registers[addr]);
|
||||
}
|
||||
#endif
|
||||
registers[dst] = memory_get8(registers[addr]);
|
||||
break;
|
||||
}
|
||||
|
|
@ -324,7 +346,9 @@ int main(int argc, char **argv) {
|
|||
case 0xC1: { // JmpIZ
|
||||
unsigned char addr = inputs[0];
|
||||
if (zeroFlag) {
|
||||
if (DEBUG) printf("Jump!\n");
|
||||
#ifdef DEBUG
|
||||
printf("Jump!\n");
|
||||
#endif
|
||||
xPc = registers[addr];
|
||||
}
|
||||
break;
|
||||
|
|
@ -332,7 +356,9 @@ int main(int argc, char **argv) {
|
|||
case 0xC3: { // JmpIP
|
||||
unsigned char addr = inputs[0];
|
||||
if (positiveFlag) {
|
||||
if (DEBUG) printf("Jump!\n");
|
||||
#ifdef DEBUG
|
||||
printf("Jump!\n");
|
||||
#endif
|
||||
xPc = registers[addr];
|
||||
}
|
||||
break;
|
||||
|
|
@ -340,7 +366,9 @@ int main(int argc, char **argv) {
|
|||
case 0xC2: { // JmpIN
|
||||
unsigned char addr = inputs[0];
|
||||
if (negativeFlag) {
|
||||
if (DEBUG) printf("Jump!\n");
|
||||
#ifdef DEBUG
|
||||
printf("Jump!\n");
|
||||
#endif
|
||||
xPc = registers[addr];
|
||||
}
|
||||
break;
|
||||
|
|
@ -348,7 +376,9 @@ int main(int argc, char **argv) {
|
|||
case 0xC8: { // JmpIE
|
||||
unsigned char addr = inputs[0];
|
||||
if (!parityFlag) {
|
||||
if (DEBUG) printf("Jump!\n");
|
||||
#ifdef DEBUG
|
||||
printf("Jump!\n");
|
||||
#endif
|
||||
xPc = registers[addr];
|
||||
}
|
||||
break;
|
||||
|
|
@ -377,7 +407,39 @@ int main(int argc, char **argv) {
|
|||
exit(1);
|
||||
}
|
||||
}
|
||||
#ifdef TIME
|
||||
clock_t endTime = clock();
|
||||
clock_t diff = endTime - startTime ;
|
||||
uint usec = diff * 1000000 / CLOCKS_PER_SEC;
|
||||
|
||||
if (lz_hm_exists(instrTimes, inst)) {
|
||||
uint x = lz_hm_get(instrTimes, inst);
|
||||
lz_hm_remove(instrTimes, inst);
|
||||
lz_hm_add(instrTimes, inst, x+usec);
|
||||
} else {
|
||||
lz_hm_add(instrTimes, inst, usec);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
halt:
|
||||
#ifdef TIME
|
||||
// TODO: Fix this shit
|
||||
for (int i = 0; i < instrTimes.cap; ++i) {
|
||||
if (instrTimes.exists[i]) {
|
||||
printf("Instr: %2x used %dus\n",
|
||||
instrTimes.keys[i],
|
||||
instrTimes.vals[i]);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < instrCounts.cap; ++i) {
|
||||
if (instrCounts.exists[i]) {
|
||||
printf("Instr: %2x used %d times\n",
|
||||
instrCounts.keys[i],
|
||||
instrCounts.vals[i]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue