Skip to content

Commit

Permalink
Merge pull request lcompilers#1361 from Shaikh-Ubaid/wasm_x64_local_g…
Browse files Browse the repository at this point in the history
…et_set

WASM_X64: Support local variables
  • Loading branch information
certik committed Dec 15, 2022
2 parents aa90263 + 356b3ca commit d36a853
Show file tree
Hide file tree
Showing 2 changed files with 138 additions and 5 deletions.
74 changes: 74 additions & 0 deletions src/libasr/codegen/wasm_to_x64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,80 @@ class X64Visitor : public WASMDecoder<X64Visitor>,

func_idx -= 7u; // adjust function index as per imports
m_a.asm_call_label(exports[func_idx].name);

// Pop the passed function arguments
wasm::FuncType func_type = func_types[type_indices[func_idx]];
for (uint32_t i = 0; i < func_type.param_types.size(); i++) {
m_a.asm_pop_r64(X64Reg::rax);
}

// Adjust the return values of the called function
X64Reg base = X64Reg::rsp;
for (uint32_t i = 0; i < func_type.result_types.size(); i++) {
// take value into eax
m_a.asm_mov_r64_m64(X64Reg::rax, &base, nullptr, 1,
-8 * (func_type.param_types.size() + 2 +
codes[func_idx].locals.size() + 1));

// push eax value onto stack
m_a.asm_push_r64(X64Reg::rax);
}
}

void visit_LocalGet(uint32_t localidx) {
X64Reg base = X64Reg::rbp;
auto cur_func_param_type = func_types[type_indices[cur_func_idx]];
int no_of_params = (int)cur_func_param_type.param_types.size();
if ((int)localidx < no_of_params) {
std::string var_type = var_type_to_string[cur_func_param_type.param_types[localidx]];
if (var_type == "i32") {
m_a.asm_mov_r64_m64(X64Reg::rax, &base, nullptr, 1, 8 * (2 + localidx));
m_a.asm_push_r64(X64Reg::rax);
} else if (var_type == "f64") {
std::cerr << "Floats are not yet supported" << std::endl;
} else {
throw CodeGenError("WASM_X64: Var type not supported");
}
} else {
localidx -= no_of_params;
std::string var_type = var_type_to_string[codes[cur_func_idx].locals[localidx].type];
if (var_type == "i32") {
m_a.asm_mov_r64_m64(X64Reg::rax, &base, nullptr, 1, -8 * (1 + localidx));
m_a.asm_push_r64(X64Reg::rax);
} else if (var_type == "f64") {
std::cerr << "Floats are not yet supported" << std::endl;
} else {
throw CodeGenError("WASM_X64: Var type not supported");
}
}
}

void visit_LocalSet(uint32_t localidx) {
X64Reg base = X64Reg::rbp;
auto cur_func_param_type = func_types[type_indices[cur_func_idx]];
int no_of_params = (int)cur_func_param_type.param_types.size();
if ((int)localidx < no_of_params) {
std::string var_type = var_type_to_string[cur_func_param_type.param_types[localidx]];
if (var_type == "i32") {
m_a.asm_pop_r64(X64Reg::rax);
m_a.asm_mov_m64_r64(&base, nullptr, 1, 8 * (2 + localidx), X64Reg::rax);
} else if (var_type == "f64") {
std::cerr << "Floats are not yet supported" << std::endl;
} else {
throw CodeGenError("WASM_X64: Var type not supported");
}
} else {
localidx -= no_of_params;
std::string var_type = var_type_to_string[codes[cur_func_idx].locals[localidx].type];
if (var_type == "i32") {
m_a.asm_pop_r64(X64Reg::rax);
m_a.asm_mov_m64_r64(&base, nullptr, 1, -8 * (1 + localidx), X64Reg::rax);
} else if (var_type == "f64") {
std::cerr << "Floats are not yet supported" << std::endl;
} else {
throw CodeGenError("WASM_X64: Var type not supported");
}
}
}

void visit_I32Const(int32_t value) {
Expand Down
69 changes: 64 additions & 5 deletions src/libasr/codegen/x86_assembler.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,26 @@ static std::string r2s(X86Reg r32) {
}
}

static std::string m2s(X64Reg *base, X64Reg *index, uint8_t scale, int64_t disp) {
std::string r;
r = "[";
if (base) r += r2s(*base);
if (index) {
if (base) r += "+";
if (scale == 1) {
r += r2s(*index);
} else {
r += std::to_string(scale) + "*" + r2s(*index);
}
}
if (disp) {
if ((base || index) && (disp > 0)) r += "+";
r += std::to_string(disp);
}
r += "]";
return r;
}

