OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <stdint.h> | 5 #include <stdint.h> |
6 #include <stdlib.h> | 6 #include <stdlib.h> |
7 #include <string.h> | 7 #include <string.h> |
8 | 8 |
9 #include "src/wasm/wasm-macro-gen.h" | 9 #include "src/wasm/wasm-macro-gen.h" |
10 | 10 |
11 #include "test/cctest/cctest.h" | 11 #include "test/cctest/cctest.h" |
12 #include "test/cctest/compiler/value-helper.h" | 12 #include "test/cctest/compiler/value-helper.h" |
13 #include "test/cctest/wasm/test-signatures.h" | 13 #include "test/cctest/wasm/test-signatures.h" |
14 #include "test/cctest/wasm/wasm-run-utils.h" | 14 #include "test/cctest/wasm/wasm-run-utils.h" |
15 | 15 |
| 16 #define CHECK_TRAP32(x) \ |
| 17 CHECK_EQ(0xdeadbeef, (bit_cast<uint32_t>(x)) & 0xFFFFFFFF) |
| 18 #define CHECK_TRAP64(x) \ |
| 19 CHECK_EQ(0xdeadbeefdeadbeef, (bit_cast<uint64_t>(x)) & 0xFFFFFFFFFFFFFFFF) |
| 20 #define CHECK_TRAP(x) CHECK_TRAP32(x) |
| 21 |
| 22 #define asi64(x) static_cast<int64_t>(x) |
| 23 |
| 24 #define asu64(x) static_cast<uint64_t>(x) |
| 25 |
16 #define B2(a, b) kExprBlock, 2, a, b | 26 #define B2(a, b) kExprBlock, 2, a, b |
17 #define B1(a) kExprBlock, 1, a | 27 #define B1(a) kExprBlock, 1, a |
18 | 28 |
19 // Can't bridge macro land with nested macros. | 29 // Can't bridge macro land with nested macros. |
20 #if V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_X87 | 30 #if V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_X87 |
21 #define MIPS_OR_X87 true | 31 #define MIPS_OR_X87 true |
22 #else | 32 #else |
23 #define MIPS_OR_X87 false | 33 #define MIPS_OR_X87 false |
24 #endif | 34 #endif |
25 | 35 |
26 #if V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_X87 || V8_TARGET_ARCH_ARM | 36 #if V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_X87 || V8_TARGET_ARCH_ARM |
27 #define MIPS_OR_ARM_OR_X87 true | 37 #define MIPS_OR_ARM_OR_X87 true |
28 #else | 38 #else |
29 #define MIPS_OR_ARM_OR_X87 false | 39 #define MIPS_OR_ARM_OR_X87 false |
30 #endif | 40 #endif |
31 | 41 |
32 #define FOREACH_I64_OPERATOR(V) \ | 42 #define FOREACH_I64_OPERATOR(V) \ |
33 V(DepthFirst, true) \ | 43 V(DepthFirst, true) \ |
34 V(I64Const, true) \ | 44 V(I64Const, true) \ |
35 V(I64Return, true) \ | 45 V(I64Return, true) \ |
36 V(I64Param, true) \ | 46 V(I64Param, true) \ |
37 V(I64LoadStore, true) \ | 47 V(I64LoadStore, true) \ |
38 V(I64Add, true) \ | 48 V(I64Add, true) \ |
39 V(I64Sub, false) \ | 49 V(I64Sub, false) \ |
40 V(I64Mul, false) \ | 50 V(I64Mul, false) \ |
41 V(I64DivS, false) \ | 51 V(I64DivS, true) \ |
42 V(I64DivU, false) \ | 52 V(I64DivU, true) \ |
43 V(I64RemS, false) \ | 53 V(I64RemS, true) \ |
44 V(I64RemU, false) \ | 54 V(I64RemU, true) \ |
45 V(I64And, true) \ | 55 V(I64And, true) \ |
46 V(I64Ior, true) \ | 56 V(I64Ior, true) \ |
47 V(I64Xor, true) \ | 57 V(I64Xor, true) \ |
48 V(I64Shl, !MIPS_OR_X87) \ | 58 V(I64Shl, !MIPS_OR_X87) \ |
49 V(I64ShrU, !MIPS_OR_ARM_OR_X87) \ | 59 V(I64ShrU, !MIPS_OR_ARM_OR_X87) \ |
50 V(I64ShrS, !MIPS_OR_ARM_OR_X87) \ | 60 V(I64ShrS, !MIPS_OR_ARM_OR_X87) \ |
51 V(I64Eq, true) \ | 61 V(I64Eq, true) \ |
52 V(I64Ne, true) \ | 62 V(I64Ne, true) \ |
53 V(I64LtS, true) \ | 63 V(I64LtS, true) \ |
54 V(I64LeS, true) \ | 64 V(I64LeS, true) \ |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
122 REQUIRE(I64Add); | 132 REQUIRE(I64Add); |
123 WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64()); | 133 WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64()); |
124 BUILD(r, WASM_I64_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); | 134 BUILD(r, WASM_I64_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); |
125 FOR_INT64_INPUTS(i) { | 135 FOR_INT64_INPUTS(i) { |
126 FOR_INT64_INPUTS(j) { CHECK_EQ(*i + *j, r.Call(*i, *j)); } | 136 FOR_INT64_INPUTS(j) { CHECK_EQ(*i + *j, r.Call(*i, *j)); } |
127 } | 137 } |
128 } | 138 } |
129 // kExprI64Sub: | 139 // kExprI64Sub: |
130 // kExprI64Mul: | 140 // kExprI64Mul: |
131 // kExprI64DivS: | 141 // kExprI64DivS: |
| 142 |
| 143 TEST(Run_WasmI64DivS) { |
| 144 REQUIRE(I64DivS); |
| 145 WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64()); |
| 146 BUILD(r, WASM_I64_DIVS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); |
| 147 FOR_INT64_INPUTS(i) { |
| 148 FOR_INT64_INPUTS(j) { |
| 149 if (*j == 0) { |
| 150 CHECK_TRAP64(r.Call(*i, *j)); |
| 151 } else if (*j == -1 && *i == std::numeric_limits<int64_t>::min()) { |
| 152 CHECK_TRAP64(r.Call(*i, *j)); |
| 153 } else { |
| 154 CHECK_EQ(*i / *j, r.Call(*i, *j)); |
| 155 } |
| 156 } |
| 157 } |
| 158 } |
| 159 |
| 160 TEST(Run_WasmI64DivS_Trap) { |
| 161 REQUIRE(I64DivS); |
| 162 WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64()); |
| 163 BUILD(r, WASM_I64_DIVS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); |
| 164 CHECK_EQ(0, r.Call(asi64(0), asi64(100))); |
| 165 CHECK_TRAP64(r.Call(asi64(100), asi64(0))); |
| 166 CHECK_TRAP64(r.Call(asi64(-1001), asi64(0))); |
| 167 CHECK_TRAP64(r.Call(std::numeric_limits<int64_t>::min(), asi64(-1))); |
| 168 CHECK_TRAP64(r.Call(std::numeric_limits<int64_t>::min(), asi64(0))); |
| 169 } |
| 170 |
| 171 TEST(Run_WasmI64DivS_Byzero_Const) { |
| 172 REQUIRE(I64DivS); |
| 173 for (int8_t denom = -2; denom < 8; denom++) { |
| 174 WasmRunner<int64_t> r(MachineType::Int64()); |
| 175 BUILD(r, WASM_I64_DIVS(WASM_GET_LOCAL(0), WASM_I64V_1(denom))); |
| 176 for (int64_t val = -7; val < 8; val++) { |
| 177 if (denom == 0) { |
| 178 CHECK_TRAP64(r.Call(val)); |
| 179 } else { |
| 180 CHECK_EQ(val / denom, r.Call(val)); |
| 181 } |
| 182 } |
| 183 } |
| 184 } |
132 // kExprI64DivU: | 185 // kExprI64DivU: |
| 186 |
| 187 TEST(Run_WasmI64DivU) { |
| 188 REQUIRE(I64DivU); |
| 189 WasmRunner<uint64_t> r(MachineType::Uint64(), MachineType::Uint64()); |
| 190 BUILD(r, WASM_I64_DIVU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); |
| 191 FOR_UINT64_INPUTS(i) { |
| 192 FOR_UINT64_INPUTS(j) { |
| 193 if (*j == 0) { |
| 194 CHECK_TRAP64(r.Call(*i, *j)); |
| 195 } else { |
| 196 CHECK_EQ(*i / *j, r.Call(*i, *j)); |
| 197 } |
| 198 } |
| 199 } |
| 200 } |
| 201 |
| 202 TEST(Run_WasmI64DivU_Trap) { |
| 203 REQUIRE(I64DivU); |
| 204 WasmRunner<uint64_t> r(MachineType::Uint64(), MachineType::Uint64()); |
| 205 BUILD(r, WASM_I64_DIVU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); |
| 206 CHECK_EQ(0, r.Call(asu64(0), asu64(100))); |
| 207 CHECK_TRAP64(r.Call(asu64(100), asu64(0))); |
| 208 CHECK_TRAP64(r.Call(asu64(1001), asu64(0))); |
| 209 CHECK_TRAP64(r.Call(std::numeric_limits<uint64_t>::max(), asu64(0))); |
| 210 } |
| 211 |
| 212 TEST(Run_WasmI64DivU_Byzero_Const) { |
| 213 REQUIRE(I64DivU); |
| 214 for (uint64_t denom = 0xfffffffffffffffe; denom < 8; denom++) { |
| 215 WasmRunner<uint64_t> r(MachineType::Uint64()); |
| 216 BUILD(r, WASM_I64_DIVU(WASM_GET_LOCAL(0), WASM_I64V_1(denom))); |
| 217 |
| 218 for (uint64_t val = 0xfffffffffffffff0; val < 8; val++) { |
| 219 if (denom == 0) { |
| 220 CHECK_TRAP64(r.Call(val)); |
| 221 } else { |
| 222 CHECK_EQ(val / denom, r.Call(val)); |
| 223 } |
| 224 } |
| 225 } |
| 226 } |
133 // kExprI64RemS: | 227 // kExprI64RemS: |
| 228 TEST(Run_WasmI64RemS) { |
| 229 REQUIRE(I64RemS); |
| 230 WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64()); |
| 231 BUILD(r, WASM_I64_REMS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); |
| 232 FOR_INT64_INPUTS(i) { |
| 233 FOR_INT64_INPUTS(j) { |
| 234 if (*j == 0) { |
| 235 CHECK_TRAP64(r.Call(*i, *j)); |
| 236 } else { |
| 237 CHECK_EQ(*i % *j, r.Call(*i, *j)); |
| 238 } |
| 239 } |
| 240 } |
| 241 } |
| 242 |
| 243 TEST(Run_WasmI64RemS_Trap) { |
| 244 REQUIRE(I64RemS); |
| 245 WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64()); |
| 246 BUILD(r, WASM_I64_REMS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); |
| 247 CHECK_EQ(33, r.Call(asi64(133), asi64(100))); |
| 248 CHECK_EQ(0, r.Call(std::numeric_limits<int64_t>::min(), asi64(-1))); |
| 249 CHECK_TRAP64(r.Call(asi64(100), asi64(0))); |
| 250 CHECK_TRAP64(r.Call(asi64(-1001), asi64(0))); |
| 251 CHECK_TRAP64(r.Call(std::numeric_limits<int64_t>::min(), asi64(0))); |
| 252 } |
| 253 |
134 // kExprI64RemU: | 254 // kExprI64RemU: |
| 255 TEST(Run_WasmI64RemU) { |
| 256 REQUIRE(I64RemU); |
| 257 WasmRunner<uint64_t> r(MachineType::Uint64(), MachineType::Uint64()); |
| 258 BUILD(r, WASM_I64_REMU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); |
| 259 FOR_UINT64_INPUTS(i) { |
| 260 FOR_UINT64_INPUTS(j) { |
| 261 if (*j == 0) { |
| 262 CHECK_TRAP64(r.Call(*i, *j)); |
| 263 } else { |
| 264 CHECK_EQ(*i % *j, r.Call(*i, *j)); |
| 265 } |
| 266 } |
| 267 } |
| 268 } |
| 269 |
| 270 TEST(Run_Wasm_I64RemU_Trap) { |
| 271 REQUIRE(I64RemU); |
| 272 WasmRunner<uint64_t> r(MachineType::Uint64(), MachineType::Uint64()); |
| 273 BUILD(r, WASM_I64_REMU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); |
| 274 CHECK_EQ(17, r.Call(asu64(217), asu64(100))); |
| 275 CHECK_TRAP64(r.Call(asu64(100), asu64(0))); |
| 276 CHECK_TRAP64(r.Call(asu64(1001), asu64(0))); |
| 277 CHECK_TRAP64(r.Call(std::numeric_limits<uint64_t>::max(), asu64(0))); |
| 278 } |
| 279 |
135 // kExprI64And: | 280 // kExprI64And: |
136 TEST(Run_Wasm_I64And) { | 281 TEST(Run_Wasm_I64And) { |
137 REQUIRE(I64And); | 282 REQUIRE(I64And); |
138 WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64()); | 283 WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64()); |
139 BUILD(r, WASM_I64_AND(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); | 284 BUILD(r, WASM_I64_AND(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); |
140 FOR_INT64_INPUTS(i) { | 285 FOR_INT64_INPUTS(i) { |
141 FOR_INT64_INPUTS(j) { CHECK_EQ((*i) & (*j), r.Call(*i, *j)); } | 286 FOR_INT64_INPUTS(j) { CHECK_EQ((*i) & (*j), r.Call(*i, *j)); } |
142 } | 287 } |
143 } | 288 } |
144 // kExprI64Ior: | 289 // kExprI64Ior: |
(...skipping 871 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1016 | 1161 |
1017 FOR_FLOAT64_INPUTS(i) { | 1162 FOR_FLOAT64_INPUTS(i) { |
1018 if (*i < static_cast<float>(UINT64_MAX) && *i > -1) { | 1163 if (*i < static_cast<float>(UINT64_MAX) && *i > -1) { |
1019 CHECK_EQ(static_cast<uint64_t>(*i), r.Call(*i)); | 1164 CHECK_EQ(static_cast<uint64_t>(*i), r.Call(*i)); |
1020 } else { | 1165 } else { |
1021 CHECK_TRAP64(r.Call(*i)); | 1166 CHECK_TRAP64(r.Call(*i)); |
1022 } | 1167 } |
1023 } | 1168 } |
1024 } | 1169 } |
1025 | 1170 |
1026 #define as64(x) static_cast<int64_t>(x) | |
1027 TEST(Run_WASM_I64DivS_trap) { | |
1028 REQUIRE(I64DivS); | |
1029 WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64()); | |
1030 BUILD(r, WASM_I64_DIVS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); | |
1031 CHECK_EQ(0, r.Call(as64(0), as64(100))); | |
1032 CHECK_TRAP64(r.Call(as64(100), as64(0))); | |
1033 CHECK_TRAP64(r.Call(as64(-1001), as64(0))); | |
1034 CHECK_TRAP64(r.Call(std::numeric_limits<int64_t>::min(), as64(-1))); | |
1035 CHECK_TRAP64(r.Call(std::numeric_limits<int64_t>::min(), as64(0))); | |
1036 } | |
1037 | |
1038 TEST(Run_WASM_I64RemS_trap) { | |
1039 REQUIRE(I64RemS); | |
1040 WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64()); | |
1041 BUILD(r, WASM_I64_REMS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); | |
1042 CHECK_EQ(33, r.Call(as64(133), as64(100))); | |
1043 CHECK_EQ(0, r.Call(std::numeric_limits<int64_t>::min(), as64(-1))); | |
1044 CHECK_TRAP64(r.Call(as64(100), as64(0))); | |
1045 CHECK_TRAP64(r.Call(as64(-1001), as64(0))); | |
1046 CHECK_TRAP64(r.Call(std::numeric_limits<int64_t>::min(), as64(0))); | |
1047 } | |
1048 | |
1049 TEST(Run_WASM_I64DivU_trap) { | |
1050 REQUIRE(I64DivU); | |
1051 WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64()); | |
1052 BUILD(r, WASM_I64_DIVU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); | |
1053 CHECK_EQ(0, r.Call(as64(0), as64(100))); | |
1054 CHECK_EQ(0, r.Call(std::numeric_limits<int64_t>::min(), as64(-1))); | |
1055 CHECK_TRAP64(r.Call(as64(100), as64(0))); | |
1056 CHECK_TRAP64(r.Call(as64(-1001), as64(0))); | |
1057 CHECK_TRAP64(r.Call(std::numeric_limits<int64_t>::min(), as64(0))); | |
1058 } | |
1059 | |
1060 TEST(Run_WASM_I64RemU_trap) { | |
1061 REQUIRE(I64RemU); | |
1062 WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64()); | |
1063 BUILD(r, WASM_I64_REMU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); | |
1064 CHECK_EQ(17, r.Call(as64(217), as64(100))); | |
1065 CHECK_TRAP64(r.Call(as64(100), as64(0))); | |
1066 CHECK_TRAP64(r.Call(as64(-1001), as64(0))); | |
1067 CHECK_TRAP64(r.Call(std::numeric_limits<int64_t>::min(), as64(0))); | |
1068 CHECK_EQ(std::numeric_limits<int64_t>::min(), | |
1069 r.Call(std::numeric_limits<int64_t>::min(), as64(-1))); | |
1070 } | |
1071 | |
1072 TEST(Run_WASM_I64DivS_byzero_const) { | |
1073 REQUIRE(I64DivS); | |
1074 for (int8_t denom = -2; denom < 8; denom++) { | |
1075 WasmRunner<int64_t> r(MachineType::Int64()); | |
1076 BUILD(r, WASM_I64_DIVS(WASM_GET_LOCAL(0), WASM_I64V_1(denom))); | |
1077 for (int64_t val = -7; val < 8; val++) { | |
1078 if (denom == 0) { | |
1079 CHECK_TRAP64(r.Call(val)); | |
1080 } else { | |
1081 CHECK_EQ(val / denom, r.Call(val)); | |
1082 } | |
1083 } | |
1084 } | |
1085 } | |
1086 | |
1087 TEST(Run_WASM_I64DivU_byzero_const) { | |
1088 REQUIRE(I64DivU); | |
1089 for (uint64_t denom = 0xfffffffffffffffe; denom < 8; denom++) { | |
1090 WasmRunner<uint64_t> r(MachineType::Uint64()); | |
1091 BUILD(r, WASM_I64_DIVU(WASM_GET_LOCAL(0), WASM_I64V_1(denom))); | |
1092 | |
1093 for (uint64_t val = 0xfffffffffffffff0; val < 8; val++) { | |
1094 if (denom == 0) { | |
1095 CHECK_TRAP64(r.Call(val)); | |
1096 } else { | |
1097 CHECK_EQ(val / denom, r.Call(val)); | |
1098 } | |
1099 } | |
1100 } | |
1101 } | |
1102 | |
1103 TEST(Run_Wasm_F64ReinterpretI64) { | 1171 TEST(Run_Wasm_F64ReinterpretI64) { |
1104 REQUIRE(F64ReinterpretI64); | 1172 REQUIRE(F64ReinterpretI64); |
1105 TestingModule module; | 1173 TestingModule module; |
1106 int64_t* memory = module.AddMemoryElems<int64_t>(8); | 1174 int64_t* memory = module.AddMemoryElems<int64_t>(8); |
1107 WasmRunner<int64_t> r(&module); | 1175 WasmRunner<int64_t> r(&module); |
1108 | 1176 |
1109 BUILD(r, WASM_I64_REINTERPRET_F64( | 1177 BUILD(r, WASM_I64_REINTERPRET_F64( |
1110 WASM_LOAD_MEM(MachineType::Float64(), WASM_ZERO))); | 1178 WASM_LOAD_MEM(MachineType::Float64(), WASM_ZERO))); |
1111 | 1179 |
1112 FOR_INT32_INPUTS(i) { | 1180 FOR_INT32_INPUTS(i) { |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1214 REQUIRE(I64Eq); | 1282 REQUIRE(I64Eq); |
1215 | 1283 |
1216 WasmRunner<int32_t> r(MachineType::Int64()); | 1284 WasmRunner<int32_t> r(MachineType::Int64()); |
1217 BUILD(r, WASM_I64_EQZ(WASM_GET_LOCAL(0))); | 1285 BUILD(r, WASM_I64_EQZ(WASM_GET_LOCAL(0))); |
1218 | 1286 |
1219 FOR_INT64_INPUTS(i) { | 1287 FOR_INT64_INPUTS(i) { |
1220 int32_t result = *i == 0 ? 1 : 0; | 1288 int32_t result = *i == 0 ? 1 : 0; |
1221 CHECK_EQ(result, r.Call(*i)); | 1289 CHECK_EQ(result, r.Call(*i)); |
1222 } | 1290 } |
1223 } | 1291 } |
OLD | NEW |