harec

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit ba13e1099a3818307a3209e5c329130bde791ff9
parent 28541ae45185f623f7ff4693081ec3144f477858
Author: Eyal Sawady <ecs@d2evs.net>
Date:   Tue,  8 Mar 2022 12:15:52 +0000

lex: separate negative literals into two tokens

Fixes some lexer ambiguities and allows negative unsigned constants

Signed-off-by: Eyal Sawady <ecs@d2evs.net>

Diffstat:
Minclude/qbe.h | 1+
Msrc/check.c | 11+++++++++++
Msrc/eval.c | 6+++++-
Msrc/gen.c | 3+--
Msrc/lex.c | 34++++++++++++++++------------------
Msrc/qbe.c | 1+
Mtests/00-constants.ha | 2+-
Mtests/10-binarithms.ha | 2+-
Mtests/29-unarithm.ha | 4+++-
9 files changed, 40 insertions(+), 24 deletions(-)

diff --git a/include/qbe.h b/include/qbe.h @@ -134,6 +134,7 @@ enum qbe_instr { Q_OR, Q_REM, Q_RET, + Q_NEG, Q_SAR, Q_SHL, Q_SHR, diff --git a/src/check.c b/src/check.c @@ -2633,6 +2633,17 @@ check_expr_unarithm(struct context *ctx, expr->result = operand->result; break; case UN_MINUS: + if (operand->result->storage == STORAGE_ICONST) { + // Not technically quite right, but we need + // operand->result to be lowered with expr->result, and + // this is correct enough + const struct type *old = operand->result; + const struct type *new = type_create_const( + STORAGE_ICONST, -old->_const.min, + -old->_const.max); + lower_const(old, new); + } + // Fallthrough case UN_PLUS: if (!type_is_numeric(operand->result)) { error(ctx, aexpr->unarithm.operand->loc, expr, diff --git a/src/eval.c b/src/eval.c @@ -755,7 +755,11 @@ eval_unarithm(struct context *ctx, struct expression *in, struct expression *out out->constant.bval = !lvalue.constant.bval; break; case UN_MINUS: - out->constant.ival = -lvalue.constant.ival; + if (type_is_float(out->result)) { + out->constant.fval = -lvalue.constant.fval; + } else { + out->constant.ival = -lvalue.constant.ival; + } break; case UN_PLUS: out->constant = lvalue.constant; diff --git a/src/gen.c b/src/gen.c @@ -2766,8 +2766,7 @@ gen_expr_unarithm(struct gen_context *ctx, val = gen_expr(ctx, operand); temp = mktemp(ctx, operand->result, ".%d"); qval = mkqval(ctx, &val), qtmp = mkqval(ctx, &temp); - struct qbe_value zerol = constl(0); - pushi(ctx->current, &qtmp, Q_SUB, &zerol, &qval, NULL); + pushi(ctx->current, &qtmp, Q_NEG, &qval, NULL); return temp; case UN_PLUS: return gen_expr(ctx, operand); diff --git a/src/lex.c b/src/lex.c @@ -279,9 +279,6 @@ static uint32_t lex_literal(struct lexer *lexer, struct token *out) { uint32_t c = next(lexer, &out->loc, true); - if (c == '-') { - c = next(lexer, NULL, true); - } assert(c != UTF8_INVALID && c <= 0x7F && isdigit(c)); int base = 10; @@ -434,16 +431,13 @@ finalize: } break; case STORAGE_ICONST: - if (lexer->buf[0] != '-') { - uintmax_t uval = strtoumax(lexer->buf, NULL, base); - for (intmax_t i = 0; i < exponent; i++) { - uval *= 10; - } - if (uval > (uintmax_t)INT64_MAX) { - out->storage = STORAGE_U64; - out->uval = uval; - break; - } + out->uval = strtoumax(lexer->buf, NULL, base); + for (intmax_t i = 0; i < exponent; i++) { + out->uval *= 10; + } + if (out->uval > (uintmax_t)INT64_MAX) { + out->storage = STORAGE_U64; + break; } // Fallthrough case STORAGE_I8: @@ -451,6 +445,15 @@ finalize: case STORAGE_I32: case STORAGE_INT: case STORAGE_I64: + out->uval = strtoumax(lexer->buf, NULL, base); + for (intmax_t i = 0; i < exponent; i++) { + out->uval *= 10; + } + if (out->uval == (uintmax_t)INT64_MIN) { + // XXX: Hack + out->ival = INT64_MIN; + break; + } out->ival = strtoimax(lexer->buf, NULL, base); for (intmax_t i = 0; i < exponent; i++) { out->ival *= 10; @@ -816,11 +819,6 @@ lex2(struct lexer *lexer, struct token *out, uint32_t c) out->token = T_MINUSEQ; break; default: - if (c != UTF8_INVALID && c <= 0x7F && isdigit(c)) { - push(lexer, c, false); - push(lexer, '-', false); - return lex_literal(lexer, out); - } push(lexer, c, false); out->token = T_MINUS; break; diff --git a/src/qbe.c b/src/qbe.c @@ -106,6 +106,7 @@ const char *qbe_instr[Q_LAST_INSTR] = { [Q_LOADUH] = "loaduh", [Q_LOADUW] = "loaduw", [Q_MUL] = "mul", + [Q_NEG] = "neg", [Q_OR] = "or", [Q_REM] = "rem", [Q_RET] = "ret", diff --git a/tests/00-constants.ha b/tests/00-constants.ha @@ -135,7 +135,7 @@ fn aggregates() void = { export fn main() void = { let i1 = 13, i2 = 13i, i3 = 13i8, i4 = 13i16, i5 = 13i32, i6 = 13i64; let u1 = 13u, u2 = 13z, u3 = 13u8, u4 = 13u16, u5 = 13u32, u6 = 13u64; - let n = -13; + let n1 = -13, n2 = -13u; let b1 = true, b2 = false; let p1: nullable *int = null; let r1 = 'x', r2 = '\x0A', r3 = '\u1234', r4 = '\0', r5 = '\a', diff --git a/tests/10-binarithms.ha b/tests/10-binarithms.ha @@ -71,7 +71,7 @@ fn sar_shr() void = { let x = 1i64; x <<= 63; - assert(x == -9223372036854775808); + assert(x == -9223372036854775808i64); x >>= 63; assert(x == -1); diff --git a/tests/29-unarithm.ha b/tests/29-unarithm.ha @@ -14,7 +14,9 @@ fn addr() void = { let z = &struct { a: int = 42 }; assert(z.a == 42); let a = -2; - assert(a == 0i - 2i); + assert(a == 0 - 2); + let b = 1-1; + assert(b == 0); }; export fn main() void = {