commit 3dc2455e1bc046b6520629e50ba2df5c9b7ec8a2
parent b5ec8fe28362fbd82ccfa66bd4fb60904afeffb8
Author: Nihal Jere <nihal@nihaljere.xyz>
Date: Sun, 30 Jan 2022 11:38:18 -0600
replace blockstack with a more generic pointer stack
Now we can add arbitrarily many stacks, which will be useful for
determining what the current loop is.
Diffstat:
17 files changed, 121 insertions(+), 97 deletions(-)
diff --git a/Makefile b/Makefile
@@ -1,8 +1,8 @@
.c.o:
$(CC) -Wall -c $< -o $@
-nooc: main.o array.o util.o x64.o elf.o lex.o parse.o map.o siphash.o type.o blake3.o blockstack.o ir.o
- $(CC) main.o array.o x64.o util.o elf.o lex.o parse.o map.o siphash.o type.o blake3.o blockstack.o ir.o -o nooc
+nooc: main.o array.o util.o x64.o elf.o lex.o parse.o map.o siphash.o type.o blake3.o stack.o ir.o
+ $(CC) main.o array.o x64.o util.o elf.o lex.o parse.o map.o siphash.o type.o blake3.o stack.o ir.o -o nooc
clean:
rm -f *.o nooc
diff --git a/array.c b/array.c
@@ -4,6 +4,7 @@
#include <string.h>
#include "nooc.h"
+#include "stack.h"
#include "ir.h"
#include "util.h"
#include "array.h"
diff --git a/blockstack.c b/blockstack.c
@@ -1,55 +0,0 @@
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdlib.h>
-
-#include "nooc.h"
-#include "ir.h"
-#include "util.h"
-
-const struct block *blockstack[BLOCKSTACKSIZE];
-size_t blocki;
-
-struct decl *
-finddecl(const struct slice s)
-{
- for (int j = blocki - 1; j >= 0; j--) {
- for (int i = 0; i < blockstack[j]->decls.len; i++) {
- struct decl *decl = &blockstack[j]->decls.data[i];
- if (slice_cmp(&s, &decl->s) == 0) {
- return decl;
- }
- }
- }
-
- return NULL;
-}
-
-void
-blockpush(const struct block *const block)
-{
- if (blocki >= BLOCKSTACKSIZE - 1)
- die("blockpush: too many blocks!");
-
- blockstack[blocki] = block;
- blocki++;
-}
-
-const struct block *const
-blockpop()
-{
- if (blocki == 0)
- die("blockpop: cannot pop empty stack!");
-
- blocki--;
- return blockstack[blocki];
-}
-
-const struct block *const
-blockpeek()
-{
- if (blocki == 0)
- return NULL;
-
- return blockstack[blocki - 1];
-}
-
diff --git a/blockstack.h b/blockstack.h
@@ -1,4 +0,0 @@
-void blockpush(const struct block *const block);
-struct block *blockpop();
-struct block *blockpeek();
-struct decl *finddecl(struct slice s);
diff --git a/ir.c b/ir.c
@@ -7,9 +7,9 @@
#include "array.h"
#include "nooc.h"
+#include "stack.h"
#include "ir.h"
#include "util.h"
-#include "blockstack.h"
#include "target.h"
#define STARTINS(op, val, valtype) putins((out), (op), (val), (valtype)) ; curi++ ;
@@ -20,6 +20,7 @@
#define PTRSIZE 8
static uint64_t tmpi, labeli, curi, reali, rblocki, out_index;
+static struct stack *blocks;
static void
genblock(struct iproc *const out, const struct block *const block);
@@ -177,7 +178,7 @@ genexpr(struct iproc *const out, const size_t expri, uint64_t *const val)
}
return VT_TEMP;
case EXPR_IDENT: {
- struct decl *decl = finddecl(expr->d.s);
+ struct decl *decl = finddecl(blocks, expr->d.s);
if (decl == NULL)
die("genexpr: EXPR_IDENT: decl is null");
struct type *type = &types.data[decl->type];
@@ -235,7 +236,8 @@ genexpr(struct iproc *const out, const size_t expri, uint64_t *const val)
case UOP_REF: {
struct expr *operand = &exprs.data[expr->d.uop.expr];
assert(operand->kind == EXPR_IDENT);
- struct decl *decl = finddecl(operand->d.s);
+ struct decl *decl = finddecl(blocks, operand->d.s);
+ assert(decl);
// a global
if (decl->toplevel) {
*val = immediate(out, PTRSIZE, decl->w.addr);
@@ -289,27 +291,27 @@ genexpr(struct iproc *const out, const size_t expri, uint64_t *const val)
size_t startlabel = bumplabel(out), endlabel = bumplabel(out);
if (expr->d.cond.belse.len) {
size_t elselabel = bumplabel(out);
- blockpush(&expr->d.cond.bif);
+ stackpush(blocks, &expr->d.cond.bif);
NEWBLOCK(startlabel, elselabel);
LABEL(startlabel);
STARTINS(IR_CONDJUMP, elselabel, VT_LABEL);
putins(out, IR_EXTRA, condtmp, valtype);
genblock(out, &expr->d.cond.bif);
- blockpop();
+ stackpop(blocks);
STARTINS(IR_JUMP, endlabel, VT_LABEL);
- blockpush(&expr->d.cond.belse);
+ stackpush(blocks, &expr->d.cond.belse);
NEWBLOCK(elselabel, endlabel);
LABEL(elselabel);
genblock(out, &expr->d.cond.belse);
- blockpop();
+ stackpop(blocks);
LABEL(endlabel);
} else {
- blockpush(&expr->d.cond.bif);
+ stackpush(blocks, &expr->d.cond.bif);
STARTINS(IR_CONDJUMP, endlabel, VT_LABEL);
NEWBLOCK(startlabel, endlabel);
putins(out, IR_EXTRA, condtmp, valtype);
genblock(out, &expr->d.cond.bif);
- blockpop();
+ stackpop(blocks);
LABEL(endlabel);
}
return VT_EMPTY;
@@ -382,7 +384,7 @@ genblock(struct iproc *const out, const struct block *const block)
break;
case STMT_ASSGN:
assgn = &assgns.data[statement->idx];
- decl = finddecl(assgn->s);
+ decl = finddecl(blocks, assgn->s);
genassign(out, decl, assgn->val);
break;
case STMT_EXPR:
@@ -443,10 +445,11 @@ chooseregs(const struct iproc *const proc)
}
size_t
-genproc(struct decl *const decl, const struct proc *const proc)
+genproc(struct stack *blockstack, struct decl *const decl, const struct proc *const proc)
{
tmpi = labeli = curi = 1;
rblocki = reali = 0;
+ blocks = blockstack;
struct type *type;
struct iproc iproc = {
.s = decl->s,
@@ -473,7 +476,7 @@ genproc(struct decl *const decl, const struct proc *const proc)
LABEL(startlabel);
for (size_t j = 0; j < proc->in.len; j++, i++) {
- struct decl *decl = finddecl(proc->in.data[j].name);
+ struct decl *decl = finddecl(blocks, proc->in.data[j].name);
type = &types.data[proc->in.data[j].type];
size_t what = NEWTMP;
decl->index = what;
@@ -484,7 +487,7 @@ genproc(struct decl *const decl, const struct proc *const proc)
}
for (size_t j = 0; j < proc->out.len; j++, i++) {
- struct decl *decl = finddecl(proc->out.data[j].name);
+ struct decl *decl = finddecl(blocks, proc->out.data[j].name);
type = &types.data[proc->out.data[j].type];
size_t what = NEWTMP;
decl->index = what;
@@ -494,9 +497,9 @@ genproc(struct decl *const decl, const struct proc *const proc)
putins(out, IR_IN, i, VT_IMM);
}
- blockpush(&proc->block);
+ stackpush(blocks, &proc->block);
genblock(out, &proc->block);
- blockpop();
+ stackpop(blocks);
LABEL(endlabel);
chooseregs(&iproc);
diff --git a/ir.h b/ir.h
@@ -96,4 +96,4 @@ struct toplevel {
uint64_t entry;
};
-size_t genproc(struct decl *const decl, const struct proc *const proc);
+size_t genproc(struct stack *blockstack, struct decl *const decl, const struct proc *const proc);
diff --git a/lex.c b/lex.c
@@ -4,6 +4,7 @@
#include <stdlib.h>
#include "nooc.h"
+#include "stack.h"
#include "ir.h"
#include "util.h"
diff --git a/main.c b/main.c
@@ -10,14 +10,15 @@
#include "array.h"
#include "nooc.h"
+#include "stack.h"
#include "ir.h"
#include "util.h"
#include "elf.h"
#include "type.h"
#include "map.h"
-#include "blockstack.h"
#include "target.h"
+static struct stack blocks;
struct assgns assgns;
struct exprs exprs;
struct target targ;
@@ -88,8 +89,8 @@ void
gentoplevel(struct toplevel *toplevel, struct block *block)
{
char syscallname[] = "syscall0";
- blockpush(block);
- typecheck(block);
+ stackpush(&blocks, block);
+ typecheck(&blocks, block);
struct iproc iproc = { 0 };
uint64_t curaddr = TEXT_OFFSET;
@@ -120,11 +121,11 @@ gentoplevel(struct toplevel *toplevel, struct block *block)
toplevel->entry = curaddr;
}
assert(expr->kind == EXPR_PROC);
- blockpush(&expr->d.proc.block);
- typecheck(&expr->d.proc.block);
+ stackpush(&blocks, &expr->d.proc.block);
+ typecheck(&blocks, &expr->d.proc.block);
decl->w.addr = curaddr;
- curaddr += genproc(decl, &expr->d.proc);
- blockpop();
+ curaddr += genproc(&blocks, decl, &expr->d.proc);
+ stackpop(&blocks);
} else {
evalexpr(decl);
}
@@ -135,7 +136,7 @@ gentoplevel(struct toplevel *toplevel, struct block *block)
}
}
- blockpop();
+ stackpop(&blocks);
}
struct stat statbuf;
diff --git a/map.c b/map.c
@@ -23,6 +23,7 @@ THIS SOFTWARE.
#include <string.h>
#include "nooc.h"
+#include "stack.h"
#include "ir.h"
#include "util.h"
#include "map.h"
diff --git a/parse.c b/parse.c
@@ -4,14 +4,16 @@
#include <stdlib.h>
#include "nooc.h"
+#include "stack.h"
#include "ir.h"
#include "util.h"
#include "array.h"
#include "type.h"
#include "map.h"
-#include "blockstack.h"
static const struct token *tok;
+static struct stack blocks;
+
static void parsenametypes(struct nametypes *const nametypes);
static size_t parsetype();
@@ -168,7 +170,7 @@ parseexpr(struct block *const block)
// a function call
} else if (tok->next && tok->next->type == TOK_LPAREN) {
expr.d.call.name = tok->slice;
- decl = finddecl(expr.d.call.name);
+ decl = finddecl(&blocks, expr.d.call.name);
if (slice_cmplit(&expr.d.call.name, "syscall") == 0) {
expr.class = C_INT;
} else {
@@ -199,7 +201,7 @@ parseexpr(struct block *const block)
expr.kind = EXPR_IDENT;
expr.d.s = tok->slice;
- decl = finddecl(expr.d.s);
+ decl = finddecl(&blocks, expr.d.s);
if (decl == NULL)
error(expr.start->line, expr.start->col, "undeclared identifier '%.*s'", expr.d.s.len, expr.d.s.data);
expr.class = typetoclass(&types.data[decl->type]);
@@ -368,9 +370,9 @@ static void
parseblock(struct block *const block)
{
struct statement statement;
- bool toplevel = blockpeek() == NULL;
+ bool toplevel = stackpeek(&blocks) == NULL;
- blockpush(block);
+ stackpush(&blocks, block);
if (!toplevel)
EXPECTADV(TOK_LCURLY);
@@ -391,7 +393,7 @@ parseblock(struct block *const block)
decl.type = parsetype();
EXPECTADV(TOK_EQUAL);
- if (finddecl(decl.s))
+ if (finddecl(&blocks, decl.s))
error(tok->line, tok->col, "repeat declaration!");
decl.val = parseexpr(block);
@@ -425,7 +427,7 @@ parseblock(struct block *const block)
if (!toplevel)
EXPECTADV(TOK_RCURLY);
- blockpop();
+ stackpop(&blocks);
}
struct block
@@ -434,5 +436,9 @@ parse(const struct token *const start)
tok = start;
struct block block = { 0 };
parseblock(&block);
+ if (blocks.data)
+ free(blocks.data);
+
+ blocks = (struct stack){ 0 };
return block;
}
diff --git a/stack.c b/stack.c
@@ -0,0 +1,38 @@
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "nooc.h"
+#include "stack.h"
+#include "ir.h"
+#include "util.h"
+
+void
+stackpush(struct stack *const stack, const void *const ptr)
+{
+ if (stack->cap == stack->idx) {
+ stack->cap = stack->cap ? stack->cap * 2 : 1;
+ stack->data = xrealloc(stack->data, sizeof(void *) * stack->cap);
+ }
+
+ stack->data[stack->idx++] = ptr;
+}
+
+const void *const
+stackpop(struct stack *const stack)
+{
+ if (stack->idx == 0)
+ die("blockpop: cannot pop empty stack!");
+
+ return stack->data[--stack->idx];
+}
+
+const void *const
+stackpeek(const struct stack *const stack)
+{
+ if (stack->idx == 0)
+ return NULL;
+
+ return stack->data[stack->idx - 1];
+}
+
diff --git a/stack.h b/stack.h
@@ -0,0 +1,8 @@
+struct stack {
+ size_t cap, idx;
+ const void **data;
+};
+
+void stackpush(struct stack *const stack, const void *const ptr);
+const void *const stackpop(struct stack *const stack);
+const void *const stackpeek(const struct stack *const stack);
diff --git a/type.c b/type.c
@@ -5,18 +5,20 @@
#include <string.h>
#include "nooc.h"
+#include "stack.h"
#include "ir.h"
#include "util.h"
#include "type.h"
#include "map.h"
#include "blake3.h"
#include "array.h"
-#include "blockstack.h"
// hashtable based on cproc's map.c
struct types types;
+static const struct stack *blocks;
+
static struct typetable {
size_t cap, count;
struct typekey *keys;
@@ -214,7 +216,7 @@ static void
typecheckcall(const struct expr *const expr)
{
assert(expr->kind == EXPR_FCALL);
- const struct decl *const decl = finddecl(expr->d.call.name);
+ const struct decl *const decl = finddecl(blocks, expr->d.call.name);
if (decl == NULL) {
if (slice_cmplit(&expr->d.call.name, "syscall") == 0)
@@ -261,8 +263,9 @@ typecheckexpr(const size_t expri)
}
void
-typecheck(const struct block *const block)
+typecheck(const struct stack *const blockstack, const struct block *const block)
{
+ blocks = blockstack;
for (size_t i = 0; i < block->len; i++) {
const struct statement *const statement = &block->data[i];
const struct decl *decl;
@@ -270,7 +273,7 @@ typecheck(const struct block *const block)
switch (block->data[i].kind) {
case STMT_ASSGN:
assgn = &assgns.data[statement->idx];
- decl = finddecl(assgn->s);
+ decl = finddecl(blocks, assgn->s);
if (decl == NULL)
error(assgn->start->line, assgn->start->col, "typecheck: unknown name '%.*s'", assgn->s.len, assgn->s.data);
@@ -294,4 +297,6 @@ typecheck(const struct block *const block)
error(statement->start->line, statement->start->col, "unknown statement type");
}
}
+
+ blocks = NULL;
}
diff --git a/type.h b/type.h
@@ -2,6 +2,6 @@ const size_t type_get(const uint8_t hash[16]);
const size_t type_put(const struct type *const type);
void inittypes();
const size_t typeref(const size_t typei);
-void typecheck(const struct block *const block);
+void typecheck(const struct stack *const blocks, const struct block *const block);
extern struct types types;
diff --git a/util.c b/util.c
@@ -6,6 +6,7 @@
#include <string.h>
#include "nooc.h"
+#include "stack.h"
#include "ir.h"
#include "array.h"
#include "util.h"
@@ -228,6 +229,22 @@ dumpir(const struct iproc *const instrs)
}
}
+struct decl *
+finddecl(const struct stack *const blocks, const struct slice s)
+{
+ for (int j = blocks->idx - 1; j >= 0; j--) {
+ const struct block *block = blocks->data[j];
+ for (int i = 0; i < block->decls.len; i++) {
+ struct decl *decl = &block->decls.data[i];
+ if (slice_cmp(&s, &decl->s) == 0) {
+ return decl;
+ }
+ }
+ }
+
+ return NULL;
+}
+
int
slice_cmp(const struct slice *const s1, const struct slice *const s2)
{
diff --git a/util.h b/util.h
@@ -3,6 +3,7 @@ void dumpval(const struct expr *const e);
void dumpbinop(const struct binop *const op);
void dumpexpr(const int indent, const struct expr *const expr);
void dumpir(const struct iproc *const instrs);
+struct decl *finddecl(const struct stack *const blocks, struct slice s);
int slice_cmp(const struct slice *const s1, const struct slice *const s2);
int slice_cmplit(const struct slice *const s1, const char *const s2);
void error(const size_t line, const size_t col, const char *error, ...);
diff --git a/x64.c b/x64.c
@@ -4,6 +4,7 @@
#include <string.h>
#include "nooc.h"
+#include "stack.h"
#include "ir.h"
#include "util.h"
#include "array.h"