@@ -31,6 +31,7 @@ class X64Visitor : public WASMDecoder<X64Visitor>,
31
31
public WASM_INSTS_VISITOR::BaseWASMVisitor<X64Visitor> {
32
32
public:
33
33
X86Assembler &m_a;
34
+ uint32_t cur_func_idx;
34
35
35
36
X64Visitor (X86Assembler &m_a, Allocator &al,
36
37
diag::Diagnostics &diagonostics, Vec<uint8_t > &code)
@@ -40,19 +41,105 @@ class X64Visitor : public WASMDecoder<X64Visitor>,
40
41
wasm_bytes.from_pointer_n (code.data (), code.size ());
41
42
}
42
43
44
+ void visit_Return () {}
45
+
46
+ void call_imported_function (uint32_t func_idx) {
47
+ switch (func_idx) {
48
+ case 0 : { // print_i32
49
+ std::cerr << " Call to print_i32() will be printed as exit code\n " ;
50
+
51
+ // Currently, for print we are setting the value to be printed
52
+ // as the exit code. Later we can access/view this value from console
53
+ // using: echo $?
54
+ m_a.asm_pop_r64 (X64Reg::rdi); // get exit code from stack top
55
+ m_a.asm_mov_r64_imm64 (X64Reg::rax, 60 ); // sys_exit
56
+ m_a.asm_syscall (); // syscall
57
+ break ;
58
+ }
59
+ case 1 : { // print_i64
60
+ std::cerr << " Call to print_i64() is not yet supported\n " ;
61
+ break ;
62
+ }
63
+ case 2 : { // print_f32
64
+ std::cerr << " Call to print_f32() is not yet supported\n " ;
65
+ break ;
66
+ }
67
+ case 3 : { // print_f64
68
+ std::cerr << " Call to print_f64() is not yet supported\n " ;
69
+ break ;
70
+ }
71
+ case 4 : { // print_str
72
+ std::cerr << " Call to print_str() is not yet supported\n " ;
73
+ break ;
74
+ }
75
+ case 5 : { // flush_buf
76
+ std::cerr << " Call to flush_buf() is not yet supported\n " ;
77
+ break ;
78
+ }
79
+ case 6 : { // set_exit_code
80
+ m_a.asm_pop_r64 (X64Reg::rdi); // get exit code from stack top
81
+ m_a.asm_mov_r64_imm64 (X64Reg::rax, 60 ); // sys_exit
82
+ m_a.asm_syscall (); // syscall
83
+ break ;
84
+ }
85
+ default : {
86
+ std::cerr << " Unsupported func_idx" ;
87
+ }
88
+ }
89
+ }
90
+
91
+ void visit_Call (uint32_t func_idx) {
92
+ if (func_idx <= 6U ) {
93
+ call_imported_function (func_idx);
94
+ return ;
95
+ }
96
+
97
+ func_idx -= 7u ; // adjust function index as per imports
98
+ m_a.asm_call_label (exports[func_idx].name );
99
+ }
100
+
101
+ void visit_I32Const (int32_t value) {
102
+ // direct addition of imm64 to stack is not available with us yet
103
+ // so temporarily using a combination of instructions
104
+ // TODO: Update this once we have support for push_imm64()
105
+ m_a.asm_mov_r64_imm64 (X64Reg::rax, value);
106
+ m_a.asm_push_r64 (X64Reg::rax);
107
+ }
108
+
43
109
void gen_x64_bytes () {
44
- // update the initial value of asm text as per X64 text format
45
- m_a.update_asm (" BITS 64\n\n " );
110
+ { // Initialize/Modify values of entities for code simplicity later
111
+
112
+ m_a.update_asm (" BITS 64\n\n " ); // Update initial value of asm text as per X64 text format
113
+ exports.back ().name = " _start" ; // Update _lcompilers_main() to _start
114
+ }
46
115
47
116
emit_elf64_header (m_a);
48
117
49
- {
50
- m_a.add_label (" _start" );
118
+ for (uint32_t idx = 0 ; idx < type_indices.size (); idx++) {
119
+ m_a.add_label (exports[idx].name );
120
+ {
121
+ // Initialize the stack
122
+ m_a.asm_push_r64 (X64Reg::rbp);
123
+ m_a.asm_mov_r64_r64 (X64Reg::rbp, X64Reg::rsp);
124
+
125
+ // Initialize local variables to zero and thus allocate space
126
+ m_a.asm_mov_r64_imm64 (X64Reg::rax, 0u );
127
+ for (auto &local_var_info:codes[idx].locals ) {
128
+ for (uint32_t cnt = 0u ; cnt < local_var_info.count ; cnt++) {
129
+ m_a.asm_push_r64 (X64Reg::rax);
130
+ }
131
+ }
132
+
133
+ offset = codes[idx].insts_start_index ;
134
+ cur_func_idx = idx;
135
+ decode_instructions ();
136
+
137
+ // Restore stack
138
+ m_a.asm_mov_r64_r64 (X64Reg::rsp, X64Reg::rbp);
139
+ m_a.asm_pop_r64 (X64Reg::rbp);
140
+ m_a.asm_ret ();
141
+ }
51
142
52
- // exit with a fixed non-zero exit code
53
- m_a.asm_mov_r64_imm64 (LFortran::X64Reg::rax, 60 ); // sys_exit
54
- m_a.asm_mov_r64_imm64 (LFortran::X64Reg::rdi, 24 /* exit_code */ ); // exit code
55
- m_a.asm_syscall (); // syscall
56
143
}
57
144
58
145
emit_elf64_footer (m_a);
0 commit comments