authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2022-12-08 21:29:42-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-12-09 03:45:29-05:00
log6966fb8ca5608cae122434a50ff2cd264502c0eb
treedb686902c404fbfabd181a03eb6c814afc1fcf0a
parent5c67f9ce7a4d9f5aedbe8cfba1f361922701a144

wasm2c: reuse locals

* Reduce stack usage of a -O0 build of zig1 by 33%. * Avoid compiler builtin calls.

2 files changed, 488 insertions(+), 739 deletions(-)

stage1/FuncGen.h+62-12
...@@ -8,22 +8,27 @@...@@ -8,22 +8,27 @@
8#include <stdbool.h>8#include <stdbool.h>
9#include <stdint.h>9#include <stdint.h>
10#include <stdio.h>10#include <stdio.h>
11#include <stdlib.h>
11#include <string.h>12#include <string.h>
1213
13struct Block {14struct Block {
14 uint32_t type;15 uint32_t type;
15 uint32_t label;16 uint32_t label;
16 uint32_t stack_i;17 uint32_t stack_i;
18 uint32_t reuse_i;
17};19};
1820
19struct FuncGen {21struct FuncGen {
20 int8_t *type;22 int8_t *type;
23 uint32_t *reuse;
21 uint32_t *stack;24 uint32_t *stack;
22 struct Block *block;25 struct Block *block;
23 uint32_t type_i;26 uint32_t type_i;
27 uint32_t reuse_i;
24 uint32_t stack_i;28 uint32_t stack_i;
25 uint32_t block_i;29 uint32_t block_i;
26 uint32_t type_len;30 uint32_t type_len;
31 uint32_t reuse_len;
27 uint32_t stack_len;32 uint32_t stack_len;
28 uint32_t block_len;33 uint32_t block_len;
29};34};
...@@ -34,6 +39,7 @@ static void FuncGen_init(struct FuncGen *self) {...@@ -34,6 +39,7 @@ static void FuncGen_init(struct FuncGen *self) {
3439
35static void FuncGen_reset(struct FuncGen *self) {40static void FuncGen_reset(struct FuncGen *self) {
36 self->type_i = 0;41 self->type_i = 0;
42 self->reuse_i = 0;
37 self->stack_i = 0;43 self->stack_i = 0;
38 self->block_i = 0;44 self->block_i = 0;
39}45}
...@@ -41,6 +47,7 @@ static void FuncGen_reset(struct FuncGen *self) {...@@ -41,6 +47,7 @@ static void FuncGen_reset(struct FuncGen *self) {
41static void FuncGen_free(struct FuncGen *self) {47static void FuncGen_free(struct FuncGen *self) {
42 free(self->block);48 free(self->block);
43 free(self->stack);49 free(self->stack);
50 free(self->reuse);
44 free(self->type);51 free(self->type);
45}52}
4653
...@@ -65,20 +72,41 @@ static uint32_t FuncGen_localAlloc(struct FuncGen *self, int8_t type) {...@@ -65,20 +72,41 @@ static uint32_t FuncGen_localAlloc(struct FuncGen *self, int8_t type) {
65 self->type = realloc(self->type, sizeof(int8_t) * self->type_len);72 self->type = realloc(self->type, sizeof(int8_t) * self->type_len);
66 if (self->type == NULL) panic("out of memory");73 if (self->type == NULL) panic("out of memory");
67 }74 }
68 uint32_t local_i = self->type_i;75 uint32_t local_idx = self->type_i;
69 self->type[local_i] = type;76 self->type[local_idx] = type;
70 self->type_i += 1;77 self->type_i += 1;
71 return local_i;78 return local_idx;
79}
80
81static enum WasmValType FuncGen_localType(const struct FuncGen *self, uint32_t local_idx) {
82 return self->type[local_idx];
72}83}
7384
74static uint32_t FuncGen_localDeclare(struct FuncGen *self, FILE *out, enum WasmValType val_type) {85static uint32_t FuncGen_localDeclare(struct FuncGen *self, FILE *out, enum WasmValType val_type) {
75 uint32_t local_i = FuncGen_localAlloc(self, (int8_t)val_type);86 uint32_t local_idx = FuncGen_localAlloc(self, (int8_t)val_type);
76 fprintf(out, "%s l%" PRIu32, WasmValType_toC(val_type), local_i);87 fprintf(out, "%s l%" PRIu32, WasmValType_toC(val_type), local_idx);
77 return local_i;88 return local_idx;
78}89}
7990
80static enum WasmValType FuncGen_localType(const struct FuncGen *self, uint32_t local_idx) {91static uint32_t FuncGen_reuseTop(const struct FuncGen *self) {
81 return self->type[local_idx];92 return self->block_i > 0 ? self->block[self->block_i - 1].reuse_i : 0;
93}
94
95static void FuncGen_reuseReset(struct FuncGen *self) {
96 self->reuse_i = FuncGen_reuseTop(self);
97}
98
99static uint32_t FuncGen_reuseLocal(struct FuncGen *self, FILE *out, enum WasmValType val_type) {
100 for (uint32_t i = FuncGen_reuseTop(self); i < self->reuse_i; i += 1) {
101 uint32_t local_idx = self->reuse[i];
102 if (FuncGen_localType(self, local_idx) == val_type) {
103 self->reuse_i -= 1;
104 self->reuse[i] = self->reuse[self->reuse_i];
105 fprintf(out, "l%" PRIu32, local_idx);
106 return local_idx;
107 }
108 }
109 return FuncGen_localDeclare(self, out, val_type);
82}110}
83111
84static void FuncGen_stackPush(struct FuncGen *self, FILE *out, enum WasmValType val_type) {112static void FuncGen_stackPush(struct FuncGen *self, FILE *out, enum WasmValType val_type) {
...@@ -89,8 +117,7 @@ static void FuncGen_stackPush(struct FuncGen *self, FILE *out, enum WasmValType...@@ -89,8 +117,7 @@ static void FuncGen_stackPush(struct FuncGen *self, FILE *out, enum WasmValType
89 if (self->stack == NULL) panic("out of memory");117 if (self->stack == NULL) panic("out of memory");
90 }118 }
91 FuncGen_indent(self, out);119 FuncGen_indent(self, out);
92 fputs("const ", out);120 self->stack[self->stack_i] = FuncGen_reuseLocal(self, out, val_type);
93 self->stack[self->stack_i] = FuncGen_localDeclare(self, out, val_type);
94 self->stack_i += 1;121 self->stack_i += 1;
95 fputs(" = ", out);122 fputs(" = ", out);
96}123}
...@@ -100,8 +127,17 @@ static uint32_t FuncGen_stackAt(const struct FuncGen *self, uint32_t stack_idx)...@@ -100,8 +127,17 @@ static uint32_t FuncGen_stackAt(const struct FuncGen *self, uint32_t stack_idx)
100}127}
101128
102static uint32_t FuncGen_stackPop(struct FuncGen *self) {129static uint32_t FuncGen_stackPop(struct FuncGen *self) {
130 if (self->reuse_i == self->reuse_len) {
131 self->reuse_len += 10;
132 self->reuse_len *= 2;
133 self->reuse = realloc(self->reuse, sizeof(uint32_t) * self->reuse_len);
134 if (self->reuse == NULL) panic("out of memory");
135 }
103 self->stack_i -= 1;136 self->stack_i -= 1;
104 return self->stack[self->stack_i];137 uint32_t local_idx = self->stack[self->stack_i];
138 self->reuse[self->reuse_i] = local_idx;
139 self->reuse_i += 1;
140 return local_idx;
105}141}
106142
107static void FuncGen_label(struct FuncGen *self, FILE *out, uint32_t label) {143static void FuncGen_label(struct FuncGen *self, FILE *out, uint32_t label) {
...@@ -118,7 +154,6 @@ static void FuncGen_blockBegin(struct FuncGen *self, FILE *out, enum WasmOpcode...@@ -118,7 +154,6 @@ static void FuncGen_blockBegin(struct FuncGen *self, FILE *out, enum WasmOpcode
118 self->block = realloc(self->block, sizeof(struct Block) * self->block_len);154 self->block = realloc(self->block, sizeof(struct Block) * self->block_len);
119 if (self->block == NULL) panic("out of memory");155 if (self->block == NULL) panic("out of memory");
120 }156 }
121 uint32_t label = FuncGen_localAlloc(self, type < 0 ? ~(int8_t)kind : (int8_t)kind);
122157
123 if (kind == WasmOpcode_if) {158 if (kind == WasmOpcode_if) {
124 FuncGen_indent(self, out);159 FuncGen_indent(self, out);
...@@ -128,11 +163,24 @@ static void FuncGen_blockBegin(struct FuncGen *self, FILE *out, enum WasmOpcode...@@ -128,11 +163,24 @@ static void FuncGen_blockBegin(struct FuncGen *self, FILE *out, enum WasmOpcode
128 fputs("{\n", out);163 fputs("{\n", out);
129 }164 }
130165
166 uint32_t label = FuncGen_localAlloc(self, type < 0 ? ~(int8_t)kind : (int8_t)kind);
131 self->block[self->block_i].type = type < 0 ? ~type : type;167 self->block[self->block_i].type = type < 0 ? ~type : type;
132 self->block[self->block_i].label = label;168 self->block[self->block_i].label = label;
133 self->block[self->block_i].stack_i = self->stack_i;169 self->block[self->block_i].stack_i = self->stack_i;
170 self->block[self->block_i].reuse_i = self->reuse_i;
134 self->block_i += 1;171 self->block_i += 1;
135 if (kind == WasmOpcode_loop) FuncGen_label(self, out, label);172 if (kind == WasmOpcode_loop) FuncGen_label(self, out, label);
173
174 uint32_t reuse_top = FuncGen_reuseTop(self);
175 uint32_t reuse_n = self->reuse_i - reuse_top;
176 if (reuse_n > self->reuse_len - self->reuse_i) {
177 self->reuse_len += 10;
178 self->reuse_len *= 2;
179 self->reuse = realloc(self->reuse, sizeof(uint32_t) * self->reuse_len);
180 if (self->reuse == NULL) panic("out of memory");
181 }
182 memcpy(&self->reuse[self->reuse_i], &self->reuse[reuse_top], sizeof(uint32_t) * reuse_n);
183 self->reuse_i += reuse_n;
136}184}
137185
138static enum WasmOpcode FuncGen_blockKind(const struct FuncGen *self, uint32_t label_idx) {186static enum WasmOpcode FuncGen_blockKind(const struct FuncGen *self, uint32_t label_idx) {
...@@ -165,6 +213,8 @@ static void FuncGen_blockEnd(struct FuncGen *self, FILE *out) {...@@ -165,6 +213,8 @@ static void FuncGen_blockEnd(struct FuncGen *self, FILE *out) {
165 fprintf(out, "// stack mismatch %u != %u\n", self->stack_i, self->block[self->block_i].stack_i);213 fprintf(out, "// stack mismatch %u != %u\n", self->stack_i, self->block[self->block_i].stack_i);
166 }214 }
167 self->stack_i = self->block[self->block_i].stack_i;215 self->stack_i = self->block[self->block_i].stack_i;
216
217 self->reuse_i = self->block[self->block_i].reuse_i;
168}218}
169219
170static bool FuncGen_done(const struct FuncGen *self) {220static bool FuncGen_done(const struct FuncGen *self) {
stage1/wasm2c.c+426-727
...@@ -97,21 +97,20 @@ int main(int argc, char **argv) {...@@ -97,21 +97,20 @@ int main(int argc, char **argv) {
97 "#include <stdint.h>\n"97 "#include <stdint.h>\n"
98 "#include <stdlib.h>\n"98 "#include <stdlib.h>\n"
99 "#include <string.h>\n"99 "#include <string.h>\n"
100 "\n"
101 "static uint16_t i16_byteswap(uint16_t src) {\n"
102 " return (uint16_t)(uint8_t)(src >> 0) << 8 |\n"
103 " (uint16_t)(uint8_t)(src >> 8) << 0;\n"
104 "}\n"
105 "static uint32_t i32_byteswap(uint32_t src) {\n"
106 " return (uint32_t)i16_byteswap(src >> 0) << 16 |\n"
107 " (uint32_t)i16_byteswap(src >> 16) << 0;\n"
108 "}\n"
109 "static uint64_t i64_byteswap(uint64_t src) {\n"
110 " return (uint64_t)i32_byteswap(src >> 0) << 32 |\n"
111 " (uint64_t)i32_byteswap(src >> 32) << 0;\n"
112 "}\n"
100 "\n", out);113 "\n", out);
101 if (is_big_endian)
102 fputs("static uint16_t i16_byteswap(uint16_t src) {\n"
103 " return (uint16_t)(uint8_t)(src >> 0) << 8 |\n"
104 " (uint16_t)(uint8_t)(src >> 8) << 0;\n"
105 "}\n"
106 "static uint32_t i32_byteswap(uint32_t src) {\n"
107 " return (uint32_t)i16_byteswap(src >> 0) << 16 |\n"
108 " (uint32_t)i16_byteswap(src >> 16) << 0;\n"
109 "}\n"
110 "static uint64_t i64_byteswap(uint64_t src) {\n"
111 " return (uint64_t)i32_byteswap(src >> 0) << 32 |\n"
112 " (uint64_t)i32_byteswap(src >> 32) << 0;\n"
113 "}\n"
114 "\n", out);
115 fputs("static uint16_t load16_align0(const uint8_t *ptr) {\n"114 fputs("static uint16_t load16_align0(const uint8_t *ptr) {\n"
116 " uint16_t val;\n"115 " uint16_t val;\n"
117 " memcpy(&val, ptr, sizeof(val));\n", out);116 " memcpy(&val, ptr, sizeof(val));\n", out);
...@@ -165,6 +164,39 @@ int main(int argc, char **argv) {...@@ -165,6 +164,39 @@ int main(int argc, char **argv) {
165 " memcpy(&val, ptr, sizeof(val));\n", out);164 " memcpy(&val, ptr, sizeof(val));\n", out);
166 if (is_big_endian) fputs(" val = i64_byteswap(val);", out);165 if (is_big_endian) fputs(" val = i64_byteswap(val);", out);
167 fputs(" return val;\n"166 fputs(" return val;\n"
167 "}\n"
168 "\n"
169 "static uint32_t i32_popcnt(uint32_t lhs) {\n"
170 " lhs = lhs - ((lhs >> 1) & UINT32_C(0x55555555));\n"
171 " lhs = (lhs & UINT32_C(0x33333333)) + ((lhs >> 2) & UINT32_C(0x33333333));\n"
172 " lhs = (lhs + (lhs >> 4)) & UINT32_C(0x0F0F0F0F);\n"
173 " return (lhs * UINT32_C(0x01010101)) >> 24;\n"
174 "}\n"
175 "static uint32_t i32_ctz(uint32_t lhs) {\n"
176 " return i32_popcnt(~lhs & (lhs - 1));\n"
177 "}\n"
178 "static uint32_t i32_clz(uint32_t lhs) {\n"
179 " lhs = i32_byteswap(lhs);\n"
180 " lhs = (lhs & UINT32_C(0x0F0F0F0F)) << 4 | (lhs & UINT32_C(0xF0F0F0F0)) >> 4;\n"
181 " lhs = (lhs & UINT32_C(0x33333333)) << 2 | (lhs & UINT32_C(0xCCCCCCCC)) >> 2;\n"
182 " lhs = (lhs & UINT32_C(0x55555555)) << 1 | (lhs & UINT32_C(0xAAAAAAAA)) >> 1;\n"
183 " return i32_ctz(lhs);\n"
184 "}\n"
185 "static uint64_t i64_popcnt(uint64_t lhs) {\n"
186 " lhs = lhs - ((lhs >> 1) & UINT64_C(0x5555555555555555));\n"
187 " lhs = (lhs & UINT64_C(0x3333333333333333)) + ((lhs >> 2) & UINT64_C(0x3333333333333333));\n"
188 " lhs = (lhs + (lhs >> 4)) & UINT64_C(0x0F0F0F0F0F0F0F0F);\n"
189 " return (lhs * UINT64_C(0x0101010101010101)) >> 56;\n"
190 "}\n"
191 "static uint64_t i64_ctz(uint64_t lhs) {\n"
192 " return i64_popcnt(~lhs & (lhs - 1));\n"
193 "}\n"
194 "static uint64_t i64_clz(uint64_t lhs) {\n"
195 " lhs = i64_byteswap(lhs);\n"
196 " lhs = (lhs & UINT64_C(0x0F0F0F0F0F0F0F0F)) << 4 | (lhs & UINT32_C(0xF0F0F0F0F0F0F0F0)) >> 4;\n"
197 " lhs = (lhs & UINT64_C(0x3333333333333333)) << 2 | (lhs & UINT32_C(0xCCCCCCCCCCCCCCCC)) >> 2;\n"
198 " lhs = (lhs & UINT64_C(0x5555555555555555)) << 1 | (lhs & UINT32_C(0xAAAAAAAAAAAAAAAA)) >> 1;\n"
199 " return i64_ctz(lhs);\n"
168 "}\n"200 "}\n"
169 "\n"201 "\n"
170 "static void store16_align0(uint8_t *ptr, uint16_t val) {\n", out);202 "static void store16_align0(uint8_t *ptr, uint16_t val) {\n", out);
...@@ -787,6 +819,7 @@ int main(int argc, char **argv) {...@@ -787,6 +819,7 @@ int main(int argc, char **argv) {
787 } else unreachable_depth -= 1;819 } else unreachable_depth -= 1;
788 switch (opcode) {820 switch (opcode) {
789 case WasmOpcode_else:821 case WasmOpcode_else:
822 FuncGen_reuseReset(&fg);
790 FuncGen_outdent(&fg, out);823 FuncGen_outdent(&fg, out);
791 fputs("} else {\n", out);824 fputs("} else {\n", out);
792 break;825 break;
...@@ -968,10 +1001,10 @@ int main(int argc, char **argv) {...@@ -968,10 +1001,10 @@ int main(int argc, char **argv) {
968 if (unreachable_depth == 0) {1001 if (unreachable_depth == 0) {
969 uint32_t cond = FuncGen_stackPop(&fg);1002 uint32_t cond = FuncGen_stackPop(&fg);
970 uint32_t rhs = FuncGen_stackPop(&fg);1003 uint32_t rhs = FuncGen_stackPop(&fg);
971 uint32_t lhs = FuncGen_stackPop(&fg);1004 uint32_t lhs = FuncGen_stackAt(&fg, 0);
972 FuncGen_stackPush(&fg, out, FuncGen_localType(&fg, lhs));1005 FuncGen_indent(&fg, out);
973 fprintf(out, "l%" PRIu32 " ? l%" PRIu32 " : l%" PRIu32 ";\n",1006 fprintf(out, "l%"PRIu32" = l%" PRIu32 " ? l%" PRIu32 " : l%" PRIu32 ";\n",
974 cond, lhs, rhs);1007 lhs, cond, lhs, rhs);
975 }1008 }
976 break;1009 break;
9771010
...@@ -1369,89 +1402,55 @@ int main(int argc, char **argv) {...@@ -1369,89 +1402,55 @@ int main(int argc, char **argv) {
13691402
1370 case WasmOpcode_i32_eqz:1403 case WasmOpcode_i32_eqz:
1371 if (unreachable_depth == 0) {1404 if (unreachable_depth == 0) {
1372 uint32_t lhs = FuncGen_stackPop(&fg);1405 uint32_t lhs = FuncGen_stackAt(&fg, 0);
1373 FuncGen_stackPush(&fg, out, WasmValType_i32);1406 FuncGen_indent(&fg, out);
1374 fprintf(out, "!l%" PRIu32 ";\n", lhs);1407 fprintf(out, "l%" PRIu32 " = !l%" PRIu32 ";\n", lhs, lhs);
1375 }1408 }
1376 break;1409 break;
1377 case WasmOpcode_i32_eq:1410 case WasmOpcode_i32_eq:
1378 if (unreachable_depth == 0) {
1379 uint32_t rhs = FuncGen_stackPop(&fg);
1380 uint32_t lhs = FuncGen_stackPop(&fg);
1381 FuncGen_stackPush(&fg, out, WasmValType_i32);
1382 fprintf(out, "l%" PRIu32 " == l%" PRIu32 ";\n", lhs, rhs);
1383 }
1384 break;
1385 case WasmOpcode_i32_ne:1411 case WasmOpcode_i32_ne:
1386 if (unreachable_depth == 0) {
1387 uint32_t rhs = FuncGen_stackPop(&fg);
1388 uint32_t lhs = FuncGen_stackPop(&fg);
1389 FuncGen_stackPush(&fg, out, WasmValType_i32);
1390 fprintf(out, "l%" PRIu32 " != l%" PRIu32 ";\n", lhs, rhs);
1391 }
1392 break;
1393 case WasmOpcode_i32_lt_s:
1394 if (unreachable_depth == 0) {
1395 uint32_t rhs = FuncGen_stackPop(&fg);
1396 uint32_t lhs = FuncGen_stackPop(&fg);
1397 FuncGen_stackPush(&fg, out, WasmValType_i32);
1398 fprintf(out, "(int32_t)l%" PRIu32 " < (int32_t)l%" PRIu32 ";\n", lhs, rhs);
1399 }
1400 break;
1401 case WasmOpcode_i32_lt_u:1412 case WasmOpcode_i32_lt_u:
1402 if (unreachable_depth == 0) {
1403 uint32_t rhs = FuncGen_stackPop(&fg);
1404 uint32_t lhs = FuncGen_stackPop(&fg);
1405 FuncGen_stackPush(&fg, out, WasmValType_i32);
1406 fprintf(out, "l%" PRIu32 " < l%" PRIu32 ";\n", lhs, rhs);
1407 }
1408 break;
1409 case WasmOpcode_i32_gt_s:
1410 if (unreachable_depth == 0) {
1411 uint32_t rhs = FuncGen_stackPop(&fg);
1412 uint32_t lhs = FuncGen_stackPop(&fg);
1413 FuncGen_stackPush(&fg, out, WasmValType_i32);
1414 fprintf(out, "(int32_t)l%" PRIu32 " > (int32_t)l%" PRIu32 ";\n", lhs, rhs);
1415 }
1416 break;
1417 case WasmOpcode_i32_gt_u:1413 case WasmOpcode_i32_gt_u:
1418 if (unreachable_depth == 0) {
1419 uint32_t rhs = FuncGen_stackPop(&fg);
1420 uint32_t lhs = FuncGen_stackPop(&fg);
1421 FuncGen_stackPush(&fg, out, WasmValType_i32);
1422 fprintf(out, "l%" PRIu32 " > l%" PRIu32 ";\n", lhs, rhs);
1423 }
1424 break;
1425 case WasmOpcode_i32_le_s:
1426 if (unreachable_depth == 0) {
1427 uint32_t rhs = FuncGen_stackPop(&fg);
1428 uint32_t lhs = FuncGen_stackPop(&fg);
1429 FuncGen_stackPush(&fg, out, WasmValType_i32);
1430 fprintf(out, "(int32_t)l%" PRIu32 " <= (int32_t)l%" PRIu32 ";\n", lhs, rhs);
1431 }
1432 break;
1433 case WasmOpcode_i32_le_u:1414 case WasmOpcode_i32_le_u:
1415 case WasmOpcode_i32_ge_u:
1416 // i32 unsigned comparisons
1434 if (unreachable_depth == 0) {1417 if (unreachable_depth == 0) {
1435 uint32_t rhs = FuncGen_stackPop(&fg);1418 uint32_t rhs = FuncGen_stackPop(&fg);
1436 uint32_t lhs = FuncGen_stackPop(&fg);1419 uint32_t lhs = FuncGen_stackAt(&fg, 0);
1437 FuncGen_stackPush(&fg, out, WasmValType_i32);1420 const char *operator;
1438 fprintf(out, "l%" PRIu32 " <= l%" PRIu32 ";\n", lhs, rhs);1421 switch (opcode) {
1422 case WasmOpcode_i32_eq: operator = "=="; break;
1423 case WasmOpcode_i32_ne: operator = "!="; break;
1424 case WasmOpcode_i32_lt_u: operator = "<"; break;
1425 case WasmOpcode_i32_gt_u: operator = ">"; break;
1426 case WasmOpcode_i32_le_u: operator = "<="; break;
1427 case WasmOpcode_i32_ge_u: operator = ">="; break;
1428 default: panic("unreachable");
1429 }
1430 FuncGen_indent(&fg, out);
1431 fprintf(out, "l%" PRIu32 " = l%" PRIu32 " %s l%" PRIu32 ";\n",
1432 lhs, lhs, operator, rhs);
1439 }1433 }
1440 break;1434 break;
1435 case WasmOpcode_i32_lt_s:
1436 case WasmOpcode_i32_gt_s:
1437 case WasmOpcode_i32_le_s:
1441 case WasmOpcode_i32_ge_s:1438 case WasmOpcode_i32_ge_s:
1439 // i32 signed comparisons
1442 if (unreachable_depth == 0) {1440 if (unreachable_depth == 0) {
1443 uint32_t rhs = FuncGen_stackPop(&fg);1441 uint32_t rhs = FuncGen_stackPop(&fg);
1444 uint32_t lhs = FuncGen_stackPop(&fg);1442 uint32_t lhs = FuncGen_stackAt(&fg, 0);
1445 FuncGen_stackPush(&fg, out, WasmValType_i32);1443 const char *operator;
1446 fprintf(out, "(int32_t)l%" PRIu32 " >= (int32_t)l%" PRIu32 ";\n", lhs, rhs);1444 switch (opcode) {
1447 }1445 case WasmOpcode_i32_lt_s: operator = "<"; break;
1448 break;1446 case WasmOpcode_i32_gt_s: operator = ">"; break;
1449 case WasmOpcode_i32_ge_u:1447 case WasmOpcode_i32_le_s: operator = "<="; break;
1450 if (unreachable_depth == 0) {1448 case WasmOpcode_i32_ge_s: operator = ">="; break;
1451 uint32_t rhs = FuncGen_stackPop(&fg);1449 default: panic("unreachable");
1452 uint32_t lhs = FuncGen_stackPop(&fg);1450 }
1453 FuncGen_stackPush(&fg, out, WasmValType_i32);1451 FuncGen_indent(&fg, out);
1454 fprintf(out, "l%" PRIu32 " >= l%" PRIu32 ";\n", lhs, rhs);1452 fprintf(out, "l%" PRIu32 " = (int32_t)l%" PRIu32 " %s (int32_t)l%" PRIu32
1453 ";\n", lhs, lhs, operator, rhs);
1455 }1454 }
1456 break;1455 break;
14571456
...@@ -1463,685 +1462,385 @@ int main(int argc, char **argv) {...@@ -1463,685 +1462,385 @@ int main(int argc, char **argv) {
1463 }1462 }
1464 break;1463 break;
1465 case WasmOpcode_i64_eq:1464 case WasmOpcode_i64_eq:
1466 if (unreachable_depth == 0) {
1467 uint32_t rhs = FuncGen_stackPop(&fg);
1468 uint32_t lhs = FuncGen_stackPop(&fg);
1469 FuncGen_stackPush(&fg, out, WasmValType_i32);
1470 fprintf(out, "l%" PRIu32 " == l%" PRIu32 ";\n", lhs, rhs);
1471 }
1472 break;
1473 case WasmOpcode_i64_ne:1465 case WasmOpcode_i64_ne:
1466 case WasmOpcode_i64_lt_u:
1467 case WasmOpcode_i64_gt_u:
1468 case WasmOpcode_i64_le_u:
1469 case WasmOpcode_i64_ge_u:
1470 case WasmOpcode_f32_eq:
1471 case WasmOpcode_f32_ne:
1472 case WasmOpcode_f32_lt:
1473 case WasmOpcode_f32_gt:
1474 case WasmOpcode_f32_le:
1475 case WasmOpcode_f32_ge:
1476 case WasmOpcode_f64_eq:
1477 case WasmOpcode_f64_ne:
1478 case WasmOpcode_f64_lt:
1479 case WasmOpcode_f64_gt:
1480 case WasmOpcode_f64_le:
1481 case WasmOpcode_f64_ge:
1482 // non-i32 unsigned comparisons
1474 if (unreachable_depth == 0) {1483 if (unreachable_depth == 0) {
1475 uint32_t rhs = FuncGen_stackPop(&fg);1484 uint32_t rhs = FuncGen_stackPop(&fg);
1476 uint32_t lhs = FuncGen_stackPop(&fg);1485 uint32_t lhs = FuncGen_stackPop(&fg);
1486 const char *operator;
1487 switch (opcode) {
1488 case WasmOpcode_i64_eq:
1489 case WasmOpcode_f32_eq:
1490 case WasmOpcode_f64_eq:
1491 operator = "==";
1492 break;
1493 case WasmOpcode_i64_ne:
1494 case WasmOpcode_f32_ne:
1495 case WasmOpcode_f64_ne:
1496 operator = "!=";
1497 break;
1498 case WasmOpcode_i64_lt_u:
1499 case WasmOpcode_f32_lt:
1500 case WasmOpcode_f64_lt:
1501 operator = "<";
1502 break;
1503 case WasmOpcode_i64_gt_u:
1504 case WasmOpcode_f32_gt:
1505 case WasmOpcode_f64_gt:
1506 operator = ">";
1507 break;
1508 case WasmOpcode_i64_le_u:
1509 case WasmOpcode_f32_le:
1510 case WasmOpcode_f64_le:
1511 operator = "<=";
1512 break;
1513 case WasmOpcode_i64_ge_u:
1514 case WasmOpcode_f32_ge:
1515 case WasmOpcode_f64_ge:
1516 operator = ">=";
1517 break;
1518 default: panic("unreachable");
1519 }
1477 FuncGen_stackPush(&fg, out, WasmValType_i32);1520 FuncGen_stackPush(&fg, out, WasmValType_i32);
1478 fprintf(out, "l%" PRIu32 " != l%" PRIu32 ";\n", lhs, rhs);1521 fprintf(out, "l%" PRIu32 " = l%" PRIu32 " %s l%" PRIu32 ";\n",
1522 lhs, lhs, operator, rhs);
1479 }1523 }
1480 break;1524 break;
1481 case WasmOpcode_i64_lt_s:1525 case WasmOpcode_i64_lt_s:
1526 case WasmOpcode_i64_gt_s:
1527 case WasmOpcode_i64_le_s:
1528 case WasmOpcode_i64_ge_s:
1529 // i64 signed comparisons
1482 if (unreachable_depth == 0) {1530 if (unreachable_depth == 0) {
1483 uint32_t rhs = FuncGen_stackPop(&fg);1531 uint32_t rhs = FuncGen_stackPop(&fg);
1484 uint32_t lhs = FuncGen_stackPop(&fg);1532 uint32_t lhs = FuncGen_stackPop(&fg);
1533 const char *operator;
1534 switch (opcode) {
1535 case WasmOpcode_i64_lt_s: operator = "<"; break;
1536 case WasmOpcode_i64_gt_s: operator = ">"; break;
1537 case WasmOpcode_i64_le_s: operator = "<="; break;
1538 case WasmOpcode_i64_ge_s: operator = ">="; break;
1539 default: panic("unreachable");
1540 }
1485 FuncGen_stackPush(&fg, out, WasmValType_i32);1541 FuncGen_stackPush(&fg, out, WasmValType_i32);
1486 fprintf(out, "(int64_t)l%" PRIu32 " < (int64_t)l%" PRIu32 ";\n", lhs, rhs);1542 fprintf(out, "l%" PRIu32 " = (int64_t)l%" PRIu32 " %s (int64_t)l%" PRIu32
1543 ";\n", lhs, lhs, operator, rhs);
1487 }1544 }
1488 break;1545 break;
1489 case WasmOpcode_i64_lt_u:1546
1547 case WasmOpcode_i32_clz:
1548 case WasmOpcode_i32_ctz:
1549 case WasmOpcode_i32_popcnt:
1550 case WasmOpcode_i64_clz:
1551 case WasmOpcode_i64_ctz:
1552 case WasmOpcode_i64_popcnt:
1553 case WasmOpcode_f32_abs:
1554 case WasmOpcode_f32_neg:
1555 case WasmOpcode_f32_ceil:
1556 case WasmOpcode_f32_floor:
1557 case WasmOpcode_f32_trunc:
1558 case WasmOpcode_f32_nearest:
1559 case WasmOpcode_f32_sqrt:
1560 case WasmOpcode_f64_abs:
1561 case WasmOpcode_f64_neg:
1562 case WasmOpcode_f64_ceil:
1563 case WasmOpcode_f64_floor:
1564 case WasmOpcode_f64_trunc:
1565 case WasmOpcode_f64_nearest:
1566 case WasmOpcode_f64_sqrt:
1567 // unary functions
1490 if (unreachable_depth == 0) {1568 if (unreachable_depth == 0) {
1491 uint32_t rhs = FuncGen_stackPop(&fg);1569 uint32_t lhs = FuncGen_stackAt(&fg, 0);
1492 uint32_t lhs = FuncGen_stackPop(&fg);1570 const char *function;
1493 FuncGen_stackPush(&fg, out, WasmValType_i32);1571 switch (opcode) {
1494 fprintf(out, "l%" PRIu32 " < l%" PRIu32 ";\n", lhs, rhs);1572 case WasmOpcode_i32_clz: function = "i32_clz"; break;
1573 case WasmOpcode_i32_ctz: function = "i32_ctz"; break;
1574 case WasmOpcode_i32_popcnt: function = "i32_popcnt"; break;
1575 case WasmOpcode_i64_clz: function = "i64_clz"; break;
1576 case WasmOpcode_i64_ctz: function = "i64_ctz"; break;
1577 case WasmOpcode_i64_popcnt: function = "i64_popcnt"; break;
1578 case WasmOpcode_f32_abs: function = "fabsf"; break;
1579 case WasmOpcode_f32_neg:
1580 case WasmOpcode_f64_neg: function = "-"; break;
1581 case WasmOpcode_f32_ceil: function = "ceilf"; break;
1582 case WasmOpcode_f32_floor: function = "floorf"; break;
1583 case WasmOpcode_f32_trunc: function = "truncf"; break;
1584 case WasmOpcode_f32_nearest: function = "roundf"; break;
1585 case WasmOpcode_f32_sqrt: function = "sqrtf"; break;
1586 case WasmOpcode_f64_abs: function = "fabs"; break;
1587 case WasmOpcode_f64_ceil: function = "ceil"; break;
1588 case WasmOpcode_f64_floor: function = "floor"; break;
1589 case WasmOpcode_f64_trunc: function = "trunc"; break;
1590 case WasmOpcode_f64_nearest: function = "round"; break;
1591 case WasmOpcode_f64_sqrt: function = "sqrt"; break;
1592 default: panic("unreachable");
1593 }
1594 FuncGen_indent(&fg, out);
1595 fprintf(out, "l%" PRIu32 " = %s(l%" PRIu32 ");\n", lhs, function, lhs);
1495 }1596 }
1496 break;1597 break;
1497 case WasmOpcode_i64_gt_s:1598 case WasmOpcode_i32_add:
1599 case WasmOpcode_i32_sub:
1600 case WasmOpcode_i32_mul:
1601 case WasmOpcode_i32_div_u:
1602 case WasmOpcode_i32_rem_u:
1603 case WasmOpcode_i32_and:
1604 case WasmOpcode_i32_or:
1605 case WasmOpcode_i32_xor:
1606 case WasmOpcode_i64_add:
1607 case WasmOpcode_i64_sub:
1608 case WasmOpcode_i64_mul:
1609 case WasmOpcode_i64_div_u:
1610 case WasmOpcode_i64_rem_u:
1611 case WasmOpcode_i64_and:
1612 case WasmOpcode_i64_or:
1613 case WasmOpcode_i64_xor:
1614 case WasmOpcode_f32_add:
1615 case WasmOpcode_f32_sub:
1616 case WasmOpcode_f32_mul:
1617 case WasmOpcode_f32_div:
1618 case WasmOpcode_f64_add:
1619 case WasmOpcode_f64_sub:
1620 case WasmOpcode_f64_mul:
1621 case WasmOpcode_f64_div:
1622 // unsigned binary operators
1498 if (unreachable_depth == 0) {1623 if (unreachable_depth == 0) {
1499 uint32_t rhs = FuncGen_stackPop(&fg);1624 uint32_t rhs = FuncGen_stackPop(&fg);
1500 uint32_t lhs = FuncGen_stackPop(&fg);1625 uint32_t lhs = FuncGen_stackAt(&fg, 0);
1501 FuncGen_stackPush(&fg, out, WasmValType_i32);1626 char operator;
1502 fprintf(out, "(int64_t)l%" PRIu32 " > (int64_t)l%" PRIu32 ";\n", lhs, rhs);1627 switch (opcode) {
1628 case WasmOpcode_i32_add:
1629 case WasmOpcode_i64_add:
1630 case WasmOpcode_f32_add:
1631 case WasmOpcode_f64_add:
1632 operator = '+';
1633 break;
1634 case WasmOpcode_i32_sub:
1635 case WasmOpcode_i64_sub:
1636 case WasmOpcode_f32_sub:
1637 case WasmOpcode_f64_sub:
1638 operator = '-';
1639 break;
1640 case WasmOpcode_i32_mul:
1641 case WasmOpcode_i64_mul:
1642 case WasmOpcode_f32_mul:
1643 case WasmOpcode_f64_mul:
1644 operator = '*';
1645 break;
1646 case WasmOpcode_i32_div_u:
1647 case WasmOpcode_i64_div_u:
1648 case WasmOpcode_f32_div:
1649 case WasmOpcode_f64_div:
1650 operator = '/';
1651 break;
1652 case WasmOpcode_i32_rem_u:
1653 case WasmOpcode_i64_rem_u:
1654 operator = '%';
1655 break;
1656 case WasmOpcode_i32_and:
1657 case WasmOpcode_i64_and:
1658 operator = '&';
1659 break;
1660 case WasmOpcode_i32_or:
1661 case WasmOpcode_i64_or:
1662 operator = '|';
1663 break;
1664 case WasmOpcode_i32_xor:
1665 case WasmOpcode_i64_xor:
1666 operator = '^';
1667 break;
1668 default: panic("unreachable");
1669 }
1670 FuncGen_indent(&fg, out);
1671 fprintf(out, "l%" PRIu32 " %c= l%" PRIu32 ";\n", lhs, operator, rhs);
1503 }1672 }
1504 break;1673 break;
1505 case WasmOpcode_i64_gt_u:1674 case WasmOpcode_i32_div_s:
1675 case WasmOpcode_i32_rem_s:
1676 case WasmOpcode_i64_div_s:
1677 case WasmOpcode_i64_rem_s:
1678 // signed binary operators
1506 if (unreachable_depth == 0) {1679 if (unreachable_depth == 0) {
1507 uint32_t rhs = FuncGen_stackPop(&fg);1680 uint32_t rhs = FuncGen_stackPop(&fg);
1508 uint32_t lhs = FuncGen_stackPop(&fg);1681 uint32_t lhs = FuncGen_stackAt(&fg, 0);
1509 FuncGen_stackPush(&fg, out, WasmValType_i32);1682 char operator;
1510 fprintf(out, "l%" PRIu32 " > l%" PRIu32 ";\n", lhs, rhs);1683 unsigned width;
1684 switch (opcode) {
1685 case WasmOpcode_i32_div_s:
1686 case WasmOpcode_i64_div_s:
1687 operator = '/';
1688 break;
1689 case WasmOpcode_i32_rem_s:
1690 case WasmOpcode_i64_rem_s:
1691 operator = '%';
1692 break;
1693 default: panic("unreachable");
1694 }
1695 switch (opcode) {
1696 case WasmOpcode_i32_div_s:
1697 case WasmOpcode_i32_rem_s:
1698 width = 32;
1699 break;
1700 case WasmOpcode_i64_div_s:
1701 case WasmOpcode_i64_rem_s:
1702 width = 64;
1703 break;
1704 default: panic("unreachable");
1705 }
1706 FuncGen_indent(&fg, out);
1707 fprintf(out, "l%" PRIu32 " = (uint%u_t)((int%u_t)l%" PRIu32 " %c "
1708 "(int%u_t)l%" PRIu32 ");\n",
1709 lhs, width, width, lhs, operator, width, rhs);
1511 }1710 }
1512 break;1711 break;
1513 case WasmOpcode_i64_le_s:1712 case WasmOpcode_i32_shl:
1713 case WasmOpcode_i32_shr_u:
1714 case WasmOpcode_i64_shl:
1715 case WasmOpcode_i64_shr_u:
1716 // unsigned shift operators
1514 if (unreachable_depth == 0) {1717 if (unreachable_depth == 0) {
1515 uint32_t rhs = FuncGen_stackPop(&fg);1718 uint32_t rhs = FuncGen_stackPop(&fg);
1516 uint32_t lhs = FuncGen_stackPop(&fg);1719 uint32_t lhs = FuncGen_stackAt(&fg, 0);
1517 FuncGen_stackPush(&fg, out, WasmValType_i32);1720 char operator;
1518 fprintf(out, "(int64_t)l%" PRIu32 " <= (int64_t)l%" PRIu32 ";\n", lhs, rhs);1721 unsigned width;
1722 switch (opcode) {
1723 case WasmOpcode_i32_shl:
1724 case WasmOpcode_i64_shl:
1725 operator = '<';
1726 break;
1727 case WasmOpcode_i32_shr_u:
1728 case WasmOpcode_i64_shr_u:
1729 operator = '>';
1730 break;
1731 default: panic("unreachable");
1732 }
1733 switch (opcode) {
1734 case WasmOpcode_i32_shl:
1735 case WasmOpcode_i32_shr_u:
1736 width = 32;
1737 break;
1738 case WasmOpcode_i64_shl:
1739 case WasmOpcode_i64_shr_u:
1740 width = 64;
1741 break;
1742 default: panic("unreachable");
1743 }
1744 FuncGen_indent(&fg, out);
1745 fprintf(out, "l%" PRIu32 " %c%c= l%" PRIu32 " & 0x%X;\n",
1746 lhs, operator, operator, rhs, width - 1);
1519 }1747 }
1520 break;1748 break;
1521 case WasmOpcode_i64_le_u:1749 case WasmOpcode_i32_shr_s:
1750 case WasmOpcode_i64_shr_s:
1751 // signed shift operators
1522 if (unreachable_depth == 0) {1752 if (unreachable_depth == 0) {
1523 uint32_t rhs = FuncGen_stackPop(&fg);1753 uint32_t rhs = FuncGen_stackPop(&fg);
1524 uint32_t lhs = FuncGen_stackPop(&fg);1754 uint32_t lhs = FuncGen_stackAt(&fg, 0);
1525 FuncGen_stackPush(&fg, out, WasmValType_i32);1755 char operator;
1526 fprintf(out, "l%" PRIu32 " <= l%" PRIu32 ";\n", lhs, rhs);1756 unsigned width;
1757 switch (opcode) {
1758 case WasmOpcode_i32_shr_s:
1759 case WasmOpcode_i64_shr_s:
1760 operator = '>';
1761 break;
1762 default: panic("unreachable");
1763 }
1764 switch (opcode) {
1765 case WasmOpcode_i32_shr_s:
1766 width = 32;
1767 break;
1768 case WasmOpcode_i64_shr_s:
1769 width = 64;
1770 break;
1771 default: panic("unreachable");
1772 }
1773 FuncGen_indent(&fg, out);
1774 fprintf(out, "l%" PRIu32 " = (uint%u_t)((int%u_t)l%" PRIu32 " %c%c "
1775 "(l%" PRIu32 " & 0x%X));\n",
1776 lhs, width, width, lhs, operator, operator, rhs, width - 1);
1527 }1777 }
1528 break;1778 break;
1529 case WasmOpcode_i64_ge_s:1779 case WasmOpcode_i32_rotl:
1780 case WasmOpcode_i32_rotr:
1781 case WasmOpcode_i64_rotl:
1782 case WasmOpcode_i64_rotr:
1783 // rotate operators
1530 if (unreachable_depth == 0) {1784 if (unreachable_depth == 0) {
1531 uint32_t rhs = FuncGen_stackPop(&fg);1785 uint32_t rhs = FuncGen_stackPop(&fg);
1532 uint32_t lhs = FuncGen_stackPop(&fg);1786 uint32_t lhs = FuncGen_stackAt(&fg, 0);
1533 FuncGen_stackPush(&fg, out, WasmValType_i32);1787 char forward_operator;
1534 fprintf(out, "(int64_t)l%" PRIu32 " >= (int64_t)l%" PRIu32 ";\n", lhs, rhs);1788 char reverse_operator;
1789 unsigned width;
1790 switch (opcode) {
1791 case WasmOpcode_i32_rotl:
1792 case WasmOpcode_i64_rotl:
1793 forward_operator = '<';
1794 reverse_operator = '>';
1795 break;
1796 case WasmOpcode_i32_rotr:
1797 case WasmOpcode_i64_rotr:
1798 forward_operator = '>';
1799 reverse_operator = '<';
1800 break;
1801 default: panic("unreachable");
1802 }
1803 switch (opcode) {
1804 case WasmOpcode_i32_rotl:
1805 case WasmOpcode_i32_rotr:
1806 width = 32;
1807 break;
1808 case WasmOpcode_i64_rotl:
1809 case WasmOpcode_i64_rotr:
1810 width = 64;
1811 break;
1812 default: panic("unreachable");
1813 }
1814 FuncGen_indent(&fg, out);
1815 fprintf(out, "l%" PRIu32" = l%" PRIu32 " %c%c (l%" PRIu32 " & 0x%X) | "
1816 "l%" PRIu32 " %c%c (-l%" PRIu32" & 0x%X);\n", lhs,
1817 lhs, forward_operator, forward_operator, rhs, width - 1,
1818 lhs, reverse_operator, reverse_operator, rhs, width - 1);
1535 }1819 }
1536 break;1820 break;
1537 case WasmOpcode_i64_ge_u:1821 case WasmOpcode_f32_min:
1822 case WasmOpcode_f32_max:
1823 case WasmOpcode_f32_copysign:
1824 case WasmOpcode_f64_min:
1825 case WasmOpcode_f64_max:
1826 case WasmOpcode_f64_copysign:
1827 // binary functions
1538 if (unreachable_depth == 0) {1828 if (unreachable_depth == 0) {
1539 uint32_t rhs = FuncGen_stackPop(&fg);1829 uint32_t rhs = FuncGen_stackPop(&fg);
1540 uint32_t lhs = FuncGen_stackPop(&fg);1830 uint32_t lhs = FuncGen_stackAt(&fg, 0);
1541 FuncGen_stackPush(&fg, out, WasmValType_i32);1831 const char *function;
1542 fprintf(out, "l%" PRIu32 " >= l%" PRIu32 ";\n", lhs, rhs);1832 switch (opcode) {
1543 }1833 case WasmOpcode_f32_min: function = "fminf"; break;
1544 break;1834 case WasmOpcode_f32_max: function = "fmaxf"; break;
15451835 case WasmOpcode_f32_copysign: function = "copysignf"; break;
1546 case WasmOpcode_f32_eq:1836 case WasmOpcode_f64_min: function = "fmin"; break;
1547 if (unreachable_depth == 0) {1837 case WasmOpcode_f64_max: function = "fmax"; break;
1548 uint32_t rhs = FuncGen_stackPop(&fg);1838 case WasmOpcode_f64_copysign: function = "copysign"; break;
1549 uint32_t lhs = FuncGen_stackPop(&fg);1839 default: panic("unreachable");
1550 FuncGen_stackPush(&fg, out, WasmValType_i32);1840 }
1551 fprintf(out, "l%" PRIu32 " == l%" PRIu32 ";\n", lhs, rhs);1841 FuncGen_indent(&fg, out);
1552 }1842 fprintf(out, "l%" PRIu32 " = %s(l%" PRIu32 ", l%" PRIu32 ");\n",
1553 break;1843 lhs, function, lhs, rhs);
1554 case WasmOpcode_f32_ne:
1555 if (unreachable_depth == 0) {
1556 uint32_t rhs = FuncGen_stackPop(&fg);
1557 uint32_t lhs = FuncGen_stackPop(&fg);
1558 FuncGen_stackPush(&fg, out, WasmValType_i32);
1559 fprintf(out, "l%" PRIu32 " != l%" PRIu32 ";\n", lhs, rhs);
1560 }
1561 break;
1562 case WasmOpcode_f32_lt:
1563 if (unreachable_depth == 0) {
1564 uint32_t rhs = FuncGen_stackPop(&fg);
1565 uint32_t lhs = FuncGen_stackPop(&fg);
1566 FuncGen_stackPush(&fg, out, WasmValType_i32);
1567 fprintf(out, "l%" PRIu32 " < l%" PRIu32 ";\n", lhs, rhs);
1568 }
1569 break;
1570 case WasmOpcode_f32_gt:
1571 if (unreachable_depth == 0) {
1572 uint32_t rhs = FuncGen_stackPop(&fg);
1573 uint32_t lhs = FuncGen_stackPop(&fg);
1574 FuncGen_stackPush(&fg, out, WasmValType_i32);
1575 fprintf(out, "l%" PRIu32 " > l%" PRIu32 ";\n", lhs, rhs);
1576 }
1577 break;
1578 case WasmOpcode_f32_le:
1579 if (unreachable_depth == 0) {
1580 uint32_t rhs = FuncGen_stackPop(&fg);
1581 uint32_t lhs = FuncGen_stackPop(&fg);
1582 FuncGen_stackPush(&fg, out, WasmValType_i32);
1583 fprintf(out, "l%" PRIu32 " <= l%" PRIu32 ";\n", lhs, rhs);
1584 }
1585 break;
1586 case WasmOpcode_f32_ge:
1587 if (unreachable_depth == 0) {
1588 uint32_t rhs = FuncGen_stackPop(&fg);
1589 uint32_t lhs = FuncGen_stackPop(&fg);
1590 FuncGen_stackPush(&fg, out, WasmValType_i32);
1591 fprintf(out, "l%" PRIu32 " >= l%" PRIu32 ";\n", lhs, rhs);
1592 }
1593 break;
1594
1595 case WasmOpcode_f64_eq:
1596 if (unreachable_depth == 0) {
1597 uint32_t rhs = FuncGen_stackPop(&fg);
1598 uint32_t lhs = FuncGen_stackPop(&fg);
1599 FuncGen_stackPush(&fg, out, WasmValType_i32);
1600 fprintf(out, "l%" PRIu32 " == l%" PRIu32 ";\n", lhs, rhs);
1601 }
1602 break;
1603 case WasmOpcode_f64_ne:
1604 if (unreachable_depth == 0) {
1605 uint32_t rhs = FuncGen_stackPop(&fg);
1606 uint32_t lhs = FuncGen_stackPop(&fg);
1607 FuncGen_stackPush(&fg, out, WasmValType_i32);
1608 fprintf(out, "l%" PRIu32 " != l%" PRIu32 ";\n", lhs, rhs);
1609 }
1610 break;
1611 case WasmOpcode_f64_lt:
1612 if (unreachable_depth == 0) {
1613 uint32_t rhs = FuncGen_stackPop(&fg);
1614 uint32_t lhs = FuncGen_stackPop(&fg);
1615 FuncGen_stackPush(&fg, out, WasmValType_i32);
1616 fprintf(out, "l%" PRIu32 " < l%" PRIu32 ";\n", lhs, rhs);
1617 }
1618 break;
1619 case WasmOpcode_f64_gt:
1620 if (unreachable_depth == 0) {
1621 uint32_t rhs = FuncGen_stackPop(&fg);
1622 uint32_t lhs = FuncGen_stackPop(&fg);
1623 FuncGen_stackPush(&fg, out, WasmValType_i32);
1624 fprintf(out, "l%" PRIu32 " > l%" PRIu32 ";\n", lhs, rhs);
1625 }
1626 break;
1627 case WasmOpcode_f64_le:
1628 if (unreachable_depth == 0) {
1629 uint32_t rhs = FuncGen_stackPop(&fg);
1630 uint32_t lhs = FuncGen_stackPop(&fg);
1631 FuncGen_stackPush(&fg, out, WasmValType_i32);
1632 fprintf(out, "l%" PRIu32 " <= l%" PRIu32 ";\n", lhs, rhs);
1633 }
1634 break;
1635 case WasmOpcode_f64_ge:
1636 if (unreachable_depth == 0) {
1637 uint32_t rhs = FuncGen_stackPop(&fg);
1638 uint32_t lhs = FuncGen_stackPop(&fg);
1639 FuncGen_stackPush(&fg, out, WasmValType_i32);
1640 fprintf(out, "l%" PRIu32 " >= l%" PRIu32 ";\n", lhs, rhs);
1641 }
1642 break;
1643
1644 case WasmOpcode_i32_clz:
1645 if (unreachable_depth == 0) {
1646 uint32_t lhs = FuncGen_stackPop(&fg);
1647 FuncGen_stackPush(&fg, out, WasmValType_i32);
1648 fprintf(out, "l%" PRIu32 " != 0 ? __builtin_clz(l%" PRIu32 ") : 32;\n",
1649 lhs, lhs);
1650 }
1651 break;
1652 case WasmOpcode_i32_ctz:
1653 if (unreachable_depth == 0) {
1654 uint32_t lhs = FuncGen_stackPop(&fg);
1655 FuncGen_stackPush(&fg, out, WasmValType_i32);
1656 fprintf(out, "l%" PRIu32 " != 0 ? __builtin_ctz(l%" PRIu32 ") : 32;\n",
1657 lhs, lhs);
1658 }
1659 break;
1660 case WasmOpcode_i32_popcnt:
1661 if (unreachable_depth == 0) {
1662 uint32_t lhs = FuncGen_stackPop(&fg);
1663 FuncGen_stackPush(&fg, out, WasmValType_i32);
1664 fprintf(out, "__builtin_popcount(l%" PRIu32 ");\n", lhs);
1665 }
1666 break;
1667 case WasmOpcode_i32_add:
1668 if (unreachable_depth == 0) {
1669 uint32_t rhs = FuncGen_stackPop(&fg);
1670 uint32_t lhs = FuncGen_stackPop(&fg);
1671 FuncGen_stackPush(&fg, out, WasmValType_i32);
1672 fprintf(out, "l%" PRIu32 " + l%" PRIu32 ";\n", lhs, rhs);
1673 }
1674 break;
1675 case WasmOpcode_i32_sub:
1676 if (unreachable_depth == 0) {
1677 uint32_t rhs = FuncGen_stackPop(&fg);
1678 uint32_t lhs = FuncGen_stackPop(&fg);
1679 FuncGen_stackPush(&fg, out, WasmValType_i32);
1680 fprintf(out, "l%" PRIu32 " - l%" PRIu32 ";\n", lhs, rhs);
1681 }
1682 break;
1683 case WasmOpcode_i32_mul:
1684 if (unreachable_depth == 0) {
1685 uint32_t rhs = FuncGen_stackPop(&fg);
1686 uint32_t lhs = FuncGen_stackPop(&fg);
1687 FuncGen_stackPush(&fg, out, WasmValType_i32);
1688 fprintf(out, "l%" PRIu32 " * l%" PRIu32 ";\n", lhs, rhs);
1689 }
1690 break;
1691 case WasmOpcode_i32_div_s:
1692 if (unreachable_depth == 0) {
1693 uint32_t rhs = FuncGen_stackPop(&fg);
1694 uint32_t lhs = FuncGen_stackPop(&fg);
1695 FuncGen_stackPush(&fg, out, WasmValType_i32);
1696 fprintf(out, "(int32_t)l%" PRIu32 " / (int32_t)l%" PRIu32 ";\n", lhs, rhs);
1697 }
1698 break;
1699 case WasmOpcode_i32_div_u:
1700 if (unreachable_depth == 0) {
1701 uint32_t rhs = FuncGen_stackPop(&fg);
1702 uint32_t lhs = FuncGen_stackPop(&fg);
1703 FuncGen_stackPush(&fg, out, WasmValType_i32);
1704 fprintf(out, "l%" PRIu32 " / l%" PRIu32 ";\n", lhs, rhs);
1705 }
1706 break;
1707 case WasmOpcode_i32_rem_s:
1708 if (unreachable_depth == 0) {
1709 uint32_t rhs = FuncGen_stackPop(&fg);
1710 uint32_t lhs = FuncGen_stackPop(&fg);
1711 FuncGen_stackPush(&fg, out, WasmValType_i32);
1712 fprintf(out, "(int32_t)l%" PRIu32 " %% (int32_t)l%" PRIu32 ";\n", lhs, rhs);
1713 }
1714 break;
1715 case WasmOpcode_i32_rem_u:
1716 if (unreachable_depth == 0) {
1717 uint32_t rhs = FuncGen_stackPop(&fg);
1718 uint32_t lhs = FuncGen_stackPop(&fg);
1719 FuncGen_stackPush(&fg, out, WasmValType_i32);
1720 fprintf(out, "l%" PRIu32 " %% l%" PRIu32 ";\n", lhs, rhs);
1721 }
1722 break;
1723 case WasmOpcode_i32_and:
1724 if (unreachable_depth == 0) {
1725 uint32_t rhs = FuncGen_stackPop(&fg);
1726 uint32_t lhs = FuncGen_stackPop(&fg);
1727 FuncGen_stackPush(&fg, out, WasmValType_i32);
1728 fprintf(out, "l%" PRIu32 " & l%" PRIu32 ";\n", lhs, rhs);
1729 }
1730 break;
1731 case WasmOpcode_i32_or:
1732 if (unreachable_depth == 0) {
1733 uint32_t rhs = FuncGen_stackPop(&fg);
1734 uint32_t lhs = FuncGen_stackPop(&fg);
1735 FuncGen_stackPush(&fg, out, WasmValType_i32);
1736 fprintf(out, "l%" PRIu32 " | l%" PRIu32 ";\n", lhs, rhs);
1737 }
1738 break;
1739 case WasmOpcode_i32_xor:
1740 if (unreachable_depth == 0) {
1741 uint32_t rhs = FuncGen_stackPop(&fg);
1742 uint32_t lhs = FuncGen_stackPop(&fg);
1743 FuncGen_stackPush(&fg, out, WasmValType_i32);
1744 fprintf(out, "l%" PRIu32 " ^ l%" PRIu32 ";\n", lhs, rhs);
1745 }
1746 break;
1747 case WasmOpcode_i32_shl:
1748 if (unreachable_depth == 0) {
1749 uint32_t rhs = FuncGen_stackPop(&fg);
1750 uint32_t lhs = FuncGen_stackPop(&fg);
1751 FuncGen_stackPush(&fg, out, WasmValType_i32);
1752 fprintf(out, "l%" PRIu32 " << (l%" PRIu32 " & 0x1F);\n", lhs, rhs);
1753 }
1754 break;
1755 case WasmOpcode_i32_shr_s:
1756 if (unreachable_depth == 0) {
1757 uint32_t rhs = FuncGen_stackPop(&fg);
1758 uint32_t lhs = FuncGen_stackPop(&fg);
1759 FuncGen_stackPush(&fg, out, WasmValType_i32);
1760 fprintf(out, "(int32_t)l%" PRIu32 " >> (l%" PRIu32 " & 0x1F);\n", lhs, rhs);
1761 }
1762 break;
1763 case WasmOpcode_i32_shr_u:
1764 if (unreachable_depth == 0) {
1765 uint32_t rhs = FuncGen_stackPop(&fg);
1766 uint32_t lhs = FuncGen_stackPop(&fg);
1767 FuncGen_stackPush(&fg, out, WasmValType_i32);
1768 fprintf(out, "l%" PRIu32 " >> (l%" PRIu32 " & 0x1F);\n", lhs, rhs);
1769 }
1770 break;
1771 case WasmOpcode_i32_rotl:
1772 if (unreachable_depth == 0) {
1773 uint32_t rhs = FuncGen_stackPop(&fg);
1774 uint32_t lhs = FuncGen_stackPop(&fg);
1775 FuncGen_stackPush(&fg, out, WasmValType_i32);
1776 fprintf(out, "l%" PRIu32 " << (l%" PRIu32 " & 0x1F) | "
1777 "l%" PRIu32 " >> (-l%" PRIu32" & 0x1F);\n", lhs, rhs, lhs, rhs);
1778 }
1779 break;
1780 case WasmOpcode_i32_rotr:
1781 if (unreachable_depth == 0) {
1782 uint32_t rhs = FuncGen_stackPop(&fg);
1783 uint32_t lhs = FuncGen_stackPop(&fg);
1784 FuncGen_stackPush(&fg, out, WasmValType_i32);
1785 fprintf(out, "l%" PRIu32 " >> (l%" PRIu32 " & 0x1F) | "
1786 "l%" PRIu32 " << (-l%" PRIu32" & 0x1F);\n", lhs, rhs, lhs, rhs);
1787 }
1788 break;
1789
1790 case WasmOpcode_i64_clz:
1791 if (unreachable_depth == 0) {
1792 uint32_t lhs = FuncGen_stackPop(&fg);
1793 FuncGen_stackPush(&fg, out, WasmValType_i64);
1794 fprintf(out, "l%" PRIu32 " != 0 ? __builtin_clzll(l%" PRIu32 ") : 64;\n",
1795 lhs, lhs);
1796 }
1797 break;
1798 case WasmOpcode_i64_ctz:
1799 if (unreachable_depth == 0) {
1800 uint32_t lhs = FuncGen_stackPop(&fg);
1801 FuncGen_stackPush(&fg, out, WasmValType_i64);
1802 fprintf(out, "l%" PRIu32 " != 0 ? __builtin_ctzll(l%" PRIu32 ") : 64;\n",
1803 lhs, lhs);
1804 }
1805 break;
1806 case WasmOpcode_i64_popcnt:
1807 if (unreachable_depth == 0) {
1808 uint32_t lhs = FuncGen_stackPop(&fg);
1809 FuncGen_stackPush(&fg, out, WasmValType_i64);
1810 fprintf(out, "__builtin_popcountll(l%" PRIu32 ");\n", lhs);
1811 }
1812 break;
1813 case WasmOpcode_i64_add:
1814 if (unreachable_depth == 0) {
1815 uint32_t rhs = FuncGen_stackPop(&fg);
1816 uint32_t lhs = FuncGen_stackPop(&fg);
1817 FuncGen_stackPush(&fg, out, WasmValType_i64);
1818 fprintf(out, "l%" PRIu32 " + l%" PRIu32 ";\n", lhs, rhs);
1819 }
1820 break;
1821 case WasmOpcode_i64_sub:
1822 if (unreachable_depth == 0) {
1823 uint32_t rhs = FuncGen_stackPop(&fg);
1824 uint32_t lhs = FuncGen_stackPop(&fg);
1825 FuncGen_stackPush(&fg, out, WasmValType_i64);
1826 fprintf(out, "l%" PRIu32 " - l%" PRIu32 ";\n", lhs, rhs);
1827 }
1828 break;
1829 case WasmOpcode_i64_mul:
1830 if (unreachable_depth == 0) {
1831 uint32_t rhs = FuncGen_stackPop(&fg);
1832 uint32_t lhs = FuncGen_stackPop(&fg);
1833 FuncGen_stackPush(&fg, out, WasmValType_i64);
1834 fprintf(out, "l%" PRIu32 " * l%" PRIu32 ";\n", lhs, rhs);
1835 }
1836 break;
1837 case WasmOpcode_i64_div_s:
1838 if (unreachable_depth == 0) {
1839 uint32_t rhs = FuncGen_stackPop(&fg);
1840 uint32_t lhs = FuncGen_stackPop(&fg);
1841 FuncGen_stackPush(&fg, out, WasmValType_i64);
1842 fprintf(out, "(int64_t)l%" PRIu32 " / (int64_t)l%" PRIu32 ";\n", lhs, rhs);
1843 }
1844 break;
1845 case WasmOpcode_i64_div_u:
1846 if (unreachable_depth == 0) {
1847 uint32_t rhs = FuncGen_stackPop(&fg);
1848 uint32_t lhs = FuncGen_stackPop(&fg);
1849 FuncGen_stackPush(&fg, out, WasmValType_i64);
1850 fprintf(out, "l%" PRIu32 " / l%" PRIu32 ";\n", lhs, rhs);
1851 }
1852 break;
1853 case WasmOpcode_i64_rem_s:
1854 if (unreachable_depth == 0) {
1855 uint32_t rhs = FuncGen_stackPop(&fg);
1856 uint32_t lhs = FuncGen_stackPop(&fg);
1857 FuncGen_stackPush(&fg, out, WasmValType_i64);
1858 fprintf(out, "(int64_t)l%" PRIu32 " %% (int64_t)l%" PRIu32 ";\n", lhs, rhs);
1859 }
1860 break;
1861 case WasmOpcode_i64_rem_u:
1862 if (unreachable_depth == 0) {
1863 uint32_t rhs = FuncGen_stackPop(&fg);
1864 uint32_t lhs = FuncGen_stackPop(&fg);
1865 FuncGen_stackPush(&fg, out, WasmValType_i64);
1866 fprintf(out, "l%" PRIu32 " %% l%" PRIu32 ";\n", lhs, rhs);
1867 }
1868 break;
1869 case WasmOpcode_i64_and:
1870 if (unreachable_depth == 0) {
1871 uint32_t rhs = FuncGen_stackPop(&fg);
1872 uint32_t lhs = FuncGen_stackPop(&fg);
1873 FuncGen_stackPush(&fg, out, WasmValType_i64);
1874 fprintf(out, "l%" PRIu32 " & l%" PRIu32 ";\n", lhs, rhs);
1875 }
1876 break;
1877 case WasmOpcode_i64_or:
1878 if (unreachable_depth == 0) {
1879 uint32_t rhs = FuncGen_stackPop(&fg);
1880 uint32_t lhs = FuncGen_stackPop(&fg);
1881 FuncGen_stackPush(&fg, out, WasmValType_i64);
1882 fprintf(out, "l%" PRIu32 " | l%" PRIu32 ";\n", lhs, rhs);
1883 }
1884 break;
1885 case WasmOpcode_i64_xor:
1886 if (unreachable_depth == 0) {
1887 uint32_t rhs = FuncGen_stackPop(&fg);
1888 uint32_t lhs = FuncGen_stackPop(&fg);
1889 FuncGen_stackPush(&fg, out, WasmValType_i64);
1890 fprintf(out, "l%" PRIu32 " ^ l%" PRIu32 ";\n", lhs, rhs);
1891 }
1892 break;
1893 case WasmOpcode_i64_shl:
1894 if (unreachable_depth == 0) {
1895 uint32_t rhs = FuncGen_stackPop(&fg);
1896 uint32_t lhs = FuncGen_stackPop(&fg);
1897 FuncGen_stackPush(&fg, out, WasmValType_i64);
1898 fprintf(out, "l%" PRIu32 " << (l%" PRIu32 " & 0x3F);\n", lhs, rhs);
1899 }
1900 break;
1901 case WasmOpcode_i64_shr_s:
1902 if (unreachable_depth == 0) {
1903 uint32_t rhs = FuncGen_stackPop(&fg);
1904 uint32_t lhs = FuncGen_stackPop(&fg);
1905 FuncGen_stackPush(&fg, out, WasmValType_i64);
1906 fprintf(out, "(int64_t)l%" PRIu32 " >> (l%" PRIu32 " & 0x3F);\n", lhs, rhs);
1907 }
1908 break;
1909 case WasmOpcode_i64_shr_u:
1910 if (unreachable_depth == 0) {
1911 uint32_t rhs = FuncGen_stackPop(&fg);
1912 uint32_t lhs = FuncGen_stackPop(&fg);
1913 FuncGen_stackPush(&fg, out, WasmValType_i64);
1914 fprintf(out, "l%" PRIu32 " >> (l%" PRIu32 " & 0x3F);\n", lhs, rhs);
1915 }
1916 break;
1917 case WasmOpcode_i64_rotl:
1918 if (unreachable_depth == 0) {
1919 uint32_t rhs = FuncGen_stackPop(&fg);
1920 uint32_t lhs = FuncGen_stackPop(&fg);
1921 FuncGen_stackPush(&fg, out, WasmValType_i64);
1922 fprintf(out, "l%" PRIu32 " << (l%" PRIu32 " & 0x3F) | "
1923 "l%" PRIu32 " >> (-l%" PRIu32" & 0x3F);\n", lhs, rhs, lhs, rhs);
1924 }
1925 break;
1926 case WasmOpcode_i64_rotr:
1927 if (unreachable_depth == 0) {
1928 uint32_t rhs = FuncGen_stackPop(&fg);
1929 uint32_t lhs = FuncGen_stackPop(&fg);
1930 FuncGen_stackPush(&fg, out, WasmValType_i64);
1931 fprintf(out, "l%" PRIu32 " >> (l%" PRIu32 " & 0x3F) | "
1932 "l%" PRIu32 " << (-l%" PRIu32" & 0x3F);\n", lhs, rhs, lhs, rhs);
1933 }
1934 break;
1935
1936 case WasmOpcode_f32_abs:
1937 if (unreachable_depth == 0) {
1938 uint32_t lhs = FuncGen_stackPop(&fg);
1939 FuncGen_stackPush(&fg, out, WasmValType_f32);
1940 fprintf(out, "fabsf(l%" PRIu32 ");\n", lhs);
1941 }
1942 break;
1943 case WasmOpcode_f32_neg:
1944 if (unreachable_depth == 0) {
1945 uint32_t lhs = FuncGen_stackPop(&fg);
1946 FuncGen_stackPush(&fg, out, WasmValType_f32);
1947 fprintf(out, "-l%" PRIu32 ";\n", lhs);
1948 }
1949 break;
1950 case WasmOpcode_f32_ceil:
1951 if (unreachable_depth == 0) {
1952 uint32_t lhs = FuncGen_stackPop(&fg);
1953 FuncGen_stackPush(&fg, out, WasmValType_f32);
1954 fprintf(out, "ceilf(l%" PRIu32 ");\n", lhs);
1955 }
1956 break;
1957 case WasmOpcode_f32_floor:
1958 if (unreachable_depth == 0) {
1959 uint32_t lhs = FuncGen_stackPop(&fg);
1960 FuncGen_stackPush(&fg, out, WasmValType_f32);
1961 fprintf(out, "floorf(l%" PRIu32 ");\n", lhs);
1962 }
1963 break;
1964 case WasmOpcode_f32_trunc:
1965 if (unreachable_depth == 0) {
1966 uint32_t lhs = FuncGen_stackPop(&fg);
1967 FuncGen_stackPush(&fg, out, WasmValType_f32);
1968 fprintf(out, "truncf(l%" PRIu32 ");\n", lhs);
1969 }
1970 break;
1971 case WasmOpcode_f32_nearest:
1972 if (unreachable_depth == 0) {
1973 uint32_t lhs = FuncGen_stackPop(&fg);
1974 FuncGen_stackPush(&fg, out, WasmValType_f32);
1975 fprintf(out, "roundf(l%" PRIu32 ");\n", lhs);
1976 }
1977 break;
1978 case WasmOpcode_f32_sqrt:
1979 if (unreachable_depth == 0) {
1980 uint32_t lhs = FuncGen_stackPop(&fg);
1981 FuncGen_stackPush(&fg, out, WasmValType_f32);
1982 fprintf(out, "sqrtf(l%" PRIu32 ");\n", lhs);
1983 }
1984 break;
1985 case WasmOpcode_f32_add:
1986 if (unreachable_depth == 0) {
1987 uint32_t rhs = FuncGen_stackPop(&fg);
1988 uint32_t lhs = FuncGen_stackPop(&fg);
1989 FuncGen_stackPush(&fg, out, WasmValType_f32);
1990 fprintf(out, "l%" PRIu32 " + l%" PRIu32 ";\n", lhs, rhs);
1991 }
1992 break;
1993 case WasmOpcode_f32_sub:
1994 if (unreachable_depth == 0) {
1995 uint32_t rhs = FuncGen_stackPop(&fg);
1996 uint32_t lhs = FuncGen_stackPop(&fg);
1997 FuncGen_stackPush(&fg, out, WasmValType_f32);
1998 fprintf(out, "l%" PRIu32 " - l%" PRIu32 ";\n", lhs, rhs);
1999 }
2000 break;
2001 case WasmOpcode_f32_mul:
2002 if (unreachable_depth == 0) {
2003 uint32_t rhs = FuncGen_stackPop(&fg);
2004 uint32_t lhs = FuncGen_stackPop(&fg);
2005 FuncGen_stackPush(&fg, out, WasmValType_f32);
2006 fprintf(out, "l%" PRIu32 " * l%" PRIu32 ";\n", lhs, rhs);
2007 }
2008 break;
2009 case WasmOpcode_f32_div:
2010 if (unreachable_depth == 0) {
2011 uint32_t rhs = FuncGen_stackPop(&fg);
2012 uint32_t lhs = FuncGen_stackPop(&fg);
2013 FuncGen_stackPush(&fg, out, WasmValType_f32);
2014 fprintf(out, "l%" PRIu32 " / l%" PRIu32 ";\n", lhs, rhs);
2015 }
2016 break;
2017 case WasmOpcode_f32_min:
2018 if (unreachable_depth == 0) {
2019 uint32_t rhs = FuncGen_stackPop(&fg);
2020 uint32_t lhs = FuncGen_stackPop(&fg);
2021 FuncGen_stackPush(&fg, out, WasmValType_f32);
2022 fprintf(out, "fminf(l%" PRIu32 ", l%" PRIu32 ");\n", lhs, rhs);
2023 }
2024 break;
2025 case WasmOpcode_f32_max:
2026 if (unreachable_depth == 0) {
2027 uint32_t rhs = FuncGen_stackPop(&fg);
2028 uint32_t lhs = FuncGen_stackPop(&fg);
2029 FuncGen_stackPush(&fg, out, WasmValType_f32);
2030 fprintf(out, "fmaxf(l%" PRIu32 ", l%" PRIu32 ");\n", lhs, rhs);
2031 }
2032 break;
2033 case WasmOpcode_f32_copysign:
2034 if (unreachable_depth == 0) {
2035 uint32_t rhs = FuncGen_stackPop(&fg);
2036 uint32_t lhs = FuncGen_stackPop(&fg);
2037 FuncGen_stackPush(&fg, out, WasmValType_f32);
2038 fprintf(out, "copysignf(l%" PRIu32 ", l%" PRIu32 ");\n", lhs, rhs);
2039 }
2040 break;
2041
2042 case WasmOpcode_f64_abs:
2043 if (unreachable_depth == 0) {
2044 uint32_t lhs = FuncGen_stackPop(&fg);
2045 FuncGen_stackPush(&fg, out, WasmValType_f64);
2046 fprintf(out, "fabs(l%" PRIu32 ");\n", lhs);
2047 }
2048 break;
2049 case WasmOpcode_f64_neg:
2050 if (unreachable_depth == 0) {
2051 uint32_t lhs = FuncGen_stackPop(&fg);
2052 FuncGen_stackPush(&fg, out, WasmValType_f64);
2053 fprintf(out, "-l%" PRIu32 ";\n", lhs);
2054 }
2055 break;
2056 case WasmOpcode_f64_ceil:
2057 if (unreachable_depth == 0) {
2058 uint32_t lhs = FuncGen_stackPop(&fg);
2059 FuncGen_stackPush(&fg, out, WasmValType_f64);
2060 fprintf(out, "ceil(l%" PRIu32 ");\n", lhs);
2061 }
2062 break;
2063 case WasmOpcode_f64_floor:
2064 if (unreachable_depth == 0) {
2065 uint32_t lhs = FuncGen_stackPop(&fg);
2066 FuncGen_stackPush(&fg, out, WasmValType_f64);
2067 fprintf(out, "floor(l%" PRIu32 ");\n", lhs);
2068 }
2069 break;
2070 case WasmOpcode_f64_trunc:
2071 if (unreachable_depth == 0) {
2072 uint32_t lhs = FuncGen_stackPop(&fg);
2073 FuncGen_stackPush(&fg, out, WasmValType_f64);
2074 fprintf(out, "trunc(l%" PRIu32 ");\n", lhs);
2075 }
2076 break;
2077 case WasmOpcode_f64_nearest:
2078 if (unreachable_depth == 0) {
2079 uint32_t lhs = FuncGen_stackPop(&fg);
2080 FuncGen_stackPush(&fg, out, WasmValType_f64);
2081 fprintf(out, "round(l%" PRIu32 ");\n", lhs);
2082 }
2083 break;
2084 case WasmOpcode_f64_sqrt:
2085 if (unreachable_depth == 0) {
2086 uint32_t lhs = FuncGen_stackPop(&fg);
2087 FuncGen_stackPush(&fg, out, WasmValType_f64);
2088 fprintf(out, "sqrt(l%" PRIu32 ");\n", lhs);
2089 }
2090 break;
2091 case WasmOpcode_f64_add:
2092 if (unreachable_depth == 0) {
2093 uint32_t rhs = FuncGen_stackPop(&fg);
2094 uint32_t lhs = FuncGen_stackPop(&fg);
2095 FuncGen_stackPush(&fg, out, WasmValType_f64);
2096 fprintf(out, "l%" PRIu32 " + l%" PRIu32 ";\n", lhs, rhs);
2097 }
2098 break;
2099 case WasmOpcode_f64_sub:
2100 if (unreachable_depth == 0) {
2101 uint32_t rhs = FuncGen_stackPop(&fg);
2102 uint32_t lhs = FuncGen_stackPop(&fg);
2103 FuncGen_stackPush(&fg, out, WasmValType_f64);
2104 fprintf(out, "l%" PRIu32 " - l%" PRIu32 ";\n", lhs, rhs);
2105 }
2106 break;
2107 case WasmOpcode_f64_mul:
2108 if (unreachable_depth == 0) {
2109 uint32_t rhs = FuncGen_stackPop(&fg);
2110 uint32_t lhs = FuncGen_stackPop(&fg);
2111 FuncGen_stackPush(&fg, out, WasmValType_f64);
2112 fprintf(out, "l%" PRIu32 " * l%" PRIu32 ";\n", lhs, rhs);
2113 }
2114 break;
2115 case WasmOpcode_f64_div:
2116 if (unreachable_depth == 0) {
2117 uint32_t rhs = FuncGen_stackPop(&fg);
2118 uint32_t lhs = FuncGen_stackPop(&fg);
2119 FuncGen_stackPush(&fg, out, WasmValType_f64);
2120 fprintf(out, "l%" PRIu32 " / l%" PRIu32 ";\n", lhs, rhs);
2121 }
2122 break;
2123 case WasmOpcode_f64_min:
2124 if (unreachable_depth == 0) {
2125 uint32_t rhs = FuncGen_stackPop(&fg);
2126 uint32_t lhs = FuncGen_stackPop(&fg);
2127 FuncGen_stackPush(&fg, out, WasmValType_f64);
2128 fprintf(out, "fmin(l%" PRIu32 ", l%" PRIu32 ");\n", lhs, rhs);
2129 }
2130 break;
2131 case WasmOpcode_f64_max:
2132 if (unreachable_depth == 0) {
2133 uint32_t rhs = FuncGen_stackPop(&fg);
2134 uint32_t lhs = FuncGen_stackPop(&fg);
2135 FuncGen_stackPush(&fg, out, WasmValType_f64);
2136 fprintf(out, "fmax(l%" PRIu32 ", l%" PRIu32 ");\n", lhs, rhs);
2137 }
2138 break;
2139 case WasmOpcode_f64_copysign:
2140 if (unreachable_depth == 0) {
2141 uint32_t rhs = FuncGen_stackPop(&fg);
2142 uint32_t lhs = FuncGen_stackPop(&fg);
2143 FuncGen_stackPush(&fg, out, WasmValType_f64);
2144 fprintf(out, "copysign(l%" PRIu32 ", l%" PRIu32 ");\n", lhs, rhs);
2145 }1844 }
2146 break;1845 break;
21471846