summaryrefslogtreecommitdiffhomepage
path: root/compiler.c
diff options
context:
space:
mode:
authorJo-Philipp Wich <jo@mein.io>2021-12-13 12:58:18 +0100
committerJo-Philipp Wich <jo@mein.io>2022-01-04 15:53:36 +0100
commitb605dbfcf04f310e08634b52507da7a4155bfce1 (patch)
tree04397dab9be96a5978e08366299671a8aa507267 /compiler.c
parent8907ce41a36f8d42097d884550fb3cfbba62e6c5 (diff)
treewide: rework numeric value handling
- Parse integer literals as unsigned numeric values in order to be able to represent the entire unsigned 64bit value range - Stop parsing minus-prefixed integer literals as negative numbers but treat them as separate minus operator followed by a positive integer instead - Only store unsigned numeric constants in bytecode - Rework numeric comparison logic to be able to handle full 64bit unsigned integers - If possible, yield unsigned 64 bit results for additions - Simplify numeric value conversion API - Compile code with -fwrapv for defined signed overflow semantics Signed-off-by: Jo-Philipp Wich <jo@mein.io>
Diffstat (limited to 'compiler.c')
-rw-r--r--compiler.c55
1 files changed, 19 insertions, 36 deletions
diff --git a/compiler.c b/compiler.c
index e7bbd7f..b6793d7 100644
--- a/compiler.c
+++ b/compiler.c
@@ -15,6 +15,7 @@
*/
#include <assert.h>
+#include <errno.h>
#include "ucode/compiler.h"
#include "ucode/chunk.h"
@@ -410,15 +411,6 @@ uc_compiler_emit_u8(uc_compiler_t *compiler, size_t srcpos, uint8_t n)
}
static size_t
-uc_compiler_emit_s8(uc_compiler_t *compiler, size_t srcpos, int8_t n)
-{
- return uc_chunk_add(
- uc_compiler_current_chunk(compiler),
- n + 0x7f,
- uc_compiler_set_srcpos(compiler, srcpos));
-}
-
-static size_t
uc_compiler_emit_u16(uc_compiler_t *compiler, size_t srcpos, uint16_t n)
{
uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
@@ -431,19 +423,6 @@ uc_compiler_emit_u16(uc_compiler_t *compiler, size_t srcpos, uint16_t n)
}
static size_t
-uc_compiler_emit_s16(uc_compiler_t *compiler, size_t srcpos, int16_t n)
-{
- uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
- size_t lineoff = uc_compiler_set_srcpos(compiler, srcpos);
- uint16_t v = n + 0x7fff;
-
- uc_chunk_add(chunk, v / 0x100, lineoff);
- uc_chunk_add(chunk, v % 0x100, 0);
-
- return chunk->count - 2;
-}
-
-static size_t
uc_compiler_emit_u32(uc_compiler_t *compiler, size_t srcpos, uint32_t n)
{
uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
@@ -866,6 +845,7 @@ uc_compiler_emit_inc_dec(uc_compiler_t *compiler, uc_tokentype_t toktype, bool i
uc_value_t *varname = NULL;
uc_vm_insn_t type;
uint32_t cidx = 0;
+ int insn;
/* determine kind of emitted load instruction and operand value (if any) */
type = chunk->entries ? chunk->entries[compiler->last_insn] : 0;
@@ -901,30 +881,32 @@ uc_compiler_emit_inc_dec(uc_compiler_t *compiler, uc_tokentype_t toktype, bool i
return;
}
+ insn = (toktype == TK_INC) ? I_PLUS : I_MINUS;
+
/* add / substract 1 */
uc_compiler_emit_insn(compiler, 0, I_LOAD8);
- uc_compiler_emit_s8(compiler, 0, (toktype == TK_INC) ? 1 : -1);
+ uc_compiler_emit_u8(compiler, 0, 1);
/* depending on variable type, emit corresponding increment instruction */
switch (type) {
case I_LVAR:
uc_compiler_emit_insn(compiler, 0, I_UVAR);
- uc_compiler_emit_u32(compiler, 0, (I_PLUS << 24) | cidx);
+ uc_compiler_emit_u32(compiler, 0, (insn << 24) | cidx);
break;
case I_LLOC:
uc_compiler_emit_insn(compiler, 0, I_ULOC);
- uc_compiler_emit_u32(compiler, 0, (I_PLUS << 24) | cidx);
+ uc_compiler_emit_u32(compiler, 0, (insn << 24) | cidx);
break;
case I_LUPV:
uc_compiler_emit_insn(compiler, 0, I_UUPV);
- uc_compiler_emit_u32(compiler, 0, (I_PLUS << 24) | cidx);
+ uc_compiler_emit_u32(compiler, 0, (insn << 24) | cidx);
break;
case I_LVAL:
uc_compiler_emit_insn(compiler, 0, I_UVAL);
- uc_compiler_emit_u8(compiler, 0, I_PLUS);
+ uc_compiler_emit_u8(compiler, 0, insn);
break;
default:
@@ -934,7 +916,7 @@ uc_compiler_emit_inc_dec(uc_compiler_t *compiler, uc_tokentype_t toktype, bool i
/* for post increment or decrement, add/substract 1 to yield final value */
if (is_postfix) {
uc_compiler_emit_insn(compiler, 0, I_LOAD8);
- uc_compiler_emit_s8(compiler, 0, 1);
+ uc_compiler_emit_u8(compiler, 0, 1);
uc_compiler_emit_insn(compiler, 0, (toktype == TK_INC) ? I_SUB : I_ADD);
}
@@ -1466,7 +1448,7 @@ static void
uc_compiler_compile_constant(uc_compiler_t *compiler)
{
uc_function_t *fn;
- int64_t n;
+ uint64_t u;
switch (compiler->parser->prev.type) {
case TK_THIS:
@@ -1502,19 +1484,20 @@ uc_compiler_compile_constant(uc_compiler_t *compiler)
break;
case TK_NUMBER:
- n = ucv_int64_get(compiler->parser->prev.uv);
+ u = ucv_uint64_get(compiler->parser->prev.uv);
+ assert(errno == 0);
- if (n >= -0x7f && n <= 0x7f) {
+ if (u <= 0xff) {
uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_LOAD8);
- uc_compiler_emit_s8(compiler, compiler->parser->prev.pos, n);
+ uc_compiler_emit_u8(compiler, compiler->parser->prev.pos, u);
}
- else if (n >= -0x7fff && n <= 0x7fff) {
+ else if (u <= 0xffff) {
uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_LOAD16);
- uc_compiler_emit_s16(compiler, compiler->parser->prev.pos, n);
+ uc_compiler_emit_u16(compiler, compiler->parser->prev.pos, u);
}
- else if (n >= -0x7fffffff && n <= 0x7fffffff) {
+ else if (u <= 0xffffffff) {
uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_LOAD32);
- uc_compiler_emit_s32(compiler, compiler->parser->prev.pos, n);
+ uc_compiler_emit_u32(compiler, compiler->parser->prev.pos, u);
}
else {
uc_compiler_emit_constant(compiler, compiler->parser->prev.pos, compiler->parser->prev.uv);