Skip to content

Commit 368063b

Browse files
authored
Merge pull request #1257 from Shaikh-Ubaid/wasm_x86_combine_x86visitor_x86generator
WASM_X86: Combine X86Generator and X86Visitor Classes
2 parents ecdb38e + f5a5ba6 commit 368063b

File tree

2 files changed

+126
-156
lines changed

2 files changed

+126
-156
lines changed

src/libasr/codegen/wasm_to_x86.cpp

Lines changed: 126 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,128 @@ namespace LFortran {
1111

1212
namespace wasm {
1313

14-
class X86Generator : public WASMDecoder<X86Generator> {
14+
class X86Visitor : public WASMDecoder<X86Visitor>,
15+
public WASM_INSTS_VISITOR::BaseWASMVisitor<X86Visitor> {
1516
public:
16-
X86Generator(Allocator &al, diag::Diagnostics &diagonostics)
17-
: WASMDecoder(al, diagonostics) {}
17+
X86Assembler &m_a;
18+
uint32_t cur_func_idx;
19+
20+
X86Visitor(X86Assembler &m_a, Allocator &al,
21+
diag::Diagnostics &diagonostics, Vec<uint8_t> &code)
22+
: WASMDecoder(al, diagonostics),
23+
BaseWASMVisitor(code, 0U /* temporary offset */),
24+
m_a(m_a) {
25+
wasm_bytes.from_pointer_n(code.data(), code.size());
26+
}
27+
28+
void visit_Return() {}
29+
30+
void visit_Call(uint32_t func_index) {
31+
if (func_index <= 6U) {
32+
// call to imported functions
33+
if (func_index == 0) {
34+
m_a.asm_call_label("print_i32");
35+
} else if (func_index == 5) {
36+
// currently ignoring flush_buf
37+
} else if (func_index == 6) {
38+
m_a.asm_call_label("exit");
39+
} else {
40+
std::cerr << "Call to imported function with index " +
41+
std::to_string(func_index) +
42+
" not yet supported";
43+
}
44+
return;
45+
}
46+
47+
uint32_t imports_adjusted_func_index = func_index - 7U;
48+
m_a.asm_call_label(exports[imports_adjusted_func_index].name);
49+
50+
// Pop the passed function arguments
51+
wasm::FuncType func_type =
52+
func_types[type_indices[imports_adjusted_func_index]];
53+
for (uint32_t i = 0; i < func_type.param_types.size(); i++) {
54+
m_a.asm_pop_r32(X86Reg::eax);
55+
}
56+
57+
// Adjust the return values of the called function
58+
X86Reg base = X86Reg::esp;
59+
for (uint32_t i = 0; i < func_type.result_types.size(); i++) {
60+
// take value into eax
61+
m_a.asm_mov_r32_m32(
62+
X86Reg::eax, &base, nullptr, 1,
63+
-(4 * (func_type.param_types.size() + 2 +
64+
codes[imports_adjusted_func_index].locals.size() + 1)));
65+
66+
// push eax value onto stack
67+
m_a.asm_push_r32(X86Reg::eax);
68+
}
69+
}
70+
71+
void visit_LocalGet(uint32_t localidx) {
72+
X86Reg base = X86Reg::ebp;
73+
int no_of_params =
74+
(int)func_types[type_indices[cur_func_idx]].param_types.size();
75+
if ((int)localidx < no_of_params) {
76+
m_a.asm_mov_r32_m32(X86Reg::eax, &base, nullptr, 1,
77+
(4 * localidx + 8));
78+
m_a.asm_push_r32(X86Reg::eax);
79+
} else {
80+
m_a.asm_mov_r32_m32(X86Reg::eax, &base, nullptr, 1,
81+
-(4 * ((int)localidx - no_of_params + 1)));
82+
m_a.asm_push_r32(X86Reg::eax);
83+
}
84+
}
85+
void visit_LocalSet(uint32_t localidx) {
86+
X86Reg base = X86Reg::ebp;
87+
int no_of_params =
88+
(int)func_types[type_indices[cur_func_idx]].param_types.size();
89+
if ((int)localidx < no_of_params) {
90+
m_a.asm_pop_r32(X86Reg::eax);
91+
m_a.asm_mov_m32_r32(&base, nullptr, 1, (4 * localidx + 8),
92+
X86Reg::eax);
93+
} else {
94+
m_a.asm_pop_r32(X86Reg::eax);
95+
m_a.asm_mov_m32_r32(&base, nullptr, 1,
96+
-(4 * ((int)localidx - no_of_params + 1)),
97+
X86Reg::eax);
98+
}
99+
}
100+
101+
void visit_I32Const(int32_t value) {
102+
m_a.asm_push_imm32(value);
103+
// if (value < 0) {
104+
// m_a.asm_pop_r32(X86Reg::eax);
105+
// m_a.asm_neg_r32(X86Reg::eax);
106+
// m_a.asm_push_r32(X86Reg::eax);
107+
// }
108+
}
18109

19-
void gen_x86_bytes(X86Assembler &m_a) {
110+
void visit_I32Add() {
111+
m_a.asm_pop_r32(X86Reg::ebx);
112+
m_a.asm_pop_r32(X86Reg::eax);
113+
m_a.asm_add_r32_r32(X86Reg::eax, X86Reg::ebx);
114+
m_a.asm_push_r32(X86Reg::eax);
115+
}
116+
void visit_I32Sub() {
117+
m_a.asm_pop_r32(X86Reg::ebx);
118+
m_a.asm_pop_r32(X86Reg::eax);
119+
m_a.asm_sub_r32_r32(X86Reg::eax, X86Reg::ebx);
120+
m_a.asm_push_r32(X86Reg::eax);
121+
}
122+
void visit_I32Mul() {
123+
m_a.asm_pop_r32(X86Reg::ebx);
124+
m_a.asm_pop_r32(X86Reg::eax);
125+
m_a.asm_mul_r32(X86Reg::ebx);
126+
m_a.asm_push_r32(X86Reg::eax);
127+
}
128+
void visit_I32DivS() {
129+
m_a.asm_pop_r32(X86Reg::ebx);
130+
m_a.asm_pop_r32(X86Reg::eax);
131+
m_a.asm_div_r32(X86Reg::ebx);
132+
m_a.asm_push_r32(X86Reg::eax);
133+
}
134+
135+
void gen_x86_bytes() {
20136
emit_elf32_header(m_a);
21137

22138
// Add runtime library functions
@@ -44,13 +160,9 @@ class X86Generator : public WASMDecoder<X86Generator> {
44160
}
45161
}
46162

47-
WASM_INSTS_VISITOR::X86Visitor v =
48-
WASM_INSTS_VISITOR::X86Visitor(
49-
wasm_bytes, codes.p[i].insts_start_index, m_a,
50-
func_types, imports, type_indices, exports, codes,
51-
data_segments, i);
52-
53-
v.decode_instructions();
163+
offset = codes.p[i].insts_start_index;
164+
cur_func_idx = i;
165+
decode_instructions();
54166

55167
// Restore stack
56168
m_a.asm_mov_r32_r32(X86Reg::esp, X86Reg::ebp);
@@ -75,14 +187,12 @@ Result<int> wasm_to_x86(Vec<uint8_t> &wasm_bytes, Allocator &al,
75187

76188
X86Assembler m_a(al);
77189

78-
wasm::X86Generator x86_generator(al, diagnostics);
79-
x86_generator.wasm_bytes.from_pointer_n(wasm_bytes.data(),
80-
wasm_bytes.size());
190+
wasm::X86Visitor x86_visitor(m_a, al, diagnostics, wasm_bytes);
81191

82192
{
83193
auto t1 = std::chrono::high_resolution_clock::now();
84194
try {
85-
x86_generator.decode_wasm();
195+
x86_visitor.decode_wasm();
86196
} catch (const CodeGenError &e) {
87197
diagnostics.diagnostics.push_back(e.d);
88198
return Error();
@@ -95,7 +205,7 @@ Result<int> wasm_to_x86(Vec<uint8_t> &wasm_bytes, Allocator &al,
95205

96206
{
97207
auto t1 = std::chrono::high_resolution_clock::now();
98-
x86_generator.gen_x86_bytes(m_a);
208+
x86_visitor.gen_x86_bytes();
99209
auto t2 = std::chrono::high_resolution_clock::now();
100210
time_gen_x86_bytes =
101211
std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1)

src/libasr/codegen/wasm_to_x86.h

Lines changed: 0 additions & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -2,149 +2,9 @@
22
#define LFORTRAN_WASM_TO_X86_H
33

44
#include <libasr/wasm_visitor.h>
5-
#include <libasr/codegen/x86_assembler.h>
65

76
namespace LFortran {
87

9-
namespace WASM_INSTS_VISITOR {
10-
11-
class X86Visitor : public BaseWASMVisitor<X86Visitor> {
12-
public:
13-
X86Assembler &m_a;
14-
Vec<wasm::FuncType> func_types;
15-
Vec<wasm::Import> imports;
16-
Vec<uint32_t> type_indices;
17-
Vec<wasm::Export> exports;
18-
Vec<wasm::Code> func_codes;
19-
Vec<wasm::Data> data_segments;
20-
uint32_t cur_func_idx;
21-
22-
X86Visitor(Vec<uint8_t> &code, uint32_t offset, X86Assembler &m_a,
23-
Vec<wasm::FuncType> &func_types, Vec<wasm::Import> &imports,
24-
Vec<uint32_t> &type_indices, Vec<wasm::Export> &exports,
25-
Vec<wasm::Code> &func_codes, Vec<wasm::Data> &data_segments,
26-
uint32_t cur_func_idx)
27-
: BaseWASMVisitor(code, offset), m_a(m_a) {
28-
this->func_types.from_pointer_n(func_types.p, func_types.size());
29-
this->imports.from_pointer_n(imports.p, imports.size());
30-
this->type_indices.from_pointer_n(type_indices.p, type_indices.size());
31-
this->exports.from_pointer_n(exports.p, exports.size());
32-
this->func_codes.from_pointer_n(func_codes.p, func_codes.size());
33-
this->data_segments.from_pointer_n(data_segments.p,
34-
data_segments.size());
35-
this->cur_func_idx = cur_func_idx;
36-
}
37-
38-
void visit_Return() {}
39-
40-
void visit_Call(uint32_t func_index) {
41-
if (func_index <= 6U) {
42-
// call to imported functions
43-
if (func_index == 0) {
44-
m_a.asm_call_label("print_i32");
45-
} else if (func_index == 5) {
46-
// currently ignoring flush_buf
47-
} else if (func_index == 6) {
48-
m_a.asm_call_label("exit");
49-
} else {
50-
std::cerr << "Call to imported function with index " +
51-
std::to_string(func_index) +
52-
" not yet supported";
53-
}
54-
return;
55-
}
56-
57-
uint32_t imports_adjusted_func_index = func_index - 7U;
58-
m_a.asm_call_label(exports[imports_adjusted_func_index].name);
59-
60-
61-
// Pop the passed function arguments
62-
wasm::FuncType func_type = func_types[type_indices[imports_adjusted_func_index]];
63-
for (uint32_t i = 0; i < func_type.param_types.size(); i++) {
64-
m_a.asm_pop_r32(X86Reg::eax);
65-
}
66-
67-
// Adjust the return values of the called function
68-
X86Reg base = X86Reg::esp;
69-
for (uint32_t i = 0; i < func_type.result_types.size(); i++) {
70-
// take value into eax
71-
m_a.asm_mov_r32_m32(
72-
X86Reg::eax, &base, nullptr, 1,
73-
-(4 * (func_type.param_types.size() + 2 +
74-
func_codes[imports_adjusted_func_index].locals.size() + 1)));
75-
76-
// push eax value onto stack
77-
m_a.asm_push_r32(X86Reg::eax);
78-
}
79-
}
80-
81-
void visit_LocalGet(uint32_t localidx) {
82-
X86Reg base = X86Reg::ebp;
83-
int no_of_params =
84-
(int)func_types[type_indices[cur_func_idx]].param_types.size();
85-
if ((int)localidx < no_of_params) {
86-
m_a.asm_mov_r32_m32(X86Reg::eax, &base, nullptr, 1,
87-
(4 * localidx + 8));
88-
m_a.asm_push_r32(X86Reg::eax);
89-
} else {
90-
m_a.asm_mov_r32_m32(X86Reg::eax, &base, nullptr, 1,
91-
-(4 * ((int)localidx - no_of_params + 1)));
92-
m_a.asm_push_r32(X86Reg::eax);
93-
}
94-
}
95-
void visit_LocalSet(uint32_t localidx) {
96-
X86Reg base = X86Reg::ebp;
97-
int no_of_params =
98-
(int)func_types[type_indices[cur_func_idx]].param_types.size();
99-
if ((int)localidx < no_of_params) {
100-
m_a.asm_pop_r32(X86Reg::eax);
101-
m_a.asm_mov_m32_r32(&base, nullptr, 1, (4 * localidx + 8),
102-
X86Reg::eax);
103-
} else {
104-
m_a.asm_pop_r32(X86Reg::eax);
105-
m_a.asm_mov_m32_r32(&base, nullptr, 1,
106-
-(4 * ((int)localidx - no_of_params + 1)),
107-
X86Reg::eax);
108-
}
109-
}
110-
111-
void visit_I32Const(int32_t value) {
112-
m_a.asm_push_imm32(value);
113-
// if (value < 0) {
114-
// m_a.asm_pop_r32(X86Reg::eax);
115-
// m_a.asm_neg_r32(X86Reg::eax);
116-
// m_a.asm_push_r32(X86Reg::eax);
117-
// }
118-
}
119-
120-
void visit_I32Add() {
121-
m_a.asm_pop_r32(X86Reg::ebx);
122-
m_a.asm_pop_r32(X86Reg::eax);
123-
m_a.asm_add_r32_r32(X86Reg::eax, X86Reg::ebx);
124-
m_a.asm_push_r32(X86Reg::eax);
125-
}
126-
void visit_I32Sub() {
127-
m_a.asm_pop_r32(X86Reg::ebx);
128-
m_a.asm_pop_r32(X86Reg::eax);
129-
m_a.asm_sub_r32_r32(X86Reg::eax, X86Reg::ebx);
130-
m_a.asm_push_r32(X86Reg::eax);
131-
}
132-
void visit_I32Mul() {
133-
m_a.asm_pop_r32(X86Reg::ebx);
134-
m_a.asm_pop_r32(X86Reg::eax);
135-
m_a.asm_mul_r32(X86Reg::ebx);
136-
m_a.asm_push_r32(X86Reg::eax);
137-
}
138-
void visit_I32DivS() {
139-
m_a.asm_pop_r32(X86Reg::ebx);
140-
m_a.asm_pop_r32(X86Reg::eax);
141-
m_a.asm_div_r32(X86Reg::ebx);
142-
m_a.asm_push_r32(X86Reg::eax);
143-
}
144-
};
145-
146-
} // namespace WASM_INSTS_VISITOR
147-
1488
Result<int> wasm_to_x86(Vec<uint8_t> &wasm_bytes, Allocator &al,
1499
const std::string &filename, bool time_report,
15010
diag::Diagnostics &diagnostics);

0 commit comments

Comments
 (0)