Skip to content

Commit e1c55fd

Browse files
authored
Merge pull request #1675 from Shaikh-Ubaid/wasm_assembler
WASM: Implement WASMAssembler Class
2 parents 7e55c07 + 0b95d97 commit e1c55fd

8 files changed

+978
-1024
lines changed

src/libasr/codegen/asr_to_wasm.cpp

Lines changed: 600 additions & 828 deletions
Large diffs are not rendered by default.

src/libasr/codegen/wasm_assembler.h

Lines changed: 307 additions & 167 deletions
Large diffs are not rendered by default.

src/libasr/codegen/wasm_decoder.h

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44
#include <fstream>
55

66
#include <libasr/assert.h>
7-
#include <libasr/alloc.h>
8-
#include <libasr/containers.h>
97
#include <libasr/codegen/wasm_utils.h>
108

119
// #define WAT_DEBUG
@@ -48,9 +46,6 @@ class WASMDecoder {
4846
Struct &self() { return static_cast<Struct &>(*this); }
4947

5048
public:
51-
std::unordered_map<uint8_t, std::string> var_type_to_string;
52-
std::unordered_map<uint8_t, std::string> kind_to_string;
53-
5449
Allocator &al;
5550
diag::Diagnostics &diag;
5651
Vec<uint8_t> wasm_bytes;
@@ -67,10 +62,6 @@ class WASMDecoder {
6762

6863
WASMDecoder(Allocator &al, diag::Diagnostics &diagonostics)
6964
: al(al), diag(diagonostics) {
70-
var_type_to_string = {
71-
{0x7F, "i32"}, {0x7E, "i64"}, {0x7D, "f32"}, {0x7C, "f64"}};
72-
kind_to_string = {
73-
{0x00, "func"}, {0x01, "table"}, {0x02, "memory"}, {0x03, "global"}};
7465

7566
PREAMBLE_SIZE = 8 /* BYTES */;
7667
// wasm_bytes.reserve(al, 1024 * 128);

src/libasr/codegen/wasm_to_wat.cpp

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -313,13 +313,12 @@ class WATVisitor : public WASMDecoder<WATVisitor>,
313313
result +=
314314
indent + "(type (;" + std::to_string(i) + ";) (func (param";
315315
for (uint32_t j = 0; j < func_types[i].param_types.size(); j++) {
316-
result +=
317-
" " + var_type_to_string[func_types[i].param_types.p[j]];
316+
result += " " + vt2s(func_types[i].param_types.p[j]);
318317
}
319318
result += ") (result";
320319
for (uint32_t j = 0; j < func_types[i].result_types.size(); j++) {
321320
result +=
322-
" " + var_type_to_string[func_types[i].result_types.p[j]];
321+
" " + vt2s(func_types[i].result_types.p[j]);
323322
}
324323
result += ")))";
325324
}
@@ -350,8 +349,8 @@ class WATVisitor : public WASMDecoder<WATVisitor>,
350349
decode_instructions();
351350
global_initialization_insts = this->src;
352351
}
353-
std::string global_type = ((globals[i].mut == 0x00) ? var_type_to_string[globals[i].type]:
354-
"(mut " + var_type_to_string[globals[i].type] + ")" );
352+
std::string global_type = ((globals[i].mut == 0x00) ? vt2s(globals[i].type):
353+
"(mut " + vt2s(globals[i].type) + ")" );
355354
result += indent + "(global $" + std::to_string(i);
356355
result += " " + global_type;
357356
result += " (" + global_initialization_insts + "))";
@@ -365,20 +364,20 @@ class WATVisitor : public WASMDecoder<WATVisitor>,
365364
j++) {
366365
result +=
367366
" " +
368-
var_type_to_string[func_types[func_index].param_types.p[j]];
367+
vt2s(func_types[func_index].param_types.p[j]);
369368
}
370369
result += ") (result";
371370
for (uint32_t j = 0; j < func_types[func_index].result_types.size();
372371
j++) {
373-
result += " " + var_type_to_string[func_types[func_index]
374-
.result_types.p[j]];
372+
result += " " + vt2s(func_types[func_index]
373+
.result_types.p[j]);
375374
}
376375
result += ")";
377376
result += indent + " (local";
378377
for (uint32_t j = 0; j < codes.p[i].locals.size(); j++) {
379378
for (uint32_t k = 0; k < codes.p[i].locals.p[j].count; k++) {
380379
result +=
381-
" " + var_type_to_string[codes.p[i].locals.p[j].type];
380+
" " + vt2s(codes.p[i].locals.p[j].type);
382381
}
383382
}
384383
result += ")";
@@ -403,7 +402,7 @@ class WATVisitor : public WASMDecoder<WATVisitor>,
403402

