In one instruction, if one or multiple operands tending to lock some
hardware registers in IR phase, like EAX, EDX for DIV, ECX for SHIFT,
it leads to two known cases.
case 1: allocate VOID
`SHRU i250,i249,i3`. if pr_3 was allocated to vr_249 first, incoming
allocation of vr_3 leads a spill out of `vr_249` and clear the value
of `vr->hreg` of vr_249. When applying allocation result in FOREACH
in L732, a NULL will be assigned to.
case 2: unexpected spill out
`DIV_U i1,i1,i44`. if allocation of vr_44 needs to spill out one
hardware register, there is a chance that `hr_4` will be selected.
If it happens, codegen will operate EDX and overwrite vr_44 value.
The reason of how `hr_4` will be spilled out is a hidden bug that
both information of `rc->hreg[]` and `rc->vreg` can be transfered
from one block to the next one. It means even there is no vr binds
to a hr in current block, the hr may still be thought as a busy one
becase of the left infroamtion of previous blocks
Workaround for cases:
- Add `MOV LOCKED_hr LOCKED_hr` just after the instruction. It prevents
case 1
- Add `MOV LOCKED_hr LOCKED_hr` just before the instruction. It prevents
case 2
Implement bitwise 64-bit operations in codegen
Fix and refine shift IRs
Zero local variables
Remove ref-type/bulk-memory macros
Implement set aux stack
Refine clear mem registers
Translate WASM_OP_CALL into JIT IR in the frontend, and translate
JIT_OP_CALLBC and JIT_OP_CALLNATIVE in the backend.
For calling wasm native API, simply call wasm_interp_call_func_native
to reduce the complexity.
And fix some issues, including wasm loader, frontend, register allocator,
and code gen.
Implement part of codegen and fix some frontend issues
Add asmjit to emit native code and add zydis to disassemble native code
Can successfully run some simple cases
Since `basic_block_else` is NULL, it meets a crash if there is a
IF block without a else branch. Like:
``` wat
(func (export "params-id") (param i32) (result i32)
(i32.const 1)
(if (param i32) (result i32) (local.get 0)
(then)
)
)
```
Consider the ELSE block will be created lazily, focus on
`basic_block_entry" here.
After `jit_value_stack_destory()`, the `JitValue` pointed
by `value_list_head` and `value_list_end` are freed and
still keep the value.
So, when `jit_value_stack_push()` is called, for example,
`load_block_params()` after `jit_value_stack_destroy()` in
`handle_op_else()`, `value_stack` will not be treated like
an empty one, and new `JitValue` will be appended to `value_list_end`,
which is a dangling pointer(pointer to the freed `JitValue`).
Add more return value checks and set lass error
Implement exception throw and add operand stack overflow check
Remove lower_fe pass
Use cc->cmp_reg for cmp/branch IRs
Fix jit dump issues
Fix some compile warnings
Add part of codegen framework
Remove some unused JIT IRs