nit fixes

This commit is contained in:
Awal Garg 2018-01-03 15:19:43 +05:30 committed by Fabian
parent 74e6500bf1
commit 85a67caaa7
7 changed files with 374 additions and 398 deletions

View file

@ -175,7 +175,7 @@ build/v86-debug.wasm: src/native/*.c src/native/*.h src/native/codegen/*.c src/n
build/codegen-test.wasm: src/native/*.c src/native/*.h src/native/codegen/*.c src/native/codegen/*.h
mkdir -p build
emcc src/native/codegen/api.c src/native/codegen/codegen.c \
emcc src/native/codegen/codegen.c \
-Isrc/native/ \
-Wall -Wpedantic -Wextra \
-Wno-bitwise-op-parentheses -Wno-gnu-binary-literal \

View file

@ -1,339 +0,0 @@
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>
#include "const.h"
#include "wasm_opcodes.h"
#include "util.h"
#include "codegen.h"
#include "wasm_util.h"
// location in memory where we store the result of the computation for testing
#define RESULT_LOC 1600
extern bool is_asize_32(void);
extern int32_t read_imm8();
extern int32_t read_imm8s();
extern int32_t read_imm16();
extern int32_t read_imm32s();
extern int32_t get_fn_index(char* fn, uint8_t fn_len, uint8_t type_index);
extern int32_t* const instruction_pointer;
extern int32_t* const previous_ip;
extern uint8_t* const reg8;
extern uint16_t* const reg16;
extern int8_t* const reg8s;
extern int16_t* const reg16s;
extern int32_t* const reg32s;
extern Writer cs;
static void jit_resolve_modrm32_(int32_t);
static void jit_resolve_modrm16_(int32_t);
void gen_increment_instruction_pointer(int32_t n)
{
push_i32(&cs, (int32_t)instruction_pointer); // store address of ip
load_i32(&cs, (int32_t)instruction_pointer); // load ip
push_i32(&cs, n); // load value to add to it
add_i32(&cs);
store_i32(&cs); // store it back in
}
void gen_set_previous_eip()
{
push_i32(&cs, (int32_t)previous_ip); // store address of previous ip
load_i32(&cs, (int32_t)instruction_pointer); // load ip
store_i32(&cs); // store it as previous ip
}
void gen_fn0(char* fn, uint8_t fn_len)
{
int32_t fn_idx = get_fn_index(fn, fn_len, FN0_TYPE_INDEX);
call_fn(&cs, fn_idx);
}
void gen_fn1(char* fn, uint8_t fn_len, int32_t arg0)
{
int32_t fn_idx = get_fn_index(fn, fn_len, FN1_TYPE_INDEX);
push_i32(&cs, arg0);
call_fn(&cs, fn_idx);
}
void gen_fn2(char* fn, uint8_t fn_len, int32_t arg0, int32_t arg1)
{
int32_t fn_idx = get_fn_index(fn, fn_len, FN2_TYPE_INDEX);
push_i32(&cs, arg0);
push_i32(&cs, arg1);
call_fn(&cs, fn_idx);
}
void gen_drop()
{
write_raw_u8(&cs, OP_DROP);
}
#define MODRM_ENTRY(n, work)\
case (n) | 0 << 3:\
case (n) | 1 << 3:\
case (n) | 2 << 3:\
case (n) | 3 << 3:\
case (n) | 4 << 3:\
case (n) | 5 << 3:\
case (n) | 6 << 3:\
case (n) | 7 << 3:\
work; break;
#define MODRM_ENTRY16_0(row, seg, reg1, reg2)\
MODRM_ENTRY(0x00 | row, gen_modrm_entry_0(seg, reg1, reg2, 0))\
MODRM_ENTRY(0x40 | row, gen_modrm_entry_0(seg, reg1, reg2, read_imm8s()))\
MODRM_ENTRY(0x80 | row, gen_modrm_entry_0(seg, reg1, reg2, read_imm16()))
#define MODRM_ENTRY16_1(row, seg, reg)\
MODRM_ENTRY(0x00 | row, gen_modrm_entry_1(seg, reg, 0))\
MODRM_ENTRY(0x40 | row, gen_modrm_entry_1(seg, reg, read_imm8s()))\
MODRM_ENTRY(0x80 | row, gen_modrm_entry_1(seg, reg, read_imm16()))
static void inline gen_modrm_entry_0(int32_t fn_idx, int32_t reg16_idx_1, int32_t reg16_idx_2, int32_t imm)
{
// generates: fn( ( reg1 + reg2 + imm ) & 0xFFFF )
load_u16(&cs, reg16_idx_1);
load_u16(&cs, reg16_idx_2);
add_i32(&cs);
push_i32(&cs, imm);
add_i32(&cs);
push_i32(&cs, 0xFFFF);
and_i32(&cs);
call_fn(&cs, fn_idx);
}
static void gen_modrm_entry_1(int32_t fn_idx, int32_t reg16_idx, int32_t imm)
{
// generates: fn ( ( reg + imm ) & 0xFFFF )
load_u16(&cs, reg16_idx);
push_i32(&cs, imm);
add_i32(&cs);
push_i32(&cs, 0xFFFF);
and_i32(&cs);
call_fn(&cs, fn_idx);
}
static void jit_resolve_modrm16_(int32_t modrm_byte)
{
int32_t const ds = fn_get_seg_prefix_ds_idx;
int32_t const ss = fn_get_seg_prefix_ss_idx;
switch(modrm_byte)
{
// The following casts cause some weird issue with emscripten and cause
// a performance hit. XXX: look into this later.
MODRM_ENTRY16_0(0, ds, (int32_t)(reg16 + BX), (int32_t)(reg16 + SI))
MODRM_ENTRY16_0(1, ds, (int32_t)(reg16 + BX), (int32_t)(reg16 + DI))
MODRM_ENTRY16_0(2, ss, (int32_t)(reg16 + BP), (int32_t)(reg16 + SI))
MODRM_ENTRY16_0(3, ss, (int32_t)(reg16 + BP), (int32_t)(reg16 + DI))
MODRM_ENTRY16_1(4, ds, (int32_t)(reg16 + SI))
MODRM_ENTRY16_1(5, ds, (int32_t)(reg16 + DI))
// special case
MODRM_ENTRY(0x00 | 6, call_fn_with_arg(&cs, ds, read_imm16()))
MODRM_ENTRY(0x40 | 6, gen_modrm_entry_1(ss, (int32_t)(reg16 + BP), read_imm8s()))
MODRM_ENTRY(0x80 | 6, gen_modrm_entry_1(ss, (int32_t)(reg16 + BP), read_imm16()))
MODRM_ENTRY16_1(7, ds, (int32_t)(reg16 + BX))
default:
assert(false);
}
}
void gen_resolve_modrm16(int32_t modrm_byte)
{
push_u32(&cs, RESULT_LOC);
jit_resolve_modrm16_(modrm_byte);
store_i32(&cs);
}
#define MODRM_ENTRY32_0(row, seg, reg)\
MODRM_ENTRY(0x00 | row, gen_modrm32_entry(seg, reg, 0))\
MODRM_ENTRY(0x40 | row, gen_modrm32_entry(seg, reg, read_imm8s()))\
MODRM_ENTRY(0x80 | row, gen_modrm32_entry(seg, reg, read_imm32s()))
static void gen_modrm32_entry(int32_t fn_idx, int32_t reg32s_idx, int32_t imm)
{
// generates: fn ( reg + imm )
load_i32(&cs, reg32s_idx);
push_i32(&cs, imm);
add_i32(&cs);
call_fn(&cs, fn_idx);
}
static void jit_resolve_sib(bool mod)
{
uint8_t sib_byte = read_imm8();
uint8_t r = sib_byte & 7;
uint8_t m = sib_byte >> 3 & 7;
int32_t base_addr;
int32_t base;
uint8_t seg;
bool base_is_mem_access = true;
if(r == 4)
{
base_addr = (int32_t)(reg32s + ESP);
seg = SS;
}
else if(r == 5)
{
if(mod)
{
base_addr = (int32_t)(reg32s + EBP);
seg = SS;
}
else
{
base = read_imm32s();
seg = DS;
base_is_mem_access = false;
}
}
else
{
base_addr = (int32_t)(reg32s + r);
seg = DS;
}
// generate: get_seg_prefix(seg) + base
// Where base is accessed from memory if base_is_mem_access or written as a constant otherwise
dbg_assert(seg < 16);
write_raw_u8(&cs, OP_I32CONST);
write_raw_u8(&cs, seg);
call_fn(&cs, fn_get_seg_prefix_idx);
if(base_is_mem_access)
{
load_i32(&cs, base_addr);
}
else
{
push_i32(&cs, base);
}
add_i32(&cs);
// We now have to generate an offset value to add
if(m == 4)
{
// offset is 0, we don't need to add anything
return;
}
// Offset is reg32s[m] << s, where s is:
uint8_t s = sib_byte >> 6 & 3;
load_i32(&cs, (int32_t)(reg32s + m));
// We don't use push_u32 here either since s will fit in 1 byte
write_raw_u8(&cs, OP_I32CONST);
write_raw_u8(&cs, s);
shl_i32(&cs);
add_i32(&cs);
}
static void modrm32_special_case_1()
{
jit_resolve_sib(true);
push_i32(&cs, read_imm8s());
add_i32(&cs);
}
static void modrm32_special_case_2()
{
jit_resolve_sib(true);
push_i32(&cs, read_imm32s());
add_i32(&cs);
}
static void jit_resolve_modrm32_(int32_t modrm_byte)
{
int32_t const ds = fn_get_seg_prefix_ds_idx;
int32_t const ss = fn_get_seg_prefix_ss_idx;
switch(modrm_byte)
{
MODRM_ENTRY32_0(0, ds, (int32_t)(reg32s + EAX))
MODRM_ENTRY32_0(1, ds, (int32_t)(reg32s + ECX))
MODRM_ENTRY32_0(2, ds, (int32_t)(reg32s + EDX))
MODRM_ENTRY32_0(3, ds, (int32_t)(reg32s + EBX))
// special cases
MODRM_ENTRY(0x00 | 4, jit_resolve_sib(false))
MODRM_ENTRY(0x40 | 4, modrm32_special_case_1())
MODRM_ENTRY(0x80 | 4, modrm32_special_case_2())
MODRM_ENTRY(0x00 | 5, call_fn_with_arg(&cs, ds, read_imm32s()))
MODRM_ENTRY(0x40 | 5, gen_modrm32_entry(ss, (int32_t)(reg32s + EBP), read_imm8s()))
MODRM_ENTRY(0x80 | 5, gen_modrm32_entry(ss, (int32_t)(reg32s + EBP), read_imm32s()))
MODRM_ENTRY32_0(6, ds, (int32_t)(reg32s + ESI))
MODRM_ENTRY32_0(7, ds, (int32_t)(reg32s + EDI))
default:
assert(false);
}
}
void gen_resolve_modrm32(int32_t modrm_byte)
{
push_i32(&cs, RESULT_LOC);
jit_resolve_modrm32_(modrm_byte);
store_i32(&cs);
}
#undef MODRM_ENTRY
void gen_modrm_fn1(char* fn, uint8_t fn_len, int32_t modrm_byte, int32_t arg0)
{
// generates: fn( modrm_resolve( modrm_byte ), arg0 )
if(is_asize_32())
{
jit_resolve_modrm32_(modrm_byte);
}
else
{
jit_resolve_modrm16_(modrm_byte);
}
push_i32(&cs, arg0);
int32_t fn_idx = get_fn_index(fn, fn_len, FN2_RET_TYPE_INDEX);
call_fn(&cs, fn_idx);
}
void gen_modrm_fn0(char* fn, uint8_t fn_len, int32_t modrm_byte)
{
// generates: fn( modrm_resolve( modrm_byte ) )
if(is_asize_32())
{
jit_resolve_modrm32_(modrm_byte);
}
else
{
jit_resolve_modrm16_(modrm_byte);
}
int32_t fn_idx = get_fn_index(fn, fn_len, FN1_RET_TYPE_INDEX);
call_fn(&cs, fn_idx);
}

View file

@ -7,14 +7,35 @@
#include "wasm_opcodes.h"
#include "codegen.h"
#include "util.h"
#include "wasm_util.h"
#include "module_init.h"
static Writer op = { .start = (uint8_t* const) 2048, .ptr = (uint8_t*) 2048, .len = 1024 };
Writer cs = { .start = (uint8_t* const) 3072, .ptr = (uint8_t*) 3072, .len = 1024 };
static Buffer op = { .start = (uint8_t* const) 2048, .ptr = (uint8_t*) 2048, .len = 1024 };
static Buffer cs = { .start = (uint8_t* const) 3072, .ptr = (uint8_t*) 3072, .len = 1024 };
// location in memory where we store the result of the computation for testing
#define RESULT_LOC 1600
extern bool is_asize_32(void);
extern int32_t read_imm8();
extern int32_t read_imm8s();
extern int32_t read_imm16();
extern int32_t read_imm32s();
extern int32_t get_fn_index(char* fn, uint8_t fn_len, uint8_t type_index);
extern int32_t* const instruction_pointer;
extern int32_t* const previous_ip;
extern uint8_t* const reg8;
extern uint16_t* const reg16;
extern int8_t* const reg8s;
extern int16_t* const reg16s;
extern int32_t* const reg32s;
static uint8_t* op_ptr_reset_location;
static uint32_t import_table_size_reset_value;
static uint32_t initial_import_count;
static void jit_resolve_modrm32_(int32_t);
static void jit_resolve_modrm16_(int32_t);
void gen_init()
{
@ -94,3 +115,309 @@ uintptr_t gen_get_final_offset()
return (uintptr_t) op.ptr;
}
void gen_increment_instruction_pointer(int32_t n)
{
push_i32(&cs, (int32_t)instruction_pointer); // store address of ip
load_i32(&cs, (int32_t)instruction_pointer); // load ip
push_i32(&cs, n); // load value to add to it
add_i32(&cs);
store_i32(&cs); // store it back in
}
void gen_set_previous_eip()
{
push_i32(&cs, (int32_t)previous_ip); // store address of previous ip
load_i32(&cs, (int32_t)instruction_pointer); // load ip
store_i32(&cs); // store it as previous ip
}
void gen_fn0(char* fn, uint8_t fn_len)
{
int32_t fn_idx = get_fn_index(fn, fn_len, FN0_TYPE_INDEX);
call_fn(&cs, fn_idx);
}
void gen_fn1(char* fn, uint8_t fn_len, int32_t arg0)
{
int32_t fn_idx = get_fn_index(fn, fn_len, FN1_TYPE_INDEX);
push_i32(&cs, arg0);
call_fn(&cs, fn_idx);
}
void gen_fn2(char* fn, uint8_t fn_len, int32_t arg0, int32_t arg1)
{
int32_t fn_idx = get_fn_index(fn, fn_len, FN2_TYPE_INDEX);
push_i32(&cs, arg0);
push_i32(&cs, arg1);
call_fn(&cs, fn_idx);
}
void gen_drop()
{
write_raw_u8(&cs, OP_DROP);
}
#define MODRM_ENTRY(n, work)\
case (n) | 0 << 3:\
case (n) | 1 << 3:\
case (n) | 2 << 3:\
case (n) | 3 << 3:\
case (n) | 4 << 3:\
case (n) | 5 << 3:\
case (n) | 6 << 3:\
case (n) | 7 << 3:\
work; break;
#define MODRM_ENTRY16_0(row, seg, reg1, reg2)\
MODRM_ENTRY(0x00 | row, gen_modrm_entry_0(seg, reg1, reg2, 0))\
MODRM_ENTRY(0x40 | row, gen_modrm_entry_0(seg, reg1, reg2, read_imm8s()))\
MODRM_ENTRY(0x80 | row, gen_modrm_entry_0(seg, reg1, reg2, read_imm16()))
#define MODRM_ENTRY16_1(row, seg, reg)\
MODRM_ENTRY(0x00 | row, gen_modrm_entry_1(seg, reg, 0))\
MODRM_ENTRY(0x40 | row, gen_modrm_entry_1(seg, reg, read_imm8s()))\
MODRM_ENTRY(0x80 | row, gen_modrm_entry_1(seg, reg, read_imm16()))
static void inline gen_modrm_entry_0(int32_t fn_idx, int32_t reg16_idx_1, int32_t reg16_idx_2, int32_t imm)
{
// generates: fn( ( reg1 + reg2 + imm ) & 0xFFFF )
load_u16(&cs, reg16_idx_1);
load_u16(&cs, reg16_idx_2);
add_i32(&cs);
push_i32(&cs, imm);
add_i32(&cs);
push_i32(&cs, 0xFFFF);
and_i32(&cs);
call_fn(&cs, fn_idx);
}
static void gen_modrm_entry_1(int32_t fn_idx, int32_t reg16_idx, int32_t imm)
{
// generates: fn ( ( reg + imm ) & 0xFFFF )
load_u16(&cs, reg16_idx);
push_i32(&cs, imm);
add_i32(&cs);
push_i32(&cs, 0xFFFF);
and_i32(&cs);
call_fn(&cs, fn_idx);
}
static void jit_resolve_modrm16_(int32_t modrm_byte)
{
int32_t const ds = fn_get_seg_prefix_ds_idx;
int32_t const ss = fn_get_seg_prefix_ss_idx;
switch(modrm_byte)
{
// The following casts cause some weird issue with emscripten and cause
// a performance hit. XXX: look into this later.
MODRM_ENTRY16_0(0, ds, (int32_t)(reg16 + BX), (int32_t)(reg16 + SI))
MODRM_ENTRY16_0(1, ds, (int32_t)(reg16 + BX), (int32_t)(reg16 + DI))
MODRM_ENTRY16_0(2, ss, (int32_t)(reg16 + BP), (int32_t)(reg16 + SI))
MODRM_ENTRY16_0(3, ss, (int32_t)(reg16 + BP), (int32_t)(reg16 + DI))
MODRM_ENTRY16_1(4, ds, (int32_t)(reg16 + SI))
MODRM_ENTRY16_1(5, ds, (int32_t)(reg16 + DI))
// special case
MODRM_ENTRY(0x00 | 6, call_fn_with_arg(&cs, ds, read_imm16()))
MODRM_ENTRY(0x40 | 6, gen_modrm_entry_1(ss, (int32_t)(reg16 + BP), read_imm8s()))
MODRM_ENTRY(0x80 | 6, gen_modrm_entry_1(ss, (int32_t)(reg16 + BP), read_imm16()))
MODRM_ENTRY16_1(7, ds, (int32_t)(reg16 + BX))
default:
assert(false);
}
}
void gen_resolve_modrm16(int32_t modrm_byte)
{
push_u32(&cs, RESULT_LOC);
jit_resolve_modrm16_(modrm_byte);
store_i32(&cs);
}
#define MODRM_ENTRY32_0(row, seg, reg)\
MODRM_ENTRY(0x00 | row, gen_modrm32_entry(seg, reg, 0))\
MODRM_ENTRY(0x40 | row, gen_modrm32_entry(seg, reg, read_imm8s()))\
MODRM_ENTRY(0x80 | row, gen_modrm32_entry(seg, reg, read_imm32s()))
static void gen_modrm32_entry(int32_t fn_idx, int32_t reg32s_idx, int32_t imm)
{
// generates: fn ( reg + imm )
load_i32(&cs, reg32s_idx);
push_i32(&cs, imm);
add_i32(&cs);
call_fn(&cs, fn_idx);
}
static void jit_resolve_sib(bool mod)
{
uint8_t sib_byte = read_imm8();
uint8_t r = sib_byte & 7;
uint8_t m = sib_byte >> 3 & 7;
int32_t base_addr;
int32_t base;
uint8_t seg;
bool base_is_mem_access = true;
if(r == 4)
{
base_addr = (int32_t)(reg32s + ESP);
seg = SS;
}
else if(r == 5)
{
if(mod)
{
base_addr = (int32_t)(reg32s + EBP);
seg = SS;
}
else
{
base = read_imm32s();
seg = DS;
base_is_mem_access = false;
}
}
else
{
base_addr = (int32_t)(reg32s + r);
seg = DS;
}
// generate: get_seg_prefix(seg) + base
// Where base is accessed from memory if base_is_mem_access or written as a constant otherwise
dbg_assert(seg < 16);
write_raw_u8(&cs, OP_I32CONST);
write_raw_u8(&cs, seg);
call_fn(&cs, fn_get_seg_prefix_idx);
if(base_is_mem_access)
{
load_i32(&cs, base_addr);
}
else
{
push_i32(&cs, base);
}
add_i32(&cs);
// We now have to generate an offset value to add
if(m == 4)
{
// offset is 0, we don't need to add anything
return;
}
// Offset is reg32s[m] << s, where s is:
uint8_t s = sib_byte >> 6 & 3;
load_i32(&cs, (int32_t)(reg32s + m));
// We don't use push_u32 here either since s will fit in 1 byte
write_raw_u8(&cs, OP_I32CONST);
write_raw_u8(&cs, s);
shl_i32(&cs);
add_i32(&cs);
}
static void modrm32_special_case_1()
{
jit_resolve_sib(true);
push_i32(&cs, read_imm8s());
add_i32(&cs);
}
static void modrm32_special_case_2()
{
jit_resolve_sib(true);
push_i32(&cs, read_imm32s());
add_i32(&cs);
}
static void jit_resolve_modrm32_(int32_t modrm_byte)
{
int32_t const ds = fn_get_seg_prefix_ds_idx;
int32_t const ss = fn_get_seg_prefix_ss_idx;
switch(modrm_byte)
{
MODRM_ENTRY32_0(0, ds, (int32_t)(reg32s + EAX))
MODRM_ENTRY32_0(1, ds, (int32_t)(reg32s + ECX))
MODRM_ENTRY32_0(2, ds, (int32_t)(reg32s + EDX))
MODRM_ENTRY32_0(3, ds, (int32_t)(reg32s + EBX))
// special cases
MODRM_ENTRY(0x00 | 4, jit_resolve_sib(false))
MODRM_ENTRY(0x40 | 4, modrm32_special_case_1())
MODRM_ENTRY(0x80 | 4, modrm32_special_case_2())
MODRM_ENTRY(0x00 | 5, call_fn_with_arg(&cs, ds, read_imm32s()))
MODRM_ENTRY(0x40 | 5, gen_modrm32_entry(ss, (int32_t)(reg32s + EBP), read_imm8s()))
MODRM_ENTRY(0x80 | 5, gen_modrm32_entry(ss, (int32_t)(reg32s + EBP), read_imm32s()))
MODRM_ENTRY32_0(6, ds, (int32_t)(reg32s + ESI))
MODRM_ENTRY32_0(7, ds, (int32_t)(reg32s + EDI))
default:
assert(false);
}
}
void gen_resolve_modrm32(int32_t modrm_byte)
{
push_i32(&cs, RESULT_LOC);
jit_resolve_modrm32_(modrm_byte);
store_i32(&cs);
}
#undef MODRM_ENTRY
void gen_modrm_fn1(char* fn, uint8_t fn_len, int32_t modrm_byte, int32_t arg0)
{
// generates: fn( modrm_resolve( modrm_byte ), arg0 )
if(is_asize_32())
{
jit_resolve_modrm32_(modrm_byte);
}
else
{
jit_resolve_modrm16_(modrm_byte);
}
push_i32(&cs, arg0);
int32_t fn_idx = get_fn_index(fn, fn_len, FN2_RET_TYPE_INDEX);
call_fn(&cs, fn_idx);
}
void gen_modrm_fn0(char* fn, uint8_t fn_len, int32_t modrm_byte)
{
// generates: fn( modrm_resolve( modrm_byte ) )
if(is_asize_32())
{
jit_resolve_modrm32_(modrm_byte);
}
else
{
jit_resolve_modrm16_(modrm_byte);
}
int32_t fn_idx = get_fn_index(fn, fn_len, FN1_RET_TYPE_INDEX);
call_fn(&cs, fn_idx);
}

View file

@ -1,7 +1,6 @@
#pragma once
#include <stdint.h>
#include "util.h"
#define FN0_TYPE_INDEX 0
#define FN1_TYPE_INDEX 1

View file

@ -4,8 +4,8 @@
#include "util.h"
static Writer op;
extern Writer cs;
static Buffer op;
static Buffer cs;
static void write_type_section()
{

View file

@ -8,13 +8,13 @@
#define dbg_assert(condition) { if(DEBUG) { if(!(condition)) dbg_log(#condition); assert(condition); } }
#define dbg_assert_message(condition, message) { if(DEBUG && !(condition)) { dbg_log(message); assert(false); } }
typedef struct Writer {
typedef struct Buffer {
uint8_t* const start;
uint8_t* ptr;
uint32_t const len;
} Writer;
} Buffer;
static void write_leb_i32(Writer* writer, int32_t v)
static void write_leb_i32(Buffer* buf, int32_t v)
{
// Super complex stuff. See the following:
// https://en.wikipedia.org/wiki/LEB128#Encode_signed_integer
@ -40,11 +40,11 @@ static void write_leb_i32(Writer* writer, int32_t v)
{
byte |= 0b10000000; // turn on MSB
}
*(writer->ptr)++ = byte;
*(buf->ptr)++ = byte;
}
}
static void write_leb_u32(Writer* writer, uint32_t v)
static void write_leb_u32(Buffer* buf, uint32_t v)
{
do {
uint8_t byte = v & 0b1111111; // get last 7 bits
@ -53,13 +53,13 @@ static void write_leb_u32(Writer* writer, uint32_t v)
{
byte |= 0b10000000; // turn on MSB
}
*(writer->ptr)++ = byte;
*(buf->ptr)++ = byte;
} while (v != 0);
}
static void inline write_raw_u8(Writer* writer, uint8_t v)
static void inline write_raw_u8(Buffer* buf, uint8_t v)
{
*(writer->ptr)++ = v;
*(buf->ptr)++ = v;
}
static void inline write_fixed_leb16_to_ptr(uint8_t* ptr, uint16_t x)
@ -69,14 +69,3 @@ static void inline write_fixed_leb16_to_ptr(uint8_t* ptr, uint16_t x)
*(ptr + 1) = x >> 7;
}
/*123456789012345678901234567890123456789012345678901234567890123456789012345
0 @@@@@@@@ @@@@@@@@@ @@ @ @@@@@@@@@ @@@@@@@ @ @ 0
0 @ @ @ @ @ @ @ @ @ 0
0 @ @ @ @ @ @ @ @ @ 0
0 @@@@@@ @ @ @ @ @ @ @@@@@@@ 0
0 @ @ @ @ @ @ @ @ @ 0
0 @ @ @ @ @ @ @ @ @ 0
0 @ @ @ @ @ @ @ @ @ 0
0 @ @@@@@@@@@ @ @@ @@@@@@@@@ @@@@@@@ @ @ 0
123456789012345678901234567890123456789012345678901234567890123456789012345*/

