updated the compiler to fix the jump instruction positions for break and continue upon instruction eliminations
This commit is contained in:
parent
c6cf64a586
commit
2a40be7742
@ -316,6 +316,15 @@ class MyObject(Object)
|
|||||||
].
|
].
|
||||||
|
|
||||||
(a associationAt: :(#aaa)) dump.
|
(a associationAt: :(#aaa)) dump.
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
[:j :q | (j + q) dump] value: (if (true) { 20 }) value: (if (true) { break }).
|
||||||
|
(1 + (if (false) {} else { break })) dump.
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
218
moo/lib/comp.c
218
moo/lib/comp.c
@ -1912,7 +1912,7 @@ static int end_include (moo_t* moo)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------
|
/* ---------------------------------------------------------------------
|
||||||
* Byte-Code Generator
|
* Byte-Code Manipulation Functions
|
||||||
* --------------------------------------------------------------------- */
|
* --------------------------------------------------------------------- */
|
||||||
|
|
||||||
static MOO_INLINE int emit_byte_instruction (moo_t* moo, moo_oob_t code)
|
static MOO_INLINE int emit_byte_instruction (moo_t* moo, moo_oob_t code)
|
||||||
@ -2223,28 +2223,154 @@ static int patch_long_forward_jump_instruction (moo_t* moo, moo_oow_t jip, moo_o
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int push_loop (moo_t* moo, moo_loop_type_t type, moo_oow_t startpos)
|
||||||
|
{
|
||||||
|
moo_loop_t* loop;
|
||||||
|
|
||||||
|
loop = moo_callocmem (moo, MOO_SIZEOF(*loop));
|
||||||
|
if (!loop) return -1;
|
||||||
|
|
||||||
|
init_oow_pool (moo, &loop->break_ip_pool);
|
||||||
|
init_oow_pool (moo, &loop->continue_ip_pool);
|
||||||
|
loop->type = type;
|
||||||
|
loop->startpos = startpos;
|
||||||
|
loop->next = moo->c->mth.loop;
|
||||||
|
moo->c->mth.loop = loop;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int update_loop_jumps (moo_t* moo, moo_oow_pool_t* pool, moo_oow_t jt)
|
||||||
|
{
|
||||||
|
/* patch the jump instructions emitted for 'break' or 'continue' */
|
||||||
|
moo_oow_pool_chunk_t* chunk;
|
||||||
|
moo_oow_t i, j;
|
||||||
|
|
||||||
|
for (chunk = pool->head, i = 0; chunk; chunk = chunk->next)
|
||||||
|
{
|
||||||
|
for (j = 0; j < MOO_COUNTOF(pool->static_chunk.buf) && i < pool->count; j++)
|
||||||
|
{
|
||||||
|
if (chunk->buf[j] != INVALID_IP &&
|
||||||
|
patch_long_forward_jump_instruction (moo, chunk->buf[j], jt, BCODE_JUMP2_FORWARD, MOO_NULL) <= -1) return -1;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void adjust_loop_jumps_for_elimination (moo_t* moo, moo_oow_pool_t* pool, moo_oow_t start, moo_oow_t end)
|
||||||
|
{
|
||||||
|
/* update the jump instruction positions emitted for 'break' or 'continue' */
|
||||||
|
moo_oow_pool_chunk_t* chunk;
|
||||||
|
moo_oow_t i, j;
|
||||||
|
|
||||||
|
for (chunk = pool->head, i = 0; chunk; chunk = chunk->next)
|
||||||
|
{
|
||||||
|
for (j = 0; j < MOO_COUNTOF(pool->static_chunk.buf) && i < pool->count; j++)
|
||||||
|
{
|
||||||
|
if (chunk->buf[j] != INVALID_IP)
|
||||||
|
{
|
||||||
|
if (chunk->buf[j] >= start && chunk->buf[j] <= end)
|
||||||
|
{
|
||||||
|
/* invalidate the instruction position */
|
||||||
|
chunk->buf[j] = INVALID_IP;
|
||||||
|
}
|
||||||
|
else if (chunk->buf[j] > end && chunk->buf[j] < moo->c->mth.code.len)
|
||||||
|
{
|
||||||
|
/* decrement the instruction position */
|
||||||
|
chunk->buf[j] -= end - start + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static MOO_INLINE int update_loop_breaks (moo_t* moo, moo_oow_t jt)
|
||||||
|
{
|
||||||
|
return update_loop_jumps (moo, &moo->c->mth.loop->break_ip_pool, jt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static MOO_INLINE int update_loop_continues (moo_t* moo, moo_oow_t jt)
|
||||||
|
{
|
||||||
|
return update_loop_jumps (moo, &moo->c->mth.loop->continue_ip_pool, jt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static MOO_INLINE void adjust_all_loop_jumps_for_elimination (moo_t* moo, moo_oow_t start, moo_oow_t end)
|
||||||
|
{
|
||||||
|
moo_loop_t* loop;
|
||||||
|
|
||||||
|
loop = moo->c->mth.loop;
|
||||||
|
while (loop)
|
||||||
|
{
|
||||||
|
adjust_loop_jumps_for_elimination (moo, &loop->break_ip_pool, start, end);
|
||||||
|
adjust_loop_jumps_for_elimination (moo, &loop->continue_ip_pool, start, end);
|
||||||
|
loop = loop->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static MOO_INLINE moo_loop_t* unlink_loop (moo_t* moo)
|
||||||
|
{
|
||||||
|
moo_loop_t* loop;
|
||||||
|
|
||||||
|
MOO_ASSERT (moo, moo->c->mth.loop != MOO_NULL);
|
||||||
|
loop = moo->c->mth.loop;
|
||||||
|
moo->c->mth.loop = loop->next;
|
||||||
|
|
||||||
|
return loop;
|
||||||
|
}
|
||||||
|
|
||||||
|
static MOO_INLINE void free_loop (moo_t* moo, moo_loop_t* loop)
|
||||||
|
{
|
||||||
|
fini_oow_pool (moo, &loop->continue_ip_pool);
|
||||||
|
fini_oow_pool (moo, &loop->break_ip_pool);
|
||||||
|
moo_freemem (moo, loop);
|
||||||
|
}
|
||||||
|
|
||||||
|
static MOO_INLINE void pop_loop (moo_t* moo)
|
||||||
|
{
|
||||||
|
free_loop (moo, unlink_loop (moo));
|
||||||
|
}
|
||||||
|
|
||||||
|
static MOO_INLINE int inject_break_to_loop (moo_t* moo)
|
||||||
|
{
|
||||||
|
if (add_to_oow_pool (moo, &moo->c->mth.loop->break_ip_pool, moo->c->mth.code.len) <= -1 ||
|
||||||
|
emit_single_param_instruction (moo, BCODE_JUMP_FORWARD_0, MAX_CODE_JUMP) <= -1) return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static MOO_INLINE int inject_continue_to_loop (moo_t* moo)
|
||||||
|
{
|
||||||
|
if (add_to_oow_pool (moo, &moo->c->mth.loop->continue_ip_pool, moo->c->mth.code.len) <= -1 ||
|
||||||
|
emit_single_param_instruction (moo, BCODE_JUMP_FORWARD_0, MAX_CODE_JUMP) <= -1) return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void eliminate_instructions (moo_t* moo, moo_oow_t start, moo_oow_t end)
|
static void eliminate_instructions (moo_t* moo, moo_oow_t start, moo_oow_t end)
|
||||||
{
|
{
|
||||||
moo_oow_t last;
|
moo_oow_t last;
|
||||||
|
|
||||||
MOO_ASSERT (moo, moo->c->mth.code.len >= 1);
|
MOO_ASSERT (moo, moo->c->mth.code.len >= 1);
|
||||||
|
|
||||||
MOO_DEBUG2 (moo, "ELIMINATE INSTRUCTION FROM %zu TO %zu\n", start, end);
|
|
||||||
last = moo->c->mth.code.len - 1;
|
last = moo->c->mth.code.len - 1;
|
||||||
|
|
||||||
|
|
||||||
if (end >= last)
|
if (end >= last)
|
||||||
{
|
{
|
||||||
/* eliminate all instructions starting from the start index.
|
/* eliminate all instructions starting from the start index.
|
||||||
* setting the length to the start length will achieve this */
|
* setting the length to the start length will achieve this */
|
||||||
|
adjust_all_loop_jumps_for_elimination (moo, start, last);
|
||||||
moo->c->mth.code.len = start;
|
moo->c->mth.code.len = start;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* eliminate a chunk in the middle of the instruction buffer.
|
/* eliminate a chunk in the middle of the instruction buffer.
|
||||||
* some copying is required */
|
* some copying is required */
|
||||||
if (end > last) end = last;
|
adjust_all_loop_jumps_for_elimination (moo, start, end);
|
||||||
MOO_MEMMOVE (&moo->c->mth.code.ptr[start], &moo->c->mth.code.ptr[end + 1], moo->c->mth.code.len - end - 1);
|
MOO_MEMMOVE (&moo->c->mth.code.ptr[start], &moo->c->mth.code.ptr[end + 1], moo->c->mth.code.len - end - 1);
|
||||||
moo->c->mth.code.len--;
|
moo->c->mth.code.len -= end - start + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2252,7 +2378,6 @@ MOO_DEBUG2 (moo, "ELIMINATE INSTRUCTION FROM %zu TO %zu\n", start, end);
|
|||||||
* Compiler
|
* Compiler
|
||||||
* --------------------------------------------------------------------- */
|
* --------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
static int add_literal (moo_t* moo, moo_oop_t lit, moo_oow_t* index)
|
static int add_literal (moo_t* moo, moo_oop_t lit, moo_oow_t* index)
|
||||||
{
|
{
|
||||||
moo_oow_t i;
|
moo_oow_t i;
|
||||||
@ -3480,89 +3605,6 @@ static int store_tmpr_count_for_block (moo_t* moo, moo_oow_t tmpr_count)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int push_loop (moo_t* moo, moo_loop_type_t type, moo_oow_t startpos)
|
|
||||||
{
|
|
||||||
moo_loop_t* loop;
|
|
||||||
|
|
||||||
loop = moo_callocmem (moo, MOO_SIZEOF(*loop));
|
|
||||||
if (!loop) return -1;
|
|
||||||
|
|
||||||
init_oow_pool (moo, &loop->break_ip_pool);
|
|
||||||
init_oow_pool (moo, &loop->continue_ip_pool);
|
|
||||||
loop->type = type;
|
|
||||||
loop->startpos = startpos;
|
|
||||||
loop->next = moo->c->mth.loop;
|
|
||||||
moo->c->mth.loop = loop;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int update_loop_jumps (moo_t* moo, moo_oow_pool_t* pool, moo_oow_t jt)
|
|
||||||
{
|
|
||||||
/* patch the jump instructions emitted for 'break' */
|
|
||||||
moo_oow_pool_chunk_t* chunk;
|
|
||||||
moo_oow_t i, j;
|
|
||||||
|
|
||||||
for (chunk = pool->head, i = 0; chunk; chunk = chunk->next)
|
|
||||||
{
|
|
||||||
for (j = 0; j < MOO_COUNTOF(pool->static_chunk.buf) && i < pool->count; j++)
|
|
||||||
{
|
|
||||||
if (patch_long_forward_jump_instruction (moo, chunk->buf[j], jt, BCODE_JUMP2_FORWARD, MOO_NULL) <= -1) return -1;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static MOO_INLINE int update_loop_breaks (moo_t* moo, moo_oow_t jt)
|
|
||||||
{
|
|
||||||
return update_loop_jumps (moo, &moo->c->mth.loop->break_ip_pool, jt);
|
|
||||||
}
|
|
||||||
|
|
||||||
static MOO_INLINE int update_loop_continues (moo_t* moo, moo_oow_t jt)
|
|
||||||
{
|
|
||||||
return update_loop_jumps (moo, &moo->c->mth.loop->continue_ip_pool, jt);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static MOO_INLINE moo_loop_t* unlink_loop (moo_t* moo)
|
|
||||||
{
|
|
||||||
moo_loop_t* loop;
|
|
||||||
|
|
||||||
MOO_ASSERT (moo, moo->c->mth.loop != MOO_NULL);
|
|
||||||
loop = moo->c->mth.loop;
|
|
||||||
moo->c->mth.loop = loop->next;
|
|
||||||
|
|
||||||
return loop;
|
|
||||||
}
|
|
||||||
|
|
||||||
static MOO_INLINE void free_loop (moo_t* moo, moo_loop_t* loop)
|
|
||||||
{
|
|
||||||
fini_oow_pool (moo, &loop->continue_ip_pool);
|
|
||||||
fini_oow_pool (moo, &loop->break_ip_pool);
|
|
||||||
moo_freemem (moo, loop);
|
|
||||||
}
|
|
||||||
|
|
||||||
static MOO_INLINE void pop_loop (moo_t* moo)
|
|
||||||
{
|
|
||||||
free_loop (moo, unlink_loop (moo));
|
|
||||||
}
|
|
||||||
|
|
||||||
static MOO_INLINE int inject_break_to_loop (moo_t* moo)
|
|
||||||
{
|
|
||||||
if (add_to_oow_pool (moo, &moo->c->mth.loop->break_ip_pool, moo->c->mth.code.len) <= -1 ||
|
|
||||||
emit_single_param_instruction (moo, BCODE_JUMP_FORWARD_0, MAX_CODE_JUMP) <= -1) return -1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static MOO_INLINE int inject_continue_to_loop (moo_t* moo)
|
|
||||||
{
|
|
||||||
if (add_to_oow_pool (moo, &moo->c->mth.loop->continue_ip_pool, moo->c->mth.code.len) <= -1 ||
|
|
||||||
emit_single_param_instruction (moo, BCODE_JUMP_FORWARD_0, MAX_CODE_JUMP) <= -1) return -1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int compile_block_expression (moo_t* moo)
|
static int compile_block_expression (moo_t* moo)
|
||||||
{
|
{
|
||||||
moo_oow_t jump_inst_pos;
|
moo_oow_t jump_inst_pos;
|
||||||
|
Loading…
Reference in New Issue
Block a user