404403
for (uint32_t i = 0; i < exports.size(); i++) {
405404
result += indent + "(export \"" + exports.p[i].name + "\" (" +
406-
kind_to_string[exports.p[i].kind] + " " +
405+
k2s(exports.p[i].kind) + " " +
407406
std::to_string(exports.p[i].index) + "))";
408407
}
409408

src/libasr/codegen/wasm_to_x64.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ class X64Visitor : public WASMDecoder<X64Visitor>,
212212

213213
void visit_GlobalGet(uint32_t globalidx) {
214214
std::string loc = "global_" + std::to_string(globalidx);
215-
std::string var_type = var_type_to_string[globals[globalidx].type];
215+
std::string var_type = vt2s(globals[globalidx].type);
216216

217217
X64Reg base = X64Reg::rbx;
218218
m_a.asm_mov_r64_label(X64Reg::rbx, loc);
@@ -235,7 +235,7 @@ class X64Visitor : public WASMDecoder<X64Visitor>,
235235
}
236236

237237
std::string loc = "global_" + std::to_string(globalidx);
238-
std::string var_type = var_type_to_string[globals[globalidx].type];
238+
std::string var_type = vt2s(globals[globalidx].type);
239239

240240
X64Reg base = X64Reg::rbx;
241241
m_a.asm_mov_r64_label(X64Reg::rbx, loc);
@@ -257,7 +257,7 @@ class X64Visitor : public WASMDecoder<X64Visitor>,
257257
auto cur_func_param_type = func_types[type_indices[cur_func_idx]];
258258
int no_of_params = (int)cur_func_param_type.param_types.size();
259259
if ((int)localidx < no_of_params) {
260-
std::string var_type = var_type_to_string[cur_func_param_type.param_types[localidx]];
260+
std::string var_type = vt2s(cur_func_param_type.param_types[localidx]);
261261
if (var_type == "i32" || var_type == "i64") {
262262
m_a.asm_mov_r64_m64(X64Reg::rax, &base, nullptr, 1, 8 * (2 + no_of_params - (int)localidx - 1));
263263
m_a.asm_push_r64(X64Reg::rax);
@@ -271,7 +271,7 @@ class X64Visitor : public WASMDecoder<X64Visitor>,
271271
}
272272
} else {
273273
localidx -= no_of_params;
274-
std::string var_type = var_type_to_string[codes[cur_func_idx].locals[localidx].type];
274+
std::string var_type = vt2s(codes[cur_func_idx].locals[localidx].type);
275275
if (var_type == "i32" || var_type == "i64") {
276276
m_a.asm_mov_r64_m64(X64Reg::rax, &base, nullptr, 1, -8 * (1 + (int)localidx));
277277
m_a.asm_push_r64(X64Reg::rax);
@@ -291,7 +291,7 @@ class X64Visitor : public WASMDecoder<X64Visitor>,
291291
auto cur_func_param_type = func_types[type_indices[cur_func_idx]];
292292
int no_of_params = (int)cur_func_param_type.param_types.size();
293293
if ((int)localidx < no_of_params) {
294-
std::string var_type = var_type_to_string[cur_func_param_type.param_types[localidx]];
294+
std::string var_type = vt2s(cur_func_param_type.param_types[localidx]);
295295
if (var_type == "i32" || var_type == "i64") {
296296
m_a.asm_pop_r64(X64Reg::rax);
297297
m_a.asm_mov_m64_r64(&base, nullptr, 1, 8 * (2 + no_of_params - (int)localidx - 1), X64Reg::rax);
@@ -305,7 +305,7 @@ class X64Visitor : public WASMDecoder<X64Visitor>,
305305
}
306306
} else {
307307
localidx -= no_of_params;
308-
std::string var_type = var_type_to_string[codes[cur_func_idx].locals[localidx].type];
308+
std::string var_type = vt2s(codes[cur_func_idx].locals[localidx].type);
309309
if (var_type == "i32" || var_type == "i64") {
310310
m_a.asm_pop_r64(X64Reg::rax);
311311
m_a.asm_mov_m64_r64(&base, nullptr, 1, -8 * (1 + (int)localidx), X64Reg::rax);

src/libasr/codegen/wasm_to_x86.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ class X86Visitor : public WASMDecoder<X86Visitor>,
209209
auto cur_func_param_type = func_types[type_indices[cur_func_idx]];
210210
int no_of_params = (int)cur_func_param_type.param_types.size();
211211
if ((int)localidx < no_of_params) {
212-
std::string var_type = var_type_to_string[cur_func_param_type.param_types[localidx]];
212+
std::string var_type = vt2s(cur_func_param_type.param_types[localidx]);
213213
if (var_type == "i32") {
214214
m_a.asm_mov_r32_m32(X86Reg::eax, &base, nullptr, 1, 4 * (2 + no_of_params - (int)localidx - 1));
215215
m_a.asm_push_r32(X86Reg::eax);
@@ -227,7 +227,7 @@ class X86Visitor : public WASMDecoder<X86Visitor>,
227227

228228
} else {
229229
localidx -= no_of_params;
230-
std::string var_type = var_type_to_string[codes[cur_func_idx].locals[localidx].type];
230+
std::string var_type = vt2s(codes[cur_func_idx].locals[localidx].type);
231231
if (var_type == "i32") {
232232
m_a.asm_mov_r32_m32(X86Reg::eax, &base, nullptr, 1, -4 * (1 + localidx));
233233
m_a.asm_push_r32(X86Reg::eax);
@@ -249,7 +249,7 @@ class X86Visitor : public WASMDecoder<X86Visitor>,
249249
auto cur_func_param_type = func_types[type_indices[cur_func_idx]];
250250
int no_of_params = (int)cur_func_param_type.param_types.size();
251251
if ((int)localidx < no_of_params) {
252-
std::string var_type = var_type_to_string[cur_func_param_type.param_types[localidx]];
252+
std::string var_type = vt2s(cur_func_param_type.param_types[localidx]);
253253
if (var_type == "i32") {
254254
m_a.asm_pop_r32(X86Reg::eax);
255255
m_a.asm_mov_m32_r32(&base, nullptr, 1, 4 * (2 + no_of_params - (int)localidx - 1), X86Reg::eax);
@@ -267,7 +267,7 @@ class X86Visitor : public WASMDecoder<X86Visitor>,
267267

268268
} else {
269269
localidx -= no_of_params;
270-
std::string var_type = var_type_to_string[codes[cur_func_idx].locals[localidx].type];
270+
std::string var_type = vt2s(codes[cur_func_idx].locals[localidx].type);
271271
if (var_type == "i32") {
272272
m_a.asm_pop_r32(X86Reg::eax);
273273
m_a.asm_mov_m32_r32(&base, nullptr, 1, -4 * (1 + (int)localidx), X86Reg::eax);

src/libasr/codegen/wasm_utils.h

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,56 @@ namespace LCompilers {
1111

1212
namespace wasm {
1313

14+
enum var_type: uint8_t {
15+
i32 = 0x7F,
16+
i64 = 0x7E,
17+
f32 = 0x7D,
18+
f64 = 0x7C
19+
};
20+
21+
enum mem_align : uint8_t {
22+
b8 = 0,
23+
b16 = 1,
24+
b32 = 2,
25+
b64 = 3
26+
};
27+
28+
enum wasm_kind: uint8_t {
29+
func = 0x00,
30+
table = 0x01,
31+
memory = 0x02,
32+
global = 0x03
33+
};
34+
35+
template <typename T>
36+
std::string vt2s(T vt) {
37+
switch(vt) {
38+
case var_type::i32: return "i32";
39+
case var_type::i64: return "i64";
40+
case var_type::f32: return "f32";
41+
case var_type::f64: return "f64";
42+
default:
43+
std::cerr << "Unsupported wasm var_type" << std::endl;
44+
LCOMPILERS_ASSERT(false);
45+
return "";
46+
47+
}
48+
}
49+
50+
template <typename T>
51+
std::string k2s(T k) {
52+
switch(k) {
53+
case wasm_kind::func: return "func";
54+
case wasm_kind::table: return "table";
55+
case wasm_kind::memory: return "memory";
56+
case wasm_kind::global: return "global";
57+
default:
58+
std::cerr << "Unsupported wasm kind" << std::endl;
59+
LCOMPILERS_ASSERT(false);
60+
return "";
61+
}
62+
}
63+
1464
struct FuncType {
1565
Vec<uint8_t> param_types;
1666
Vec<uint8_t> result_types;

src/libasr/wasm_instructions_visitor.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,10 +105,12 @@ def visit_BaseWASMVisitor(self, mod, *args):
105105
self.emit("};\n", 0)
106106

107107
def visit_WASMInstsAssembler(self, mod):
108+
self.emit("template <class Struct>", 0)
108109
self.emit("class WASMInstsAssembler {", 0)
109110
self.emit("private:", 0)
110111
self.emit( "Allocator &m_al;", 1)
111112
self.emit( "Vec<uint8_t> &m_code;\n", 1)
113+
self.emit( "Struct &self() { return static_cast<Struct &>(*this); }", 1)
112114
self.emit("public:", 0)
113115
self.emit( "WASMInstsAssembler(Allocator &al, Vec<uint8_t> &code): m_al(al), m_code(code) {}\n", 1)
114116

0 commit comments

Comments
 (0)