control-transfer-unittest.cc 13.1 KB
Newer Older
1 2 3 4 5 6 7 8 9
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "test/unittests/test-utils.h"
#include "testing/gmock/include/gmock/gmock.h"

#include "src/v8.h"
#include "src/wasm/wasm-interpreter.h"
10 11

#include "test/common/wasm/wasm-macro-gen.h"
12 13 14 15 16 17 18 19 20 21 22

using testing::MakeMatcher;
using testing::Matcher;
using testing::MatcherInterface;
using testing::MatchResultListener;
using testing::StringMatchResultListener;

namespace v8 {
namespace internal {
namespace wasm {

23
struct ExpectedControlTransfer {
24
  pc_t pc;
25 26 27
  pcdiff_t pc_diff;
  uint32_t sp_diff;
  uint32_t target_arity;
28 29 30
};

// For nicer error messages.
31 32
class ControlTransferMatcher
    : public MatcherInterface<const ControlTransferEntry&> {
33
 public:
34 35
  explicit ControlTransferMatcher(pc_t pc,
                                  const ExpectedControlTransfer& expected)
36 37 38
      : pc_(pc), expected_(expected) {}

  void DescribeTo(std::ostream* os) const override {
39 40 41
    *os << "@" << pc_ << ": pcdiff = " << expected_.pc_diff
        << ", spdiff = " << expected_.sp_diff
        << ", target arity = " << expected_.target_arity;
42 43
  }

44
  bool MatchAndExplain(const ControlTransferEntry& input,
45
                       MatchResultListener* listener) const override {
46 47 48 49
    if (input.pc_diff == expected_.pc_diff &&
        input.sp_diff == expected_.sp_diff &&
        input.target_arity == expected_.target_arity) {
      return true;
50
    }
51 52 53 54
    *listener << "@" << pc_ << ": pcdiff = " << input.pc_diff
              << ", spdiff = " << input.sp_diff
              << ", target arity = " << input.target_arity;
    return false;
55 56 57 58
  }

 private:
  pc_t pc_;
59
  const ExpectedControlTransfer& expected_;
60 61 62 63
};

class ControlTransferTest : public TestWithZone {
 public:
64
  template <int code_len>
65 66 67
  void CheckTransfers(
      const byte (&code)[code_len],
      std::initializer_list<ExpectedControlTransfer> expected_transfers) {
68 69 70 71 72
    byte code_with_end[code_len + 1];  // NOLINT: code_len is a constant here
    memcpy(code_with_end, code, code_len);
    code_with_end[code_len] = kExprEnd;

    ControlTransferMap map = WasmInterpreter::ComputeControlTransfersForTesting(
73
        zone(), nullptr, code_with_end, code_with_end + code_len + 1);
74
    // Check all control targets in the map.
75 76 77 78 79 80 81
    for (auto& expected_transfer : expected_transfers) {
      pc_t pc = expected_transfer.pc;
      EXPECT_TRUE(map.count(pc) > 0) << "expected control target @" << pc;
      if (!map.count(pc)) continue;
      auto& entry = map[pc];
      EXPECT_THAT(entry, MakeMatcher(new ControlTransferMatcher(
                             pc, expected_transfer)));
82 83
    }

84
    // Check there are no other control targets.
85
    CheckNoOtherTargets(code_with_end, code_with_end + code_len + 1, map,
86
                        expected_transfers);
87 88
  }

89 90 91
  void CheckNoOtherTargets(
      const byte* start, const byte* end, ControlTransferMap& map,
      std::initializer_list<ExpectedControlTransfer> targets) {
92 93 94
    // Check there are no other control targets.
    for (pc_t pc = 0; start + pc < end; pc++) {
      bool found = false;
95 96
      for (auto& target : targets) {
        if (target.pc == pc) {
97 98 99 100 101
          found = true;
          break;
        }
      }
      if (found) continue;
102
      EXPECT_TRUE(map.count(pc) == 0) << "expected no control @ +" << pc;
103 104 105 106 107 108 109
    }
  }
};

TEST_F(ControlTransferTest, SimpleIf) {
  byte code[] = {
      kExprI32Const,  // @0
110
      0,              // @1
111
      kExprIf,        // @2
112 113
      kLocalVoid,     // @3
      kExprEnd        // @4
114
  };
115
  CheckTransfers(code, {{2, 2, 0, 0}});
116 117 118 119 120
}

TEST_F(ControlTransferTest, SimpleIf1) {
  byte code[] = {
      kExprI32Const,  // @0
121
      0,              // @1
122
      kExprIf,        // @2
123 124 125
      kLocalVoid,     // @3
      kExprNop,       // @4
      kExprEnd        // @5
126
  };
127
  CheckTransfers(code, {{2, 3, 0, 0}});
128 129 130 131 132
}

TEST_F(ControlTransferTest, SimpleIf2) {
  byte code[] = {
      kExprI32Const,  // @0
133
      0,              // @1
134
      kExprIf,        // @2
135
      kLocalVoid,     // @3
136
      kExprNop,       // @4
137 138
      kExprNop,       // @5
      kExprEnd        // @6
139
  };
140
  CheckTransfers(code, {{2, 4, 0, 0}});
141 142
}

143
TEST_F(ControlTransferTest, SimpleIfElse) {
144 145
  byte code[] = {
      kExprI32Const,  // @0
146
      0,              // @1
147
      kExprIf,        // @2
148 149 150
      kLocalVoid,     // @3
      kExprElse,      // @4
      kExprEnd        // @5
151
  };
152
  CheckTransfers(code, {{2, 3, 0, 0}, {4, 2, 0, 0}});
153 154 155 156 157 158 159 160
}

TEST_F(ControlTransferTest, SimpleIfElse_v1) {
  byte code[] = {
      kExprI32Const,  // @0
      0,              // @1
      kExprIf,        // @2
      kLocalVoid,     // @3
161
      kExprI32Const,  // @4
162 163
      0,              // @5
      kExprElse,      // @6
164
      kExprI32Const,  // @7
165 166 167
      0,              // @8
      kExprEnd        // @9
  };
168
  CheckTransfers(code, {{2, 5, 0, 0}, {6, 4, 1, 0}});
169 170 171 172 173
}

TEST_F(ControlTransferTest, SimpleIfElse1) {
  byte code[] = {
      kExprI32Const,  // @0
174
      0,              // @1
175
      kExprIf,        // @2
176
      kLocalVoid,     // @3
177 178 179 180
      kExprElse,      // @4
      kExprNop,       // @5
      kExprEnd        // @6
  };
181
  CheckTransfers(code, {{2, 3, 0, 0}, {4, 3, 0, 0}});
182 183 184 185 186
}

TEST_F(ControlTransferTest, IfBr) {
  byte code[] = {
      kExprI32Const,  // @0
187
      0,              // @1
188
      kExprIf,        // @2
189 190 191
      kLocalVoid,     // @3
      kExprBr,        // @4
      0,              // @5
192 193
      kExprEnd        // @6
  };
194
  CheckTransfers(code, {{2, 4, 0, 0}, {4, 3, 0, 0}});
195 196 197 198 199
}

TEST_F(ControlTransferTest, IfBrElse) {
  byte code[] = {
      kExprI32Const,  // @0
200
      0,              // @1
201
      kExprIf,        // @2
202 203 204
      kLocalVoid,     // @3
      kExprBr,        // @4
      0,              // @5
205 206 207
      kExprElse,      // @6
      kExprEnd        // @7
  };
208
  CheckTransfers(code, {{2, 5, 0, 0}, {4, 4, 0, 0}, {6, 2, 0, 0}});
209 210 211 212 213
}

TEST_F(ControlTransferTest, IfElseBr) {
  byte code[] = {
      kExprI32Const,  // @0
214
      0,              // @1
215
      kExprIf,        // @2
216
      kLocalVoid,     // @3
217 218
      kExprElse,      // @4
      kExprBr,        // @5
219 220
      0,              // @6
      kExprEnd        // @7
221
  };
222
  CheckTransfers(code, {{2, 3, 0, 0}, {4, 4, 0, 0}, {5, 3, 0, 0}});
223 224 225 226 227
}

TEST_F(ControlTransferTest, BlockEmpty) {
  byte code[] = {
      kExprBlock,  // @0
228 229
      kLocalVoid,  // @1
      kExprEnd     // @2
230
  };
231
  CheckTransfers(code, {});
232 233 234 235 236
}

TEST_F(ControlTransferTest, Br0) {
  byte code[] = {
      kExprBlock,  // @0
237 238 239
      kLocalVoid,  // @1
      kExprBr,     // @2
      0,           // @3
240 241
      kExprEnd     // @4
  };
242
  CheckTransfers(code, {{2, 3, 0, 0}});
243 244 245 246 247
}

TEST_F(ControlTransferTest, Br1) {
  byte code[] = {
      kExprBlock,  // @0
248 249 250 251
      kLocalVoid,  // @1
      kExprNop,    // @2
      kExprBr,     // @3
      0,           // @4
252 253
      kExprEnd     // @5
  };
254
  CheckTransfers(code, {{3, 3, 0, 0}});
255 256 257 258
}

TEST_F(ControlTransferTest, Br_v1a) {
  byte code[] = {
259 260 261 262 263 264 265
      kExprBlock,     // @0
      kLocalVoid,     // @1
      kExprI32Const,  // @2
      0,              // @3
      kExprBr,        // @4
      0,              // @5
      kExprEnd        // @6
266
  };
267
  CheckTransfers(code, {{4, 3, 1, 0}});
268 269 270 271
}

TEST_F(ControlTransferTest, Br_v1b) {
  byte code[] = {
272 273 274 275 276 277 278
      kExprBlock,     // @0
      kLocalVoid,     // @1
      kExprI32Const,  // @2
      0,              // @3
      kExprBr,        // @4
      0,              // @5
      kExprEnd        // @6
279
  };
280
  CheckTransfers(code, {{4, 3, 1, 0}});
281 282 283 284
}

TEST_F(ControlTransferTest, Br_v1c) {
  byte code[] = {
285 286 287 288 289 290 291
      kExprI32Const,  // @0
      0,              // @1
      kExprBlock,     // @2
      kLocalVoid,     // @3
      kExprBr,        // @4
      0,              // @5
      kExprEnd        // @6
292
  };
293 294 295 296 297 298 299 300 301 302 303 304 305 306
  CheckTransfers(code, {{4, 3, 0, 0}});
}

TEST_F(ControlTransferTest, Br_v1d) {
  byte code[] = {
      kExprBlock,     // @0
      kLocalI32,      // @1
      kExprI32Const,  // @2
      0,              // @3
      kExprBr,        // @4
      0,              // @5
      kExprEnd        // @6
  };
  CheckTransfers(code, {{4, 3, 1, 1}});
307 308 309 310 311
}

TEST_F(ControlTransferTest, Br2) {
  byte code[] = {
      kExprBlock,  // @0
312
      kLocalVoid,  // @1
313
      kExprNop,    // @2
314 315 316
      kExprNop,    // @3
      kExprBr,     // @4
      0,           // @5
317 318
      kExprEnd     // @6
  };
319
  CheckTransfers(code, {{4, 3, 0, 0}});
320 321 322 323 324
}

TEST_F(ControlTransferTest, Br0b) {
  byte code[] = {
      kExprBlock,  // @0
325 326 327
      kLocalVoid,  // @1
      kExprBr,     // @2
      0,           // @3
328 329 330
      kExprNop,    // @4
      kExprEnd     // @5
  };
331
  CheckTransfers(code, {{2, 4, 0, 0}});
332 333 334 335 336
}

TEST_F(ControlTransferTest, Br0c) {
  byte code[] = {
      kExprBlock,  // @0
337 338 339
      kLocalVoid,  // @1
      kExprBr,     // @2
      0,           // @3
340 341 342 343
      kExprNop,    // @4
      kExprNop,    // @5
      kExprEnd     // @6
  };
344
  CheckTransfers(code, {{2, 5, 0, 0}});
345 346 347 348
}

TEST_F(ControlTransferTest, SimpleLoop1) {
  byte code[] = {
349 350 351 352 353
      kExprLoop,   // @0
      kLocalVoid,  // @1
      kExprBr,     // @2
      0,           // @3
      kExprEnd     // @4
354
  };
355
  CheckTransfers(code, {{2, -2, 0, 0}});
356 357 358 359
}

TEST_F(ControlTransferTest, SimpleLoop2) {
  byte code[] = {
360 361 362 363 364 365
      kExprLoop,   // @0
      kLocalVoid,  // @1
      kExprNop,    // @2
      kExprBr,     // @3
      0,           // @4
      kExprEnd     // @5
366
  };
367
  CheckTransfers(code, {{3, -3, 0, 0}});
368 369 370 371
}

TEST_F(ControlTransferTest, SimpleLoopExit1) {
  byte code[] = {
372 373 374 375 376
      kExprLoop,   // @0
      kLocalVoid,  // @1
      kExprBr,     // @2
      1,           // @3
      kExprEnd     // @4
377
  };
378
  CheckTransfers(code, {{2, 4, 0, 0}});
379 380 381 382
}

TEST_F(ControlTransferTest, SimpleLoopExit2) {
  byte code[] = {
383 384 385 386 387 388
      kExprLoop,   // @0
      kLocalVoid,  // @1
      kExprNop,    // @2
      kExprBr,     // @3
      1,           // @4
      kExprEnd     // @5
389
  };
390
  CheckTransfers(code, {{3, 4, 0, 0}});
391 392 393 394
}

TEST_F(ControlTransferTest, BrTable0) {
  byte code[] = {
395 396 397 398 399 400 401 402
      kExprBlock,     // @0
      kLocalVoid,     // @1
      kExprI32Const,  // @2
      0,              // @3
      kExprBrTable,   // @4
      0,              // @5
      U32V_1(0),      // @6
      kExprEnd        // @7
403
  };
404
  CheckTransfers(code, {{4, 4, 0, 0}});
405 406
}

407
TEST_F(ControlTransferTest, BrTable0_v1a) {
408
  byte code[] = {
409 410 411 412 413 414 415 416 417 418
      kExprBlock,     // @0
      kLocalVoid,     // @1
      kExprI32Const,  // @2
      0,              // @3
      kExprI32Const,  // @4
      0,              // @5
      kExprBrTable,   // @6
      0,              // @7
      U32V_1(0),      // @8
      kExprEnd        // @9
419
  };
420
  CheckTransfers(code, {{6, 4, 1, 0}});
421 422
}

423 424
TEST_F(ControlTransferTest, BrTable0_v1b) {
  byte code[] = {
425 426 427 428 429 430 431 432 433 434
      kExprBlock,     // @0
      kLocalVoid,     // @1
      kExprI32Const,  // @2
      0,              // @3
      kExprI32Const,  // @4
      0,              // @5
      kExprBrTable,   // @6
      0,              // @7
      U32V_1(0),      // @8
      kExprEnd        // @9
435
  };
436
  CheckTransfers(code, {{6, 4, 1, 0}});
437 438 439
}

TEST_F(ControlTransferTest, BrTable1) {
440
  byte code[] = {
441 442 443 444 445 446 447 448 449
      kExprBlock,     // @0
      kLocalVoid,     // @1
      kExprI32Const,  // @2
      0,              // @3
      kExprBrTable,   // @4
      1,              // @5
      U32V_1(0),      // @6
      U32V_1(0),      // @7
      kExprEnd        // @8
450
  };
451
  CheckTransfers(code, {{4, 5, 0, 0}, {5, 4, 0, 0}});
452 453 454 455
}

TEST_F(ControlTransferTest, BrTable2) {
  byte code[] = {
456 457 458 459 460 461 462 463 464 465 466 467 468
      kExprBlock,     // @0
      kLocalVoid,     // @1
      kExprBlock,     // @2
      kLocalVoid,     // @3
      kExprI32Const,  // @4
      0,              // @5
      kExprBrTable,   // @6
      2,              // @7
      U32V_1(0),      // @8
      U32V_1(0),      // @9
      U32V_1(1),      // @10
      kExprEnd,       // @11
      kExprEnd        // @12
469
  };
470 471 472 473 474 475 476 477 478 479 480 481 482 483 484
  CheckTransfers(code, {{6, 6, 0, 0}, {7, 5, 0, 0}, {8, 5, 0, 0}});
}

TEST_F(ControlTransferTest, BiggerSpDiffs) {
  byte code[] = {
      kExprBlock,     // @0
      kLocalI32,      // @1
      kExprI32Const,  // @2
      0,              // @3
      kExprBlock,     // @4
      kLocalVoid,     // @5
      kExprI32Const,  // @6
      0,              // @7
      kExprI32Const,  // @8
      0,              // @9
485
      kExprI32Const,  // @10
486
      0,              // @11
487 488 489 490 491 492
      kExprBrIf,      // @12
      0,              // @13
      kExprBr,        // @14
      1,              // @15
      kExprEnd,       // @16
      kExprEnd        // @17
493
  };
494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519
  CheckTransfers(code, {{12, 5, 2, 0}, {14, 4, 3, 1}});
}

TEST_F(ControlTransferTest, NoInfoForUnreachableCode) {
  byte code[] = {
      kExprBlock,        // @0
      kLocalVoid,        // @1
      kExprBr,           // @2
      0,                 // @3
      kExprBr,           // @4 -- no control transfer entry!
      1,                 // @5
      kExprEnd,          // @6
      kExprBlock,        // @7
      kLocalVoid,        // @8
      kExprUnreachable,  // @9
      kExprI32Const,     // @10
      0,                 // @11
      kExprIf,           // @12 -- no control transfer entry!
      kLocalVoid,        // @13
      kExprBr,           // @14 -- no control transfer entry!
      0,                 // @15
      kExprElse,         // @16 -- no control transfer entry!
      kExprEnd,          // @17
      kExprEnd           // @18
  };
  CheckTransfers(code, {{2, 5, 0, 0}});
520 521 522 523 524
}

}  // namespace wasm
}  // namespace internal
}  // namespace v8