nooc

Unnamed repository; edit this file 'description' to name the repository.
git clone git://git.nihaljere.xyz/nooc
Log | Files | Refs | LICENSE

commit bdc3445101fd47655e34d3c3f4837353f026422a
parent 0c368512a89dd2f9bdf3d9845be372d47f8adb74
Author: Nihal Jere <nihal@nihaljere.xyz>
Date:   Tue, 16 Nov 2021 18:35:41 -0600

add initial expression codegen

this is necessary before we do codegen for binary expressions

Diffstat:
Mmain.c | 178+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
1 file changed, 138 insertions(+), 40 deletions(-)

diff --git a/main.c b/main.c @@ -12,7 +12,7 @@ #include "array.h" int -elf(char *text, size_t len, char*data, size_t dlen, FILE *f) +elf(char *text, size_t len, char* data, size_t dlen, FILE *f) { Elf64_Ehdr ehdr = { 0 }; Elf64_Phdr phdr_text = { 0 }; @@ -76,7 +76,6 @@ elf(char *text, size_t len, char*data, size_t dlen, FILE *f) enum tokentype { TOK_NONE = 0, TOK_SYSCALL = 1, - TOK_PRINT, TOK_LPAREN, TOK_RPAREN, @@ -169,7 +168,6 @@ lex(struct slice start) cur->type = TOK_PLUS; start.ptr++; start.len--; - continue; } else { error("invalid token"); } @@ -194,7 +192,7 @@ enum func { struct fparams { size_t cap; size_t len; - struct expr *data; + size_t *data; }; struct fcall { @@ -234,53 +232,134 @@ struct calls { }; enum primitive { - I32, - STR, + P_INT, + P_STR, +}; + +enum binop { + OP_PLUS, }; struct value { enum primitive type; - uint64_t val; + union { + uint64_t val; + struct slice s; + } v; +}; + +enum exprkind { + EXPR_LIT, + EXPR_BINARY }; +char *exprkind_str(enum exprkind kind) +{ + switch (kind) { + case EXPR_LIT: + return "EXPR_LIT"; + case EXPR_BINARY: + return "EXPR_BINARY"; + default: + error("invalid exprkind"); + } +} + struct expr { - enum { - EXPR_LIT, - EXPR_BINARY - } kind; - struct value val; - struct expr *left; - struct expr *right; + enum exprkind kind; + union { + struct value v; + enum binop op; + } d; + size_t left; + size_t right; }; -struct expr +struct exprs { + size_t cap; + size_t len; + struct expr *data; +} exprs; + +void +dumpval(struct value v) +{ + switch (v.type) { + case P_INT: + fprintf(stderr, "%ld", v.v.val); + break; + case P_STR: + fprintf(stderr, "\"%.*s\"", v.v.s.len, v.v.s.ptr); + break; + } +} + +void +dumpbinop(enum binop op) +{ + switch (op) { + case OP_PLUS: + fprintf(stderr, "OP_PLUS"); + break; + default: + error("invalid binop"); + } +} + +void +dumpexpr(int indent, struct expr *expr) +{ + for (int i = 0; i < indent; i++) + fputc(' ', stderr); + fprintf(stderr, "%s: ", exprkind_str(expr->kind)); + switch (expr->kind) { + case EXPR_LIT: + dumpval(expr->d.v); + fprintf(stderr, "\n"); + break; + case EXPR_BINARY: + dumpbinop(expr->d.op); + fprintf(stderr, "\n"); + dumpexpr(indent + 8, &exprs.data[expr->left]); + dumpexpr(indent + 8, &exprs.data[expr->right]); + break; + default: + error("dumpexpr: bad expression"); + } +} + +size_t parseexpr(struct token **tok) { struct expr expr = { 0 }; - while (1) { - switch ((*tok)->type) { - case TOK_NUM: - expr.kind = EXPR_LIT; - expr.val.type = I32; - expr.val.val = strtol((*tok)->slice.ptr, NULL, 10); - *tok = (*tok)->next; - break; - case TOK_STRING: - // FIXME: error check - expr.kind = EXPR_LIT; - expr.val.type = STR; - expr.val.val = data_push((*tok)->slice.ptr, (*tok)->slice.len); - *tok = (*tok)->next; - break; - default: - error("invalid token for expression"); - } - - if ((*tok)->type == TOK_COMMA || (*tok)->type == TOK_RPAREN) - break; + switch ((*tok)->type) { + case TOK_NUM: + expr.kind = EXPR_LIT; + expr.d.v.type = P_INT; + // FIXME: error check + expr.d.v.v.val = strtol((*tok)->slice.ptr, NULL, 10); + *tok = (*tok)->next; + break; + case TOK_PLUS: + expr.kind = EXPR_BINARY; + expr.d.op = OP_PLUS; + *tok = (*tok)->next; + expr.left = parseexpr(tok); + expr.right = parseexpr(tok); + break; + case TOK_STRING: + expr.kind = EXPR_LIT; + expr.d.v.type = P_STR; + expr.d.v.v.s = (*tok)->slice; + *tok = (*tok)->next; + break; + default: + error("invalid token for expression"); } - return expr; + array_add((&exprs), expr); + + return exprs.len - 1; } struct calls @@ -288,7 +367,7 @@ parse(struct token *tok) { struct calls calls = { 0 }; struct fcall fcall; - struct expr expr; + size_t expr; while (tok->type != TOK_NONE) { fcall = (struct fcall){ 0 }; @@ -362,6 +441,24 @@ mov_r_imm(char *buf, enum Register reg, uint64_t imm) char abi_arg[] = {RAX, RDI, RSI, RDX, R10, R8, R9}; size_t +genexpr(char *buf, size_t idx, int reg) +{ + // FIXME: this doesn't work for binary expressions + size_t len = 0; + char *ptr = buf; + struct expr *expr = &exprs.data[idx]; + if (expr->kind == EXPR_LIT && expr->d.v.type == P_INT) { + len = mov_r_imm(ptr ? ptr + len : ptr, reg, expr->d.v.v.val); + } else if (expr->kind == EXPR_LIT && expr->d.v.type == P_STR) { + int addr = data_push(expr->d.v.v.s.ptr, expr->d.v.v.s.len); + len = mov_r_imm(ptr ? ptr + len : ptr, reg, addr); + } else { + error("genexpr: could not generate code for expression"); + } + return len; +} + +size_t gensyscall(char *buf, struct fparams *params) { size_t len = 0; @@ -372,7 +469,7 @@ gensyscall(char *buf, struct fparams *params) // encoding for argument registers in ABI order for (int i = 0; i < params->len; i++) { - len += mov_r_imm(ptr ? ptr + len : ptr, abi_arg[i], params->data[i].val.val); + len += genexpr(ptr ? ptr + len : ptr, params->data[i], abi_arg[i]); } if (buf) { @@ -411,7 +508,6 @@ main(int argc, char *argv[]) struct token *head = lex((struct slice){addr, statbuf.st_size}); struct calls calls = parse(head); - munmap(addr, statbuf.st_size); FILE *out = fopen(argv[2], "w"); if (!out) { @@ -433,6 +529,8 @@ main(int argc, char *argv[]) free(fcode); } + munmap(addr, statbuf.st_size); + elf(text.data, text.len, data_seg.data, data_seg.len, out);