View file

@ -5,67 +5,67 @@
#include "wasm_opcodes.h"
#include "util.h"
static void inline push_i32(Writer* w, int32_t v)
static void inline push_i32(Buffer* buf, int32_t v)
{
write_raw_u8(w, OP_I32CONST);
write_leb_i32(w, v);
write_raw_u8(buf, OP_I32CONST);
write_leb_i32(buf, v);
}
static void inline push_u32(Writer* w, uint32_t v)
static void inline push_u32(Buffer* buf, uint32_t v)
{
write_raw_u8(w, OP_I32CONST);
write_leb_u32(w, v);
write_raw_u8(buf, OP_I32CONST);
write_leb_u32(buf, v);
}
static void inline load_u16(Writer* w, uint32_t addr)
static void inline load_u16(Buffer* buf, uint32_t addr)
{
write_raw_u8(w, OP_I32CONST);
write_leb_u32(w, addr);
write_raw_u8(w, OP_I32LOAD16U);
write_raw_u8(w, MEM_IMM_ALIGNMENT);
write_raw_u8(w, MEM_IMM_OFFSET);
write_raw_u8(buf, OP_I32CONST);
write_leb_u32(buf, addr);
write_raw_u8(buf, OP_I32LOAD16U);
write_raw_u8(buf, MEM_IMM_ALIGNMENT);
write_raw_u8(buf, MEM_IMM_OFFSET);
}
static void inline load_i32(Writer* w, uint32_t addr)
static void inline load_i32(Buffer* buf, uint32_t addr)
{
write_raw_u8(w, OP_I32CONST);
write_leb_u32(w, addr);
write_raw_u8(w, OP_I32LOAD);
write_raw_u8(w, MEM_IMM_ALIGNMENT);
write_raw_u8(w, MEM_IMM_OFFSET);
write_raw_u8(buf, OP_I32CONST);
write_leb_u32(buf, addr);
write_raw_u8(buf, OP_I32LOAD);
write_raw_u8(buf, MEM_IMM_ALIGNMENT);
write_raw_u8(buf, MEM_IMM_OFFSET);
}
static void inline store_i32(Writer* w)
static void inline store_i32(Buffer* buf)
{
write_raw_u8(w, OP_I32STORE);
write_raw_u8(w, MEM_IMM_ALIGNMENT);
write_raw_u8(w, MEM_IMM_OFFSET);
write_raw_u8(buf, OP_I32STORE);
write_raw_u8(buf, MEM_IMM_ALIGNMENT);
write_raw_u8(buf, MEM_IMM_OFFSET);
}
static void inline add_i32(Writer* w)
static void inline add_i32(Buffer* buf)
{
write_raw_u8(w, OP_I32ADD);
write_raw_u8(buf, OP_I32ADD);
}
static void inline and_i32(Writer* w)
static void inline and_i32(Buffer* buf)
{
write_raw_u8(w, OP_I32AND);
write_raw_u8(buf, OP_I32AND);
}
static void inline shl_i32(Writer* w)
static void inline shl_i32(Buffer* buf)
{
write_raw_u8(w, OP_I32SHL);
write_raw_u8(buf, OP_I32SHL);
}
static void inline call_fn(Writer* w, uint8_t fn_idx)
static void inline call_fn(Buffer* buf, uint8_t fn_idx)
{
write_raw_u8(w, OP_CALL);
write_raw_u8(w, fn_idx);
write_raw_u8(buf, OP_CALL);
write_raw_u8(buf, fn_idx);
}
static void inline call_fn_with_arg(Writer* w, uint8_t fn_idx, int32_t arg0)
static void inline call_fn_with_arg(Buffer* buf, uint8_t fn_idx, int32_t arg0)
{
push_i32(w, arg0);
call_fn(w, fn_idx);
push_i32(buf, arg0);
call_fn(buf, fn_idx);
}