diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2024-11-03 15:48:13 -0500 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2024-11-03 15:48:13 -0500 |
| commit | 3743913ce2c5bc37f899d437c09b60cbb3bc6dea (patch) | |
| tree | cbbe7fe8debc7651c915b727f608bf2bcfa151ea /compile.c | |
| parent | 792743dff3b4af6df030a53e447b28a8a3e8b072 (diff) | |
Add unsigned integer shifts
Diffstat (limited to 'compile.c')
| -rw-r--r-- | compile.c | 34 |
1 files changed, 31 insertions, 3 deletions
@@ -28,6 +28,7 @@ static CORD compile_string(env_t *env, ast_t *ast, CORD color); static CORD compile_arguments(env_t *env, ast_t *call_ast, arg_t *spec_args, arg_ast_t *call_args); static CORD compile_maybe_incref(env_t *env, ast_t *ast); static CORD compile_int_to_type(env_t *env, ast_t *ast, type_t *target); +static CORD compile_unsigned_type(type_t *t); static CORD promote_to_optional(type_t *t, CORD code); static CORD compile_null(type_t *t); @@ -198,6 +199,19 @@ CORD compile_declaration(type_t *t, CORD name) } } +PUREFUNC CORD compile_unsigned_type(type_t *t) +{ + if (t->tag != IntType) + errx(1, "Not an int type, so unsigned doesn't make sense!"); + switch (Match(t, IntType)->bits) { + case TYPE_IBITS8: return "uint8_t"; + case TYPE_IBITS16: return "uint16_t"; + case TYPE_IBITS32: return "uint32_t"; + case TYPE_IBITS64: return "uint64_t"; + default: errx(1, "Invalid integer bit size"); + } +} + CORD compile_type(type_t *t) { if (t == THREAD_TYPE) return "Thread_t"; @@ -1772,7 +1786,7 @@ CORD compile_math_method(env_t *env, binop_e op, ast_t *lhs, ast_t *rhs, type_t } break; } - case BINOP_LSHIFT: case BINOP_RSHIFT: { + case BINOP_LSHIFT: case BINOP_RSHIFT: case BINOP_ULSHIFT: case BINOP_URSHIFT: { if (rhs_t->tag == IntType || rhs_t->tag == BigIntType) { binding_t *b = get_namespace_binding(env, lhs, binop_method_names[op]); if (binding_works(b, lhs_t, rhs_t, lhs_t)) @@ -2051,13 +2065,17 @@ CORD compile(env_t *env, ast_t *ast) CORD lhs = compile(env, binop->lhs); // Special case for bit shifting by an integer literal: - if (binop->op == BINOP_LSHIFT || binop->op == BINOP_RSHIFT) { + if (binop->op == BINOP_LSHIFT || binop->op == BINOP_RSHIFT || binop->op == BINOP_ULSHIFT || binop->op == BINOP_URSHIFT) { if (lhs_t->tag == IntType && rhs_t->tag == BigIntType && binop->rhs->tag == Int) { CORD shift_amount = compile_int_to_type(env, binop->rhs, lhs_t); if (binop->op == BINOP_LSHIFT) return CORD_all("(", lhs, " << ", shift_amount, ")"); - else + else if (binop->op == BINOP_ULSHIFT) + return CORD_all("(", compile_type(lhs_t), ")((", compile_unsigned_type(lhs_t), ")", lhs, " << ", shift_amount, ")"); + else if (binop->op == BINOP_RSHIFT) return CORD_all("(", lhs, " >> ", shift_amount, ")"); + else if (binop->op == BINOP_URSHIFT) + return CORD_all("(", compile_type(lhs_t), ")((", compile_unsigned_type(lhs_t), ")", lhs, " >> ", shift_amount, ")"); } } @@ -2120,6 +2138,16 @@ CORD compile(env_t *env, ast_t *ast) code_err(ast, "Math operations are only supported for values of the same numeric type, not %T vs %T", lhs_t, rhs_t); return CORD_all("(", lhs, " >> ", rhs, ")"); } + case BINOP_ULSHIFT: { + if (operand_t->tag != IntType && operand_t->tag != NumType && operand_t->tag != ByteType) + code_err(ast, "Math operations are only supported for values of the same numeric type, not %T vs %T", lhs_t, rhs_t); + return CORD_all("(", compile_type(operand_t), ")((", compile_unsigned_type(lhs_t), ")", lhs, " << ", rhs, ")"); + } + case BINOP_URSHIFT: { + if (operand_t->tag != IntType && operand_t->tag != NumType && operand_t->tag != ByteType) + code_err(ast, "Math operations are only supported for values of the same numeric type, not %T vs %T", lhs_t, rhs_t); + return CORD_all("(", compile_type(operand_t), ")((", compile_unsigned_type(lhs_t), ")", lhs, " >> ", rhs, ")"); + } case BINOP_EQ: { switch (operand_t->tag) { case BigIntType: |
