nooc

nooc programming language compiler
git clone git://git.nihaljere.xyz/nooc
Log | Files | Refs | LICENSE

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:
MMakefile | 4++--
Marray.c | 1+
Dblockstack.c | 55-------------------------------------------------------
Dblockstack.h | 4----
Mir.c | 33++++++++++++++++++---------------
Mir.h | 2+-
Mlex.c | 1+
Mmain.c | 17+++++++++--------
Mmap.c | 1+
Mparse.c | 20+++++++++++++-------
Astack.c | 38++++++++++++++++++++++++++++++++++++++
Astack.h | 8++++++++
Mtype.c | 13+++++++++----
Mtype.h | 2+-
Mutil.c | 17+++++++++++++++++
Mutil.h | 1+
Mx64.c | 1+
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"