static std::string m2s(X86Reg *base, X86Reg *index, uint8_t scale, int32_t disp) {
std::string r;
r = "[";
Expand Down Expand Up @@ -473,7 +493,7 @@ class X86Assembler {

void asm_pop_r64(X64Reg r64) {
X86Reg r32 = X86Reg(r64 & 7);
m_code.push_back(m_al, rex(1, r64 >> 3, 0, 0));
m_code.push_back(m_al, rex(1, 0, 0, r64 >> 3));
m_code.push_back(m_al, 0x58 + r32);
EMIT("pop " + r2s(r64));
}
Expand All @@ -491,7 +511,7 @@ class X86Assembler {

void asm_push_r64(X64Reg r64) {
X86Reg r32 = X86Reg(r64 & 7);
m_code.push_back(m_al, rex(1, r64 >> 3, 0, 0));
m_code.push_back(m_al, rex(1, 0, 0, r64 >> 3));
m_code.push_back(m_al, 0x50 + r32);
EMIT("push " + r2s(r64));
}
Expand Down Expand Up @@ -664,8 +684,9 @@ class X86Assembler {
}

void asm_mov_r64_imm64(X64Reg r64, uint64_t imm64) {
m_code.push_back(m_al, rex(1, 0, 0, 0));
m_code.push_back(m_al, 0xb8 + r64);
X86Reg r32 = X86Reg(r64 & 7);
m_code.push_back(m_al, rex(1, 0, 0, r64 >> 3));
m_code.push_back(m_al, 0xb8 + r32);
push_back_uint64(m_code, m_al, imm64);
EMIT("mov " + r2s(r64) + ", " + i2s(imm64));
}
Expand All @@ -679,7 +700,7 @@ class X86Assembler {

void asm_mov_r64_r64(X64Reg r64, X64Reg s64) {
X86Reg r32 = X86Reg(r64 & 7), s32 = X86Reg(s64 & 7);
m_code.push_back(m_al, rex(1, r64 >> 3, 0, s64 >> 3));
m_code.push_back(m_al, rex(1, s64 >> 3, 0, r64 >> 3));
m_code.push_back(m_al, 0x89);
modrm_sib_disp(m_code, m_al,
s32, &r32, nullptr, 1, 0, false);
Expand All @@ -693,6 +714,25 @@ class X86Assembler {
EMIT("mov " + r2s(r32) + ", " + r2s(s32));
}

void asm_mov_r64_m64(X64Reg r64, X64Reg *base, X64Reg *index,
uint8_t scale, int64_t disp) {
X86Reg r32 = X86Reg(r64 & 7);
X86Reg* base32 = nullptr, *index32 = nullptr;
if (base) {
base32 = new X86Reg;
*base32 = X86Reg(*base & 7);
}
if (index) {
index32 = new X86Reg;
*index32 = X86Reg(*index & 7);
}
m_code.push_back(m_al, rex(1, r64 >> 3, (index32 ? (*index32 >> 3) : 0), (base32 ? (*base32 >> 3) : 0)));
m_code.push_back(m_al, 0x8b);
modrm_sib_disp(m_code, m_al,
r32, base32, index32, scale, (int32_t)disp, true);
EMIT("mov " + r2s(r64) + ", " + m2s(base, index, scale, disp));
}

void asm_mov_r32_m32(X86Reg r32, X86Reg *base, X86Reg *index,
uint8_t scale, int32_t disp) {
if (r32 == X86Reg::eax && !base && !index) {
Expand All @@ -707,6 +747,25 @@ class X86Assembler {
EMIT("mov " + r2s(r32) + ", " + m2s(base, index, scale, disp));
}

void asm_mov_m64_r64(X64Reg *base, X64Reg *index,
uint8_t scale, int64_t disp, X64Reg r64) {
X86Reg r32 = X86Reg(r64 & 7);
X86Reg* base32 = nullptr, *index32 = nullptr;
if (base) {
base32 = new X86Reg;
*base32 = X86Reg(*base & 7);
}
if (index) {
index32 = new X86Reg;
*index32 = X86Reg(*index & 7);
}
m_code.push_back(m_al, rex(1, r64 >> 3, (index32 ? (*index32 >> 3) : 0), (base32 ? (*base32 >> 3) : 0)));
m_code.push_back(m_al, 0x89);
modrm_sib_disp(m_code, m_al,
r32, base32, index32, scale, (int32_t)disp, true);
EMIT("mov " + m2s(base, index, scale, disp) + ", " + r2s(r64));
}

void asm_mov_m32_r32(X86Reg *base, X86Reg *index,
uint8_t scale, int32_t disp, X86Reg r32) {
if (r32 == X86Reg::eax && !base && !index) {
Expand Down

0 comments on commit d36a853

Please sign in to comment.