1009 lines
29 KiB
C
1009 lines
29 KiB
C
#include <stdio.h>
|
|
#include <unistd.h>
|
|
#include <ctype.h>
|
|
#define LAZY_IMPL
|
|
#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) {
|
|
char c = sb->data[i];
|
|
if (!(isdigit(c) || (i == 0 && c == '-'))) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool is_float_literal(Lz_SB *sb) {
|
|
for (int i = 0; i < sb->cnt-1; ++i) {
|
|
char c = sb->data[i];
|
|
if (!(isdigit(c) || (i == 0 && c == '-') || c == '.')) {
|
|
return false;
|
|
}
|
|
}
|
|
return sb->data[sb->cnt-1] == 'f';
|
|
}
|
|
|
|
bool is_double_literal(Lz_SB *sb) {
|
|
for (int i = 0; i < sb->cnt; ++i) {
|
|
char c = sb->data[i];
|
|
if (!(isdigit(c) || (i == 0 && c == '-') || c == '.')) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool is_hex_literal(Lz_SB *sb) {
|
|
if (sb->data[0] != '0' || sb->data[1] != 'x') {
|
|
return false;
|
|
}
|
|
for (int i = 2; i < sb->cnt; ++i) {
|
|
char c = sb->data[i];
|
|
if (c >= '0' && c <= '9') continue;
|
|
if (c >= 'a' && c <= 'f') continue;
|
|
if (c >= 'A' && c <= 'F') continue;
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool is_bin_literal(Lz_SB *sb) {
|
|
if (sb->data[0] != '0' || sb->data[1] != 'b') {
|
|
return false;
|
|
}
|
|
for (int i = 2; i < sb->cnt; ++i) {
|
|
char c = sb->data[i];
|
|
if (c == '0' && c == '1') continue;
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool SBeq(Lz_SB *sb, const char *cstr) {
|
|
size_t l = strlen(cstr);
|
|
if (l != sb->cnt) return false;
|
|
return !memcmp(sb->data, cstr, l);
|
|
}
|
|
|
|
void commentStack(void *stack) {
|
|
typedef Lz_DA(int) intstack;
|
|
intstack *s = stack;
|
|
printf(" ; Stack:");
|
|
lz_da_foreach(int, x, *s) {
|
|
printf(" %d", *x);
|
|
}
|
|
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")
|
|
|| SBeq(sb, "endproc")
|
|
|| SBeq(sb, "return")
|
|
|| SBeq(sb, "ld8")
|
|
|| SBeq(sb, "st8")
|
|
|| SBeq(sb, "dup")
|
|
|| SBeq(sb, "swap")
|
|
|| SBeq(sb, "drop")
|
|
|| SBeq(sb, "while")
|
|
|| SBeq(sb, "do")
|
|
|| SBeq(sb, "if")
|
|
|| SBeq(sb, "then")
|
|
|| SBeq(sb, "endif")
|
|
|| SBeq(sb, "endwhile")
|
|
|| SBeq(sb, "break")
|
|
|| SBeq(sb, "continue")
|
|
|| SBeq(sb, "==")
|
|
|| SBeq(sb, "not")
|
|
|| SBeq(sb, "bor")
|
|
|| SBeq(sb, "band")
|
|
|| SBeq(sb, "u+")
|
|
|| SBeq(sb, "u-")
|
|
|| SBeq(sb, "u*")
|
|
|| SBeq(sb, "u/")
|
|
|| SBeq(sb, "u%")
|
|
|| SBeq(sb, "u>")
|
|
|| SBeq(sb, "u<")
|
|
|| SBeq(sb, "i+")
|
|
|| SBeq(sb, "i-")
|
|
|| SBeq(sb, "i*")
|
|
|| SBeq(sb, "i/")
|
|
|| SBeq(sb, "i%")
|
|
|| SBeq(sb, "i>")
|
|
|| SBeq(sb, "i<")
|
|
|| SBeq(sb, "pop")
|
|
|| SBeq(sb, "$inc")
|
|
;
|
|
}
|
|
|
|
#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 \
|
|
}; \
|
|
}
|
|
|
|
typedef enum {
|
|
LABEL_WHILE,
|
|
LABEL_IF,
|
|
} LabelKind;
|
|
|
|
typedef struct {
|
|
LabelKind typ;
|
|
int num;
|
|
} AsmLabel;
|
|
|
|
int main(uint argc, char **argv) {
|
|
int opt;
|
|
Lz_DA(FILE *) inpfiles = {};
|
|
while ((opt = getopt(argc, argv, "f:")) != -1) {
|
|
switch(opt) {
|
|
case 'f': {
|
|
FILE *inpfile = fopen(optarg, "r");
|
|
if (!inpfile) {
|
|
printf("Failed to open file %s\n", optarg);
|
|
exit(1);
|
|
}
|
|
lz_da_append(inpfiles, inpfile);
|
|
break;
|
|
}
|
|
default: break;
|
|
}
|
|
}
|
|
|
|
if (inpfiles.cnt == 0) {
|
|
printf("No file requested\n");
|
|
exit(1);
|
|
}
|
|
|
|
FILE *currFile = lz_da_pop(inpfiles);
|
|
|
|
TokenKind currTokenKind;
|
|
Lz_SB tokenAccumulator = {0};
|
|
int counter = 0;
|
|
bool isQuote = false;
|
|
bool isProc = false;
|
|
bool isInclude = false;
|
|
bool isComment = false;
|
|
Lz_DA(AsmLabel) labelStack = {0};
|
|
uint64_t allocHead = 0x7000000000000000;
|
|
char funcName[128];
|
|
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(" SubR64 STACK_SP, STACK_INC\n");
|
|
printf(" St64 reg, STACK_SP\n");
|
|
printf("end macro\n\n");
|
|
printf("macro popstack reg\n");
|
|
printf(" Ld64 reg, STACK_SP\n");
|
|
printf(" AddR64 STACK_SP, STACK_INC\n");
|
|
printf("end macro\n\n");
|
|
// Genuinely idk why goto is possessing me today
|
|
compileStart:
|
|
while ((newchar = fgetc(currFile)) != EOF) {
|
|
++counter;
|
|
if (isComment && newchar == '\n') isComment = false;
|
|
if (!isComment && newchar == '#') isComment = true;
|
|
if (isComment) continue;
|
|
if (isspace(newchar) && !isQuote) {
|
|
if (tokenAccumulator.cnt == 0) continue;
|
|
if (is_int_literal(&tokenAccumulator)) {
|
|
currTokenKind = TOKEN_INTLIT;
|
|
goto codegenIR;
|
|
} else if (is_float_literal(&tokenAccumulator)) {
|
|
currTokenKind = TOKEN_FLOATLIT;
|
|
goto codegenIR;
|
|
} else if (is_double_literal(&tokenAccumulator)) {
|
|
currTokenKind = TOKEN_DOUBLELIT;
|
|
goto codegenIR;
|
|
} else if (is_hex_literal(&tokenAccumulator)) {
|
|
currTokenKind = TOKEN_HEXLIT;
|
|
goto codegenIR;
|
|
} else if (is_bin_literal(&tokenAccumulator)) {
|
|
currTokenKind = TOKEN_BINLIT;
|
|
goto codegenIR;
|
|
} else {
|
|
currTokenKind = TOKEN_IDENTIFIER;
|
|
if (isKW(&tokenAccumulator)) {
|
|
currTokenKind = TOKEN_KEYWORD;
|
|
}
|
|
goto codegenIR;
|
|
}
|
|
}
|
|
if (newchar == '"') {
|
|
if (isQuote) {
|
|
currTokenKind = TOKEN_STRINGLIT;
|
|
isQuote = false;
|
|
goto codegenIR;
|
|
} else {
|
|
if (tokenAccumulator.cnt != 0) {
|
|
fprintf(stderr, "error %d\n", __LINE__);
|
|
exit(1);
|
|
} else {
|
|
isQuote = true;
|
|
}
|
|
continue;
|
|
}
|
|
}
|
|
lz_da_append(tokenAccumulator, newchar);
|
|
continue;
|
|
// 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));
|
|
printf(" ; "LZ_STR_FMT"\n", LZ_STR_PRINTF(tokenAccumulator));
|
|
switch (currTokenKind) {
|
|
case TOKEN_KEYWORD: {
|
|
if (SBeq(&tokenAccumulator, "proc")) {
|
|
isProc = true;
|
|
break;
|
|
}
|
|
if (SBeq(&tokenAccumulator, "endproc")) {
|
|
IRComplete(&irStatements, &irVStack);
|
|
vstackUnderflows = 0;
|
|
printf(" Ret\n");
|
|
printf("\n\n");
|
|
if (labelStack.cnt != 0) {
|
|
fprintf(stderr,
|
|
"Unmatched statement in function %s\n", funcName);
|
|
exit(1);
|
|
}
|
|
funcName[0] = 0;
|
|
break;
|
|
}
|
|
if (SBeq(&tokenAccumulator, "return")) {
|
|
IRComplete(&irStatements, &irVStack);
|
|
vstackUnderflows = 0;
|
|
printf(" Ret\n");
|
|
break;
|
|
}
|
|
if (SBeq(&tokenAccumulator, "ld8")) {
|
|
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")) {
|
|
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")) {
|
|
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);
|
|
AsmLabel lbl = (AsmLabel) {
|
|
.num = counter,
|
|
.typ = LABEL_WHILE
|
|
};
|
|
lz_da_append(labelStack, lbl);
|
|
commentStack(&labelStack);
|
|
printf("__whilehead_%d:\n", lbl.num);
|
|
break;
|
|
}
|
|
if (SBeq(&tokenAccumulator, "do")) {
|
|
IRComplete(&irStatements, &irVStack);
|
|
vstackUnderflows = 0;
|
|
AsmLabel lbl = lz_da_pop(labelStack);
|
|
if (lbl.typ != LABEL_WHILE) {
|
|
fprintf(stderr, "Unmatched do without a while\n");
|
|
exit(1);
|
|
}
|
|
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.num);
|
|
break;
|
|
}
|
|
if (SBeq(&tokenAccumulator, "endwhile")) {
|
|
IRComplete(&irStatements, &irVStack);
|
|
vstackUnderflows = 0;
|
|
AsmLabel lbl = lz_da_pop(labelStack);
|
|
if (lbl.typ != LABEL_WHILE) {
|
|
fprintf(stderr, "Unmatched endwhile without while\n");
|
|
exit(1);
|
|
}
|
|
commentStack(&labelStack);
|
|
printf(" Jmp __whilehead_%d\n", lbl.num);
|
|
printf("__whiletail_%d:\n", lbl.num);
|
|
break;
|
|
}
|
|
if (SBeq(&tokenAccumulator, "break")) {
|
|
IRComplete(&irStatements, &irVStack);
|
|
AsmLabel lbl;
|
|
for (int i = labelStack.cnt; i >= 0; --i) {
|
|
if (labelStack.data[i].typ == LABEL_WHILE) {
|
|
lbl = labelStack.data[i];
|
|
}
|
|
}
|
|
printf(" Jmp __whiletail_%d\n", lbl.num);
|
|
break;
|
|
}
|
|
if (SBeq(&tokenAccumulator, "continue")) {
|
|
IRComplete(&irStatements, &irVStack);
|
|
AsmLabel lbl;
|
|
for (int i = labelStack.cnt; i >= 0; --i) {
|
|
if (labelStack.data[i].typ == LABEL_WHILE) {
|
|
lbl = labelStack.data[i];
|
|
}
|
|
}
|
|
printf(" Jmp __whilehead_%d\n", lbl.num);
|
|
break;
|
|
}
|
|
if (SBeq(&tokenAccumulator, "if")) {
|
|
break;
|
|
}
|
|
if (SBeq(&tokenAccumulator, "then")) {
|
|
IRComplete(&irStatements, &irVStack);
|
|
|
|
AsmLabel lbl = (AsmLabel) {
|
|
.num = counter,
|
|
.typ = LABEL_IF
|
|
};
|
|
lz_da_append(labelStack, lbl);
|
|
commentStack(&labelStack);
|
|
vstackUnderflows = 0;
|
|
printf(" popstack 123\n");
|
|
printf(" RSetF 123\n");
|
|
printf(" JmpIE __iftail_%d\n", lbl.num);
|
|
break;
|
|
}
|
|
|
|
if (SBeq(&tokenAccumulator, "endif")) {
|
|
IRComplete(&irStatements, &irVStack);
|
|
vstackUnderflows = 0;
|
|
commentStack(&labelStack);
|
|
AsmLabel lbl = lz_da_pop(labelStack);
|
|
if (lbl.typ != LABEL_IF) {
|
|
fprintf(stderr, "Unmatched endif without an if\n");
|
|
exit(1);
|
|
}
|
|
printf("__iftail_%d:\n", lbl.num);
|
|
break;
|
|
}
|
|
if (SBeq(&tokenAccumulator, "==")) {
|
|
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")) {
|
|
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_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")) {
|
|
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")) {
|
|
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")) {
|
|
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+")) {
|
|
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-")) {
|
|
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*")) {
|
|
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/")) {
|
|
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%")) {
|
|
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>")) {
|
|
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<")) {
|
|
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+")) {
|
|
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-")) {
|
|
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*")) {
|
|
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/")) {
|
|
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%")) {
|
|
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>")) {
|
|
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, "i<")) {
|
|
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, "$inc")) {
|
|
isInclude = true;
|
|
break;
|
|
}
|
|
printf("Unimplemented keyword: "LZ_STR_FMT"\n",
|
|
LZ_STR_PRINTF(tokenAccumulator));
|
|
exit(1);
|
|
}
|
|
case TOKEN_IDENTIFIER: {
|
|
if (isInclude) {
|
|
char *fname = malloc(tokenAccumulator.cnt+1);
|
|
memcpy(fname, tokenAccumulator.data, tokenAccumulator.cnt);
|
|
fname[tokenAccumulator.cnt] = 0;
|
|
FILE *f = fopen(fname, "r");
|
|
if (!f) {
|
|
fprintf(stderr, "Could not open file %s or doesn't exist\n",
|
|
fname);
|
|
}
|
|
lz_da_append(inpfiles, f);
|
|
isInclude = false;
|
|
break;
|
|
}
|
|
if (isProc) {
|
|
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;
|
|
} else {
|
|
memcpy(funcName, tokenAccumulator.data, 127);
|
|
funcName[127] = 0;
|
|
}
|
|
break;
|
|
}
|
|
if (tokenAccumulator.data[0] == ':') {
|
|
IRComplete(&irStatements, &irVStack);
|
|
vstackUnderflows = 0;
|
|
printf(" Call __fp_user_"LZ_STR_FMT"\n",
|
|
tokenAccumulator.cnt-1,
|
|
tokenAccumulator.data+1);
|
|
break;
|
|
}
|
|
if (tokenAccumulator.data[0] == '@') {
|
|
char varName[128];
|
|
if (tokenAccumulator.cnt < 128) {
|
|
memcpy(varName, tokenAccumulator.data+1,
|
|
tokenAccumulator.cnt-1);
|
|
varName[tokenAccumulator.cnt-1] = 0;
|
|
} else {
|
|
memcpy(varName, tokenAccumulator.data+1, 127);
|
|
varName[127] = 0;
|
|
}
|
|
uint64_t addr = 0;
|
|
lz_da_foreach(Variable, v, vars) {
|
|
if (!strcmp(v->name, varName) && !strcmp(v->func, funcName)) {
|
|
addr = v->addr;
|
|
break;
|
|
}
|
|
}
|
|
if (addr == 0) {
|
|
addr = allocHead;
|
|
Variable v = (Variable) {
|
|
.addr = addr
|
|
};
|
|
memcpy(&v.func, funcName, 128);
|
|
memcpy(&v.name, varName, 128);
|
|
lz_da_append(vars, v);
|
|
allocHead += 8;
|
|
}
|
|
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] == '&') {
|
|
char varName[128];
|
|
if (tokenAccumulator.cnt < 128) {
|
|
memcpy(varName, tokenAccumulator.data+1,
|
|
tokenAccumulator.cnt-1);
|
|
varName[tokenAccumulator.cnt-1] = 0;
|
|
} else {
|
|
memcpy(varName, tokenAccumulator.data+1, 127);
|
|
varName[127] = 0;
|
|
}
|
|
uint64_t addr = 0;
|
|
lz_da_foreach(Variable, v, vars) {
|
|
if (!strcmp(v->name, varName) && !strcmp(v->func, funcName)) {
|
|
addr = v->addr;
|
|
break;
|
|
}
|
|
}
|
|
if (addr == 0) {
|
|
fprintf(stderr, "Undeclared variable %s in function %s\n",
|
|
varName, funcName);
|
|
exit(1);
|
|
}
|
|
|
|
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?
|
|
fprintf(stderr, "Useless Identifier: "LZ_STR_FMT"\n",
|
|
LZ_STR_PRINTF(tokenAccumulator));
|
|
exit(0);
|
|
}
|
|
case TOKEN_INTLIT: {
|
|
uint64_t x = lz_sb_atoll(&tokenAccumulator);
|
|
IRValue v = (IRValue) {
|
|
.typ = IRVAL_CONSTANT,
|
|
.val = x
|
|
};
|
|
lz_da_append(irVStack, v);
|
|
break;
|
|
}
|
|
case TOKEN_HEXLIT: {
|
|
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);
|
|
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: {
|
|
printf("Bad: %d\n", currTokenKind);
|
|
exit(1);
|
|
}
|
|
}
|
|
tokenAccumulator.cnt = 0;
|
|
}
|
|
if (inpfiles.cnt != 0) {
|
|
currFile = lz_da_pop(inpfiles);
|
|
tokenAccumulator.cnt = 0;
|
|
isProc = false;
|
|
isQuote = false;
|
|
isInclude = false;
|
|
labelStack.cnt = 0;
|
|
goto compileStart;
|
|
}
|
|
}
|