commit a4dd029ba2d03e7d014958eff03de5d2ba407f08
parent b43ef1072891fa694565d481c467d57769884946
Author: Nihal Jere <nihal@nihaljere.xyz>
Date: Mon, 10 Jan 2022 23:01:03 -0600
move backend specific stuff to ir.c
This means main.c doesn't have to know about backends at all.
Diffstat:
5 files changed, 36 insertions(+), 30 deletions(-)
diff --git a/ir.c b/ir.c
@@ -3,6 +3,7 @@
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
+#include <stdlib.h>
#include <strings.h>
#include "array.h"
@@ -316,18 +317,24 @@ genblock(struct iproc *out, struct block *block)
}
}
-void
-genproc(struct iproc *out, struct proc *proc)
+size_t
+genproc(struct decl *decl, struct proc *proc)
{
tmpi = labeli = curi = 1;
regs = targ.reserved;
struct instr ins;
struct type *type;
+ struct iproc iproc = {
+ .s = decl->s,
+ .addr = decl->w.addr,
+ };
+
+ struct iproc *out = &iproc; // for macros to work, a bit hacky
blockpush(&proc->block);
// put a blank interval, since tmpi starts at 1
- array_add((&out->intervals), interval);
+ array_add((&iproc.intervals), interval);
size_t i = 0;
for (size_t j = 0; j < proc->in.len; j++, i++) {
@@ -367,5 +374,14 @@ genproc(struct iproc *out, struct proc *proc)
}
}
+ size_t len = targ.emitproc(NULL, out);
+ void *buf = xcalloc(1, len); // FIXME: unnecessary
+ len = targ.emitproc(buf, out);
+ array_push((&toplevel.text), buf, len);
+ free(buf);
+ array_add((&toplevel.code), iproc);
+
blockpop();
+
+ return len;
}
diff --git a/ir.h b/ir.h
@@ -39,9 +39,9 @@ struct interval {
struct iproc {
size_t len;
size_t cap;
- uint64_t addr;
struct instr *data;
- struct slice s;
+ uint64_t addr; // FIXME: 'addr' and 's' are only necessary because syscalls are intrinsics.
+ struct slice s; // Once syscalls are moved out, we can just use the decl fields and have a pointer to the declaration.
struct {
size_t len;
size_t cap;
@@ -61,4 +61,10 @@ struct toplevel {
uint64_t entry;
};
-void genproc(struct iproc *out, struct proc *proc);
+size_t genproc(struct decl *decl, struct proc *proc);
+
+struct target {
+ uint32_t reserved;
+ size_t (*emitsyscall)(char *buf, uint8_t paramcount);
+ size_t (*emitproc)(char *buf, struct iproc *proc);
+};
diff --git a/main.c b/main.c
@@ -13,7 +13,6 @@
#include "nooc.h"
#include "ir.h"
#include "util.h"
-#include "x64.h"
#include "elf.h"
#include "lex.h"
#include "parse.h"
@@ -134,7 +133,6 @@ gentoplevel(struct toplevel *toplevel, struct block *block)
decl_alloc(block, decl);
- // FIXME: clean this whole thing up
if (expr->class == C_PROC) {
if (slice_cmplit(&decl->s, "main") == 0) {
toplevel->entry = curaddr;
@@ -142,18 +140,8 @@ gentoplevel(struct toplevel *toplevel, struct block *block)
assert(expr->kind = EXPR_PROC);
blockpush(&expr->d.proc.block);
typecheck(&expr->d.proc.block);
- iproc = (struct iproc){ 0 };
- iproc.s = decl->s;
- iproc.addr = curaddr;
- genproc(&iproc, &(expr->d.proc));
- array_add((&toplevel->code), iproc);
- len = emitproc(NULL, &iproc);
- void *buf = xcalloc(1, len); // FIXME: unnecessary
- len = emitproc(buf, &iproc);
- curaddr += len;
- array_push((&toplevel->text), buf, len);
- free(buf);
-
+ decl->w.addr = curaddr;
+ curaddr += genproc(decl, &expr->d.proc);
blockpop();
} else {
evalexpr(decl);
diff --git a/nooc.h b/nooc.h
@@ -248,8 +248,3 @@ struct exprs {
size_t len;
struct expr *data;
};
-
-struct target {
- uint32_t reserved;
- size_t (*emitsyscall)(char *buf, uint8_t paramcount);
-};
diff --git a/x64.c b/x64.c
@@ -602,11 +602,6 @@ emitsyscall(char *buf, uint8_t paramcount)
return total;
}
-const struct target x64_target = {
- .reserved = (1 << RSP) | (1 << RBP) | (1 << R12) | (1 << R13),
- .emitsyscall = emitsyscall
-};
-
size_t
emitblock(char *buf, struct iproc *proc, struct instr *start, struct instr *end, uint64_t end_label)
{
@@ -754,3 +749,9 @@ emitproc(char *buf, struct iproc *proc)
{
return emitblock(buf, proc, NULL, NULL, 0);
}
+
+const struct target x64_target = {
+ .reserved = (1 << RSP) | (1 << RBP) | (1 << R12) | (1 << R13),
+ .emitsyscall = emitsyscall,
+ .emitproc = emitproc
+};