nooc

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

commit 4d0e68ae8339813f94cb46ed56140ae72031ae51
parent ef5ac4a6e8831874b370529cd530e2207a750a61
Author: Nihal Jere <nihal@nihaljere.xyz>
Date:   Thu, 27 Jan 2022 20:08:52 -0600

add not operator

Diffstat:
Mir.c | 9+++++++++
Mir.h | 3+++
Mlex.c | 3+++
Mnooc.h | 2++
Mparse.c | 10++++++++++
Atest/not.pass.nooc | 10++++++++++
Mutil.c | 3+++
Mx64.c | 21+++++++++++++++++++++
8 files changed, 61 insertions(+), 0 deletions(-)

diff --git a/ir.c b/ir.c @@ -88,6 +88,7 @@ putins(struct iproc *out, int op, uint64_t val, int valtype) case IR_LOAD: case IR_ADD: case IR_CEQ: + case IR_NOT: case IR_ZEXT: case IR_ASSIGN: case IR_CALLARG: @@ -276,6 +277,14 @@ genexpr(struct iproc *out, size_t expri, uint64_t *val) } break; } + case UOP_NOT: { + uint64_t arg; + int type = genexpr(out, expr->d.uop.expr, &arg); + assert(type == VT_TEMP); + *val = assign(out, 4); // FIXME: how big should bools be? + putins(out, IR_NOT, arg, VT_TEMP); + break; + } default: die("genexpr: EXPR_UNARY: unhandled unop kind"); } diff --git a/ir.h b/ir.h @@ -14,6 +14,9 @@ struct instr { IR_CONDJUMP, IR_JUMP, + // unary ops + IR_NOT, + // binary ops IR_ADD, diff --git a/lex.c b/lex.c @@ -57,6 +57,9 @@ lex(struct slice start) } else if (*start.data == '>') { cur->type = TOK_GREATER; ADVANCE(1); + } else if (*start.data == '!') { + cur->type = TOK_NOT; + ADVANCE(1); } else if (*start.data == '$') { cur->type = TOK_DOLLAR; ADVANCE(1); diff --git a/nooc.h b/nooc.h @@ -17,6 +17,7 @@ enum tokentype { TOK_PLUS, TOK_MINUS, TOK_GREATER, + TOK_NOT, TOK_DOLLAR, @@ -197,6 +198,7 @@ struct binop { struct unop { enum { UOP_REF, + UOP_NOT, } kind; size_t expr; }; diff --git a/parse.c b/parse.c @@ -237,6 +237,16 @@ parseexpr(struct block *block) case TOK_NUM: parsenum(&expr); break; + case TOK_NOT: + expr.start = tok; + tok = tok->next; + expr.kind = EXPR_UNARY; + expr.d.uop.kind = UOP_NOT; + expr.d.uop.expr = parseexpr(block); + if (exprs.data[expr.d.uop.expr].class != C_BOOL) + error(tok->line, tok->col, "expected boolean expression as not operand"); + expr.class = C_BOOL; + break; case TOK_EQUAL: expr.kind = EXPR_BINARY; expr.d.bop.kind = BOP_EQUAL; diff --git a/test/not.pass.nooc b/test/not.pass.nooc @@ -0,0 +1,9 @@ +let main proc() = proc() { + let a i64 = 10 + let b i64 = 20 + if != a b { + syscall2(60, 0) + } else { + syscall2(60, 1) + } +}+ \ No newline at end of file diff --git a/util.c b/util.c @@ -184,6 +184,9 @@ dumpir(struct iproc *instrs) case IR_CEQ: fprintf(stderr, "ceq %c%lu", sig, instr->val); break; + case IR_NOT: + fprintf(stderr, "not %c%lu\n", sig, instr->val); + break; case IR_ZEXT: fprintf(stderr, "zext %c%lu\n", sig, instr->val); break; diff --git a/x64.c b/x64.c @@ -692,6 +692,20 @@ sete_reg(struct data *text, enum reg reg) } static size_t +setne_reg(struct data *text, enum reg reg) +{ + uint8_t temp; + if (text) { + if (reg >= 8) array_addlit(text, REX_B); + array_addlit(text, 0x0F); + array_addlit(text, 0x95); + array_addlit(text, (MOD_DIRECT << 6) | (reg & 7)); + } + + return 3 + !(reg < 8); +} + +static size_t jmp(struct data *text, int64_t offset) { uint8_t temp; @@ -879,6 +893,13 @@ emitblock(struct data *text, struct iproc *proc, struct instr *start, struct ins NEXT; switch (ins->op) { + case IR_NOT: + assert(ins->valtype == VT_TEMP); + assert(size == 4); + total += cmp_r32_r32(text, src, proc->temps.data[ins->val].reg); + total += setne_reg(text, dest); + NEXT; + break; case IR_CEQ: assert(ins->valtype == VT_TEMP); src = proc->temps.data[ins->val].reg;