@@ -11,12 +11,128 @@ namespace LFortran {
11
11
12
12
namespace wasm {
13
13
14
- class X86Generator : public WASMDecoder <X86Generator> {
14
+ class X86Visitor : public WASMDecoder <X86Visitor>,
15
+ public WASM_INSTS_VISITOR::BaseWASMVisitor<X86Visitor> {
15
16
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
+ }
18
109
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 () {
20
136
emit_elf32_header (m_a);
21
137
22
138
// Add runtime library functions
@@ -44,13 +160,9 @@ class X86Generator : public WASMDecoder<X86Generator> {
44
160
}
45
161
}
46
162
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 ();
54
166
55
167
// Restore stack
56
168
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,
75
187
76
188
X86Assembler m_a (al);
77
189
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);
81
191
82
192
{
83
193
auto t1 = std::chrono::high_resolution_clock::now ();
84
194
try {
85
- x86_generator .decode_wasm ();
195
+ x86_visitor .decode_wasm ();
86
196
} catch (const CodeGenError &e) {
87
197
diagnostics.diagnostics .push_back (e.d );
88
198
return Error ();
@@ -95,7 +205,7 @@ Result<int> wasm_to_x86(Vec<uint8_t> &wasm_bytes, Allocator &al,
95
205
96
206
{
97
207
auto t1 = std::chrono::high_resolution_clock::now ();
98
- x86_generator .gen_x86_bytes (m_a );
208
+ x86_visitor .gen_x86_bytes ();
99
209
auto t2 = std::chrono::high_resolution_clock::now ();
100
210
time_gen_x86_bytes =
101
211
std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1)
0 commit comments