Coverage for /Syzygy/block_graph/basic_block_assembler_unittest.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
99.8%4554560.C++test

Line-by-line coverage:

   1    :  // Copyright 2012 Google Inc. All Rights Reserved.
   2    :  //
   3    :  // Licensed under the Apache License, Version 2.0 (the "License");
   4    :  // you may not use this file except in compliance with the License.
   5    :  // You may obtain a copy of the License at
   6    :  //
   7    :  //     http://www.apache.org/licenses/LICENSE-2.0
   8    :  //
   9    :  // Unless required by applicable law or agreed to in writing, software
  10    :  // distributed under the License is distributed on an "AS IS" BASIS,
  11    :  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12    :  // See the License for the specific language governing permissions and
  13    :  // limitations under the License.
  14    :  //
  15    :  #include "syzygy/block_graph/basic_block_assembler.h"
  16    :  
  17    :  #include "gtest/gtest.h"
  18    :  #include "syzygy/block_graph/basic_block_subgraph.h"
  19    :  
  20    :  namespace block_graph {
  21    :  
  22    :  namespace {
  23    :  
  24    :  class BasicBlockAssemblerTest : public testing::Test {
  25    :   public:
  26    :    typedef BlockGraph::RelativeAddress RelativeAddress;
  27    :    typedef BlockGraph::Block::SourceRange SourceRange;
  28    :  
  29    :    BasicBlockAssemblerTest();
  30    :  
  31  E :    void SetUp() override {}
  32    :  
  33  E :    void TearDown() override {}
  34    :  
  35    :   protected:
  36    :    struct Ref {
  37    :      size_t offset;
  38    :      BasicBlockReference::ReferredType type;
  39    :      const void* reference;
  40    :    };
  41    :  
  42    :    template <size_t N>
  43  E :    void AssertRefs(const Ref(& refs)[N]) {
  44  E :      ASSERT_EQ(1, instructions_.size());
  45  E :      const Instruction& instr = instructions_.front();
  46    :  
  47  E :      for (size_t i = 0; i < N; ++i) {
  48    :        BasicBlock::BasicBlockReferenceMap::const_iterator it =
  49  E :            instr.references().find(refs[i].offset);
  50  E :        ASSERT_NE(instr.references().end(), it);
  51  E :        ASSERT_EQ(refs[i].type, it->second.referred_type());
  52  E :        switch (refs[i].type) {
  53    :          case BasicBlockReference::REFERRED_TYPE_BLOCK:
  54  E :            ASSERT_EQ(refs[i].reference, it->second.block());
  55  E :            break;
  56    :          case BasicBlockReference::REFERRED_TYPE_BASIC_BLOCK:
  57  E :            ASSERT_EQ(refs[i].reference, it->second.basic_block());
  58  E :            break;
  59    :          default:
  60  i :            ASSERT_TRUE(false);
  61    :        }
  62    :  
  63  E :        ASSERT_EQ(refs[i].type, it->second.referred_type());
  64  E :      }
  65    :  
  66  E :      instructions_.clear();
  67  E :    }
  68    :  
  69  E :    void AssertNoRefs() {
  70  E :      ASSERT_EQ(1, instructions_.size());
  71  E :      ASSERT_EQ(0, instructions_.front().references().size());
  72  E :      instructions_.clear();
  73  E :    }
  74    :  
  75    :    BlockGraph block_graph_;
  76    :    BlockGraph::Block* test_block_;
  77    :    BasicBlockSubGraph subgraph_;
  78    :    BasicCodeBlock* test_bb_;
  79    :    BasicBlock::Instructions instructions_;
  80    :    BasicBlockAssembler asm_;
  81    :  };
  82    :  
  83    :  #define ASSERT_REFS(...) \
  84    :    do { \
  85    :      const Ref refs[] = { __VA_ARGS__ }; \
  86    :      ASSERT_NO_FATAL_FAILURE(AssertRefs(refs)); \
  87    :    } while (0)
  88    :  
  89    :  #define ASSERT_NO_REFS() ASSERT_NO_FATAL_FAILURE(AssertNoRefs())
  90    :  
  91    :  BasicBlockAssemblerTest::BasicBlockAssemblerTest()
  92    :      : test_block_(NULL),
  93    :        test_bb_(NULL),
  94  E :        asm_(instructions_.end(), &instructions_) {
  95  E :    test_block_ = block_graph_.AddBlock(BlockGraph::CODE_BLOCK, 10, "test block");
  96  E :    test_bb_ = subgraph_.AddBasicCodeBlock("foo");
  97  E :  }
  98    :  
  99    :  }  // namespace
 100    :  
 101  E :  TEST(UntypedReferenceTest, DefaultConstructor) {
 102  E :    UntypedReference r;
 103  E :    EXPECT_EQ(NULL, r.basic_block());
 104  E :    EXPECT_EQ(NULL, r.block());
 105  E :    EXPECT_EQ(0, r.offset());
 106  E :    EXPECT_EQ(0, r.base());
 107  E :    EXPECT_FALSE(r.IsValid());
 108  E :    EXPECT_EQ(BasicBlockReference::REFERRED_TYPE_UNKNOWN, r.referred_type());
 109  E :  }
 110    :  
 111  E :  TEST(UntypedReferenceTest, BasicBlockReferenceToBasicBlockConstructor) {
 112  E :    BasicBlockSubGraph subgraph;
 113  E :    BasicCodeBlock* bcb = subgraph.AddBasicCodeBlock("foo");
 114  E :    BasicBlock* bb = bcb;
 115  E :    BasicBlockReference bbref(BlockGraph::ABSOLUTE_REF, 4, bcb);
 116  E :    UntypedReference r(bbref);
 117  E :    EXPECT_EQ(bb, r.basic_block());
 118  E :    EXPECT_EQ(NULL, r.block());
 119  E :    EXPECT_EQ(0, r.offset());
 120  E :    EXPECT_EQ(0, r.base());
 121  E :    EXPECT_TRUE(r.IsValid());
 122  E :    EXPECT_EQ(BasicBlockReference::REFERRED_TYPE_BASIC_BLOCK, r.referred_type());
 123  E :  }
 124    :  
 125  E :  TEST(UntypedReferenceTest, BasicBlockReferenceToBlockConstructor) {
 126  E :    BlockGraph block_graph;
 127    :    BlockGraph::Block* b =
 128  E :        block_graph.AddBlock(BlockGraph::CODE_BLOCK, 20, "foo");
 129  E :    BasicBlockReference bbref(BlockGraph::ABSOLUTE_REF, 4, b, 4, 10);
 130  E :    UntypedReference r(bbref);
 131  E :    EXPECT_EQ(NULL, r.basic_block());
 132  E :    EXPECT_EQ(b, r.block());
 133  E :    EXPECT_EQ(4, r.offset());
 134  E :    EXPECT_EQ(10, r.base());
 135  E :    EXPECT_TRUE(r.IsValid());
 136  E :    EXPECT_EQ(BasicBlockReference::REFERRED_TYPE_BLOCK, r.referred_type());
 137  E :  }
 138    :  
 139  E :  TEST(UntypedReferenceTest, BasicBlockConstructor) {
 140  E :    BasicBlockSubGraph subgraph;
 141  E :    BasicCodeBlock* bcb = subgraph.AddBasicCodeBlock("foo");
 142  E :    BasicBlock* bb = bcb;
 143  E :    UntypedReference r(bcb);
 144  E :    EXPECT_EQ(bb, r.basic_block());
 145  E :    EXPECT_EQ(NULL, r.block());
 146  E :    EXPECT_EQ(0, r.offset());
 147  E :    EXPECT_EQ(0, r.base());
 148  E :    EXPECT_TRUE(r.IsValid());
 149  E :    EXPECT_EQ(BasicBlockReference::REFERRED_TYPE_BASIC_BLOCK, r.referred_type());
 150  E :  }
 151    :  
 152  E :  TEST(UntypedReferenceTest, BlockConstructor) {
 153  E :    BlockGraph block_graph;
 154    :    BlockGraph::Block* b =
 155  E :        block_graph.AddBlock(BlockGraph::CODE_BLOCK, 0, "dummy");
 156  E :    UntypedReference r(b, 4, 10);
 157  E :    EXPECT_EQ(NULL, r.basic_block());
 158  E :    EXPECT_EQ(b, r.block());
 159  E :    EXPECT_EQ(4, r.offset());
 160  E :    EXPECT_EQ(10, r.base());
 161  E :    EXPECT_TRUE(r.IsValid());
 162  E :    EXPECT_EQ(BasicBlockReference::REFERRED_TYPE_BLOCK, r.referred_type());
 163  E :  }
 164    :  
 165  E :  TEST(UntypedReferenceTest, CopyConstructor) {
 166  E :    BlockGraph block_graph;
 167    :    BlockGraph::Block* b =
 168  E :        block_graph.AddBlock(BlockGraph::CODE_BLOCK, 0, "dummy");
 169  E :    UntypedReference r1(b, 4, 10);
 170    :  
 171  E :    UntypedReference r2(r1);
 172  E :    EXPECT_EQ(r1.basic_block(), r2.basic_block());
 173  E :    EXPECT_EQ(r1.block(), r2.block());
 174  E :    EXPECT_EQ(r1.offset(), r2.offset());
 175  E :    EXPECT_EQ(r1.base(), r2.base());
 176  E :    EXPECT_EQ(r1.IsValid(), r2.IsValid());
 177  E :  }
 178    :  
 179  E :  TEST(UntypedReferenceTest, Comparison) {
 180  E :    BlockGraph block_graph;
 181  E :    BasicBlockSubGraph subgraph;
 182    :    BlockGraph::Block* b =
 183  E :        block_graph.AddBlock(BlockGraph::CODE_BLOCK, 0, "dummy");
 184  E :    UntypedReference r1(b, 4, 10);
 185    :  
 186  E :    UntypedReference r2(b, 0, 0);
 187  E :    EXPECT_FALSE(r1 == r2);
 188    :  
 189  E :    BasicCodeBlock* bcb = subgraph.AddBasicCodeBlock("foo");
 190  E :    UntypedReference r3(bcb);
 191  E :    EXPECT_FALSE(r1 == r3);
 192  E :    EXPECT_FALSE(r2 == r3);
 193    :  
 194  E :    UntypedReference r4(r1);
 195  E :    EXPECT_TRUE(r1 == r4);
 196    :  
 197  E :    UntypedReference r5(r2);
 198  E :    EXPECT_TRUE(r2 == r5);
 199  E :  }
 200    :  
 201    :  namespace {
 202    :  
 203    :  template <typename ValueTraits>
 204    :  class ValueTest : public BasicBlockAssemblerTest {
 205    :   public:
 206    :    typedef typename ValueTraits ValueTraits;
 207    :    typedef typename ValueTraits::ValueType ValueType;
 208    :  
 209    :    void TestValue(const ValueType& value,
 210    :                   uint32 expected_value,
 211  E :                   assm::ValueSize expected_size) {
 212  E :      EXPECT_EQ(expected_size, value.size());
 213  E :      EXPECT_EQ(expected_value, value.value());
 214  E :      EXPECT_EQ(BasicBlockReference::REFERRED_TYPE_UNKNOWN,
 215  E :                value.reference().referred_type());
 216    :  
 217  E :      auto value_copy(value);
 218  E :      EXPECT_EQ(expected_size, value_copy.size());
 219  E :      EXPECT_EQ(expected_value, value_copy.value());
 220  E :      EXPECT_EQ(BasicBlockReference::REFERRED_TYPE_UNKNOWN,
 221  E :                value_copy.reference().referred_type());
 222    :  
 223  E :      EXPECT_TRUE(value == value_copy);
 224    :  
 225  E :      auto value_diff(ValueTraits::Factory(expected_value - 1));
 226  E :      EXPECT_FALSE(value == value_diff);
 227  E :    }
 228    :  
 229  E :    void Test8BitValue(uint32 input_value, uint32 expected_value) {
 230    :      TestValue(ValueTraits::Factory(input_value),
 231  E :                expected_value, assm::kSize8Bit);
 232    :      TestValue(ValueTraits::Factory(input_value, assm::kSize8Bit),
 233  E :                expected_value, assm::kSize8Bit);
 234  E :    }
 235    :  
 236  E :    void Test32BitValue(uint32 input_value, uint32 expected_value) {
 237    :      TestValue(ValueTraits::Factory(input_value),
 238  E :                expected_value, assm::kSize32Bit);
 239    :      TestValue(ValueTraits::Factory(input_value, assm::kSize32Bit),
 240  E :                expected_value, assm::kSize32Bit);
 241  E :    }
 242    :  };
 243    :  
 244    :  struct ImmediateTestTraits {
 245    :    typedef BasicBlockAssembler::Immediate ValueType;
 246    :  
 247  E :    static ValueType Factory() { return Immediate(); }
 248  E :    static ValueType Factory(uint32 value) { return Immediate(value); }
 249  E :    static ValueType Factory(uint32 value, assm::ValueSize size) {
 250  E :      return Immediate(value, size);
 251  E :    }
 252  E :    static ValueType Factory(BasicBlock* bb) { return Immediate(bb); }
 253    :    static ValueType Factory(BlockGraph::Block* block,
 254  E :                             BlockGraph::Offset offset) {
 255  E :      return Immediate(block, offset);
 256  E :    }
 257    :    static ValueType Factory(BlockGraph::Block* block,
 258    :                             BlockGraph::Offset offset,
 259    :                             BlockGraph::Offset base) {
 260    :      return Immediate(block, offset, base);
 261    :    }
 262    :    static ValueType Factory(uint32 value,
 263    :                             ValueSize size,
 264  E :                             const UntypedReference& ref) {
 265  E :      return Immediate(value, size, ref);
 266  E :    }
 267    :  };
 268    :  
 269    :  struct DisplacementTestTraits {
 270    :    typedef BasicBlockAssembler::Displacement ValueType;
 271    :  
 272  E :    static ValueType Factory() { return Displacement(); }
 273  E :    static ValueType Factory(uint32 value) { return Displacement(value); }
 274  E :    static ValueType Factory(uint32 value, assm::ValueSize size) {
 275  E :      return Displacement(value, size);
 276  E :    }
 277  E :    static ValueType Factory(BasicBlock* bb) { return Displacement(bb); }
 278    :    static ValueType Factory(BlockGraph::Block* block,
 279  E :                             BlockGraph::Offset offset) {
 280  E :      return Displacement(block, offset);
 281  E :    }
 282    :    static ValueType Factory(BlockGraph::Block* block,
 283    :                             BlockGraph::Offset offset,
 284    :                             BlockGraph::Offset base) {
 285    :      return Displacement(block, offset, base);
 286    :    }
 287    :    static ValueType Factory(uint32 value,
 288    :                             ValueSize size,
 289  E :                             const UntypedReference& ref) {
 290  E :      return Displacement(value, size, ref);
 291  E :    }
 292    :  };
 293    :  
 294    :  }  // namespace
 295    :  
 296    :  typedef ::testing::Types<ImmediateTestTraits, DisplacementTestTraits>
 297    :      ValueTestTypes;
 298    :  TYPED_TEST_CASE(ValueTest, ValueTestTypes);
 299    :  
 300  E :  TYPED_TEST(ValueTest, Factories) {
 301    :    {
 302  E :      auto imm_empty(ValueTraits::Factory());
 303  E :      ASSERT_EQ(0, imm_empty.value());
 304  E :      ASSERT_EQ(assm::kSizeNone, imm_empty.size());
 305  E :      ASSERT_EQ(BasicBlockReference::REFERRED_TYPE_UNKNOWN,
 306    :                imm_empty.reference().referred_type());
 307    :    }
 308    :  
 309  E :    Test8BitValue(0, 0);
 310  E :    Test8BitValue(127, 127);
 311    :  
 312  E :    Test8BitValue(static_cast<uint32>(-128), 0xFFFFFF80);
 313  E :    Test8BitValue(0, 0);
 314  E :    Test8BitValue(127, 0x0000007F);
 315    :  
 316  E :    Test32BitValue(128, 0x00000080);
 317  E :    Test32BitValue(0xCAFEBABE, 0xCAFEBABE);
 318    :  
 319  E :    Test32BitValue(static_cast<uint32>(-129), 0xFFFFFF7F);
 320  E :    Test32BitValue(128, 0x000000080);
 321  E :    Test32BitValue(0xBABE, 0xBABE);
 322    :  
 323    :    {
 324  E :      const BlockGraph::Offset kOffs = 10;
 325  E :      auto imm_block_ref(ValueTraits::Factory(test_block_, kOffs));
 326    :  
 327  E :      ASSERT_EQ(0, imm_block_ref.value());
 328  E :      ASSERT_EQ(assm::kSize32Bit, imm_block_ref.size());
 329  E :      ASSERT_EQ(BasicBlockReference::REFERRED_TYPE_BLOCK,
 330    :                imm_block_ref.reference().referred_type());
 331  E :      ASSERT_EQ(test_block_, imm_block_ref.reference().block());
 332  E :      ASSERT_EQ(kOffs, imm_block_ref.reference().offset());
 333  E :      ASSERT_EQ(kOffs, imm_block_ref.reference().base());
 334    :    }
 335    :  
 336    :    {
 337  E :      auto imm_bb_ref(ValueTraits::Factory(test_bb_));
 338    :  
 339  E :      ASSERT_EQ(0, imm_bb_ref.value());
 340  E :      ASSERT_EQ(assm::kSize32Bit, imm_bb_ref.size());
 341  E :      ASSERT_EQ(BasicBlockReference::REFERRED_TYPE_BASIC_BLOCK,
 342    :                imm_bb_ref.reference().referred_type());
 343  E :      ASSERT_EQ(test_bb_, imm_bb_ref.reference().basic_block());
 344  E :      ASSERT_EQ(0, imm_bb_ref.reference().offset());
 345  E :      ASSERT_EQ(0, imm_bb_ref.reference().base());
 346    :    }
 347    :  
 348    :    {
 349    :      // Explicitly specified size and reference info.
 350  E :      UntypedReference ref(test_block_, 1, 2);
 351  E :      auto imm_expl_ref(ValueTraits::Factory(0xBE, assm::kSize8Bit, ref));
 352    :  
 353  E :      ASSERT_EQ(0xBE, imm_expl_ref.value());
 354  E :      ASSERT_EQ(assm::kSize8Bit, imm_expl_ref.size());
 355  E :      ASSERT_EQ(BasicBlockReference::REFERRED_TYPE_BLOCK,
 356    :                imm_expl_ref.reference().referred_type());
 357  E :      ASSERT_EQ(test_block_, imm_expl_ref.reference().block());
 358  E :      ASSERT_EQ(1, imm_expl_ref.reference().offset());
 359  E :      ASSERT_EQ(2, imm_expl_ref.reference().base());
 360    :    }
 361  E :  }
 362    :  
 363    :  namespace {
 364    :  
 365    :  // Asserts that @p op.displacement() is equal to @p displ.
 366    :  void TestEqualDisplacement(const BasicBlockAssembler::Operand& op,
 367  E :                             const BasicBlockAssembler::Displacement& displ) {
 368  E :    ASSERT_EQ(displ.value(), op.displacement().value());
 369  E :    ASSERT_EQ(displ.size(), op.displacement().size());
 370    :  
 371    :    ASSERT_EQ(displ.reference().IsValid(),
 372  E :              op.displacement().reference().IsValid());
 373  E :    if (!displ.reference().IsValid())
 374  E :      return;
 375    :  
 376    :    ASSERT_EQ(displ.reference().IsValid(),
 377  E :              op.displacement().reference().IsValid());
 378    :  
 379    :    ASSERT_EQ(displ.reference().basic_block(),
 380  E :              op.displacement().reference().basic_block());
 381    :    ASSERT_EQ(displ.reference().block(),
 382  E :              op.displacement().reference().block());
 383    :    ASSERT_EQ(displ.reference().offset(),
 384  E :              op.displacement().reference().offset());
 385    :    ASSERT_EQ(displ.reference().base(),
 386  E :              op.displacement().reference().base());
 387  E :  }
 388    :  
 389    :  }  // namespace
 390    :  
 391    :  typedef BasicBlockAssemblerTest OperandTest;
 392    :  
 393  E :  TEST_F(OperandTest, Factories) {
 394    :    {
 395  E :      auto op(Operand(assm::eax));
 396    :  
 397  E :      ASSERT_EQ(assm::kRegisterEax, op.base());
 398  E :      ASSERT_EQ(assm::kRegisterNone, op.index());
 399  E :      ASSERT_EQ(assm::kTimes1, op.scale());
 400  E :      ASSERT_EQ(assm::kSizeNone, op.displacement().size());
 401    :  
 402  E :      TestEqualDisplacement(op, Displacement());
 403    :    }
 404    :  
 405    :    {
 406    :      // Register-indirect with displacement.
 407  E :      auto op(Operand(assm::eax, Displacement(100)));
 408  E :      ASSERT_EQ(assm::kRegisterEax, op.base());
 409  E :      ASSERT_EQ(assm::kRegisterNone, op.index());
 410  E :      ASSERT_EQ(assm::kTimes1, op.scale());
 411  E :      ASSERT_EQ(assm::kSize8Bit, op.displacement().size());
 412    :  
 413  E :      TestEqualDisplacement(op, Displacement(100));
 414    :  
 415    :      TestEqualDisplacement(Operand(assm::eax, Displacement(test_block_, 2)),
 416  E :                            Displacement(test_block_, 2));
 417    :      TestEqualDisplacement(Operand(assm::eax, Displacement(test_bb_)),
 418  E :                            Displacement(test_bb_));
 419    :    }
 420    :  
 421    :    {
 422    :      // Displacement-only mode.
 423  E :      auto op(Operand(Displacement(100)));
 424  E :      ASSERT_EQ(assm::kRegisterNone, op.base());
 425  E :      ASSERT_EQ(assm::kRegisterNone, op.index());
 426  E :      ASSERT_EQ(assm::kTimes1, op.scale());
 427  E :      ASSERT_EQ(assm::kSize8Bit, op.displacement().size());
 428  E :      TestEqualDisplacement(op, Displacement(100));
 429    :  
 430    :      TestEqualDisplacement(Operand(Displacement(test_block_, 2)),
 431  E :                            Displacement(test_block_, 2));
 432    :      TestEqualDisplacement(Operand(Displacement(test_bb_)),
 433  E :                            Displacement(test_bb_));
 434    :    }
 435    :  
 436    :    {
 437    :      // The [base + index * scale] mode with displ.
 438  E :      auto op(Operand(assm::eax, assm::ebp, assm::kTimes2, Displacement(100)));
 439  E :      ASSERT_EQ(assm::kRegisterEax, op.base());
 440  E :      ASSERT_EQ(assm::kRegisterEbp, op.index());
 441  E :      ASSERT_EQ(assm::kTimes2, op.scale());
 442  E :      ASSERT_EQ(assm::kSize8Bit, op.displacement().size());
 443    :  
 444    :      TestEqualDisplacement(
 445    :          Operand(assm::eax, assm::ebp, assm::kTimes2,
 446    :                  Displacement(test_block_, 2)),
 447  E :          Displacement(test_block_, 2));
 448    :      TestEqualDisplacement(
 449    :          Operand(assm::eax, assm::ebp, assm::kTimes2, Displacement(test_bb_)),
 450  E :          Displacement(test_bb_));
 451    :    }
 452    :  
 453    :    {
 454    :      // The [base + index * scale] mode - no displ.
 455  E :      auto op(Operand(assm::eax, assm::ebp, assm::kTimes2));
 456  E :      ASSERT_EQ(assm::kRegisterEax, op.base());
 457  E :      ASSERT_EQ(assm::kRegisterEbp, op.index());
 458  E :      ASSERT_EQ(assm::kTimes2, op.scale());
 459  E :      ASSERT_EQ(assm::kSizeNone, op.displacement().size());
 460    :  
 461    :      // The [index * scale + displ32] mode - no base.
 462    :      TestEqualDisplacement(Operand(assm::eax, assm::ebp, assm::kTimes2),
 463  E :                            Displacement());
 464    :    }
 465  E :  }
 466    :  
 467  E :  TEST_F(BasicBlockAssemblerTest, nop) {
 468    :    // We can't use ASSERT_NO_REFS here as nop may generate more than 1
 469    :    // instruction, an exception to the rule of 1 instruction that ASSERT_NO_REFS
 470    :    // enforces.
 471  E :    asm_.nop(0);
 472  E :    ASSERT_EQ(0u, instructions_.size());
 473    :  
 474    :    // Exactly 1 or 2 instructions should be emitted per NOP length from
 475    :    // 1 to 15.
 476  E :    for (size_t i = 1; i <= 15; ++i) {
 477  E :      asm_.nop(i);
 478  E :      ASSERT_LT(0u, instructions_.size());
 479  E :      ASSERT_GE(2u, instructions_.size());
 480    :  
 481    :      // NOP instructions should have no references.
 482  E :      for (BasicCodeBlock::Instructions::const_iterator inst_it =
 483    :               instructions_.begin();
 484  E :           inst_it != instructions_.end();
 485  E :           ++inst_it) {
 486  E :        ASSERT_EQ(0u, inst_it->references().size());
 487  E :      }
 488  E :      instructions_.clear();
 489  E :    }
 490  E :  }
 491    :  
 492  E :  TEST_F(BasicBlockAssemblerTest, call) {
 493  E :    asm_.call(Immediate(test_block_, 0));
 494  E :    ASSERT_REFS(1, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_);
 495    :  
 496  E :    asm_.call(Operand(Displacement(test_bb_)));
 497  E :    ASSERT_REFS(2, BasicBlockReference::REFERRED_TYPE_BASIC_BLOCK, test_bb_);
 498  E :  }
 499    :  
 500  E :  TEST_F(BasicBlockAssemblerTest, jmp) {
 501  E :    asm_.jmp(Immediate(test_block_, 0));
 502  E :    ASSERT_REFS(1, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_);
 503    :  
 504  E :    asm_.jmp(Operand(Displacement(test_bb_)));
 505  E :    ASSERT_REFS(2, BasicBlockReference::REFERRED_TYPE_BASIC_BLOCK, test_bb_);
 506  E :  }
 507    :  
 508  E :  TEST_F(BasicBlockAssemblerTest, mov_b) {
 509    :    // mov BYTE PTR [base + index * scale + displ], immediate
 510    :    asm_.mov_b(Operand(assm::eax, assm::ebx, assm::kTimes4,
 511    :                       Displacement(test_block_, 0)),
 512  E :               Immediate(10));
 513  E :    ASSERT_REFS(3, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_);
 514  E :  }
 515    :  
 516  E :  TEST_F(BasicBlockAssemblerTest, movzx_b) {
 517    :    // movzx eax, BYTE PTR [base + index * scale + displ]
 518    :    asm_.movzx_b(assm::eax,
 519    :                 Operand(assm::eax, assm::ebx, assm::kTimes4,
 520  E :                         Displacement(test_block_, 0)));
 521  E :    ASSERT_REFS(4, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_);
 522  E :  }
 523    :  
 524  E :  TEST_F(BasicBlockAssemblerTest, mov) {
 525    :    // Simple register-register move.
 526  E :    asm_.mov(assm::eax, assm::ebx);
 527  E :    ASSERT_NO_REFS();
 528    :  
 529    :    // Simple immediate-register move.
 530  E :    asm_.mov(assm::eax, Immediate(10));
 531  E :    ASSERT_NO_REFS();
 532    :  
 533    :    // Immediate-with reference to register.
 534  E :    asm_.mov(assm::eax, Immediate(test_block_, 0));
 535  E :    ASSERT_REFS(1, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_);
 536    :  
 537    :    // Torture test; mov [displ], immediate,
 538    :    // both src and dst contain references.
 539  E :    asm_.mov(Operand(Displacement(test_block_, 0)), Immediate(test_bb_));
 540    :    ASSERT_REFS(2, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_,
 541  E :                6, BasicBlockReference::REFERRED_TYPE_BASIC_BLOCK, test_bb_);
 542    :  
 543    :    // Torture test; mov [base + index * scale + displ], immediate,
 544    :    // both src and dst contain references.
 545    :    asm_.mov(Operand(assm::eax, assm::ebx, assm::kTimes4,
 546    :                     Displacement(test_block_, 0)),
 547  E :             Immediate(test_bb_));
 548    :    ASSERT_REFS(3, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_,
 549  E :                7, BasicBlockReference::REFERRED_TYPE_BASIC_BLOCK, test_bb_);
 550  E :  }
 551    :  
 552  E :  TEST_F(BasicBlockAssemblerTest, mov_fs) {
 553    :    asm_.mov_fs(Operand(assm::eax, assm::ebx, assm::kTimes4,
 554    :                        Displacement(test_block_, 0)),
 555  E :                assm::eax);
 556  E :    ASSERT_REFS(4, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_);
 557    :  
 558    :    asm_.mov_fs(assm::eax,
 559    :                Operand(assm::eax, assm::ebx, assm::kTimes4,
 560  E :                        Displacement(test_block_, 0)));
 561  E :    ASSERT_REFS(4, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_);
 562  E :  }
 563    :  
 564  E :  TEST_F(BasicBlockAssemblerTest, lea) {
 565  E :    asm_.lea(assm::eax, Operand(assm::eax));
 566  E :    ASSERT_NO_REFS();
 567    :  
 568    :    asm_.lea(assm::eax,
 569    :             Operand(assm::eax, assm::ebx, assm::kTimes4,
 570  E :                     Displacement(test_bb_)));
 571  E :    ASSERT_REFS(3, BasicBlockReference::REFERRED_TYPE_BASIC_BLOCK, test_bb_);
 572  E :  }
 573    :  
 574  E :  TEST_F(BasicBlockAssemblerTest, push) {
 575  E :    asm_.push(assm::esp);
 576  E :    ASSERT_NO_REFS();
 577    :  
 578  E :    asm_.push(Immediate(test_block_, 0));
 579  E :    ASSERT_REFS(1, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_);
 580    :  
 581    :    asm_.push(Operand(assm::eax, assm::ebx, assm::kTimes4,
 582  E :                      Displacement(test_bb_)));
 583  E :    ASSERT_REFS(3, BasicBlockReference::REFERRED_TYPE_BASIC_BLOCK, test_bb_);
 584  E :  }
 585    :  
 586  E :  TEST_F(BasicBlockAssemblerTest, pop) {
 587  E :    asm_.pop(assm::ebp);
 588  E :    ASSERT_NO_REFS();
 589    :  
 590    :    asm_.pop(Operand(assm::eax, assm::ebx, assm::kTimes4,
 591  E :                      Displacement(test_bb_)));
 592  E :    ASSERT_REFS(3, BasicBlockReference::REFERRED_TYPE_BASIC_BLOCK, test_bb_);
 593  E :  }
 594    :  
 595  E :  TEST_F(BasicBlockAssemblerTest, pushfd) {
 596  E :    asm_.pushfd();
 597  E :    ASSERT_NO_REFS();
 598  E :  }
 599    :  
 600  E :  TEST_F(BasicBlockAssemblerTest, popfd) {
 601  E :    asm_.popfd();
 602  E :    ASSERT_NO_REFS();
 603  E :  }
 604    :  
 605  E :  TEST_F(BasicBlockAssemblerTest, lahf) {
 606  E :    asm_.lahf();
 607  E :    ASSERT_NO_REFS();
 608  E :  }
 609    :  
 610  E :  TEST_F(BasicBlockAssemblerTest, sahf) {
 611  E :    asm_.sahf();
 612  E :    ASSERT_NO_REFS();
 613  E :  }
 614    :  
 615  E :  TEST_F(BasicBlockAssemblerTest, setxx) {
 616    :    // Simple register-register operation.
 617  E :    asm_.set(assm::kParityEven, assm::eax);
 618  E :    ASSERT_NO_REFS();
 619    :  
 620  E :    asm_.set(assm::kOverflow, assm::ebx);
 621  E :    ASSERT_NO_REFS();
 622  E :  }
 623    :  
 624  E :  TEST_F(BasicBlockAssemblerTest, test) {
 625    :    // Simple register-register operation.
 626  E :    asm_.test(assm::al, assm::bl);
 627  E :    ASSERT_NO_REFS();
 628    :  
 629    :    // Simple immediate-register operation.
 630  E :    asm_.test(assm::al, Immediate(10, assm::kSize8Bit));
 631  E :    ASSERT_NO_REFS();
 632    :  
 633    :    // Simple register-register operation.
 634  E :    asm_.test(assm::eax, assm::ebx);
 635  E :    ASSERT_NO_REFS();
 636    :  
 637    :    // Simple immediate-register operation.
 638  E :    asm_.test(assm::eax, Immediate(10));
 639  E :    ASSERT_NO_REFS();
 640    :  
 641    :    // Immediate-with reference to register.
 642  E :    asm_.test(assm::eax, Immediate(test_block_, 0));
 643  E :    ASSERT_REFS(1, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_);
 644    :  
 645    :    // Torture test: both src and dst contain references.
 646  E :    asm_.test(Operand(Displacement(test_block_, 0)), Immediate(test_bb_));
 647    :    ASSERT_REFS(2, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_,
 648  E :                6, BasicBlockReference::REFERRED_TYPE_BASIC_BLOCK, test_bb_);
 649    :  
 650  E :    asm_.test(Operand(Displacement(test_block_, 0)), Immediate(10));
 651  E :    ASSERT_REFS(2, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_);
 652  E :  }
 653    :  
 654  E :  TEST_F(BasicBlockAssemblerTest, cmp) {
 655    :      // Simple register-register operation.
 656  E :    asm_.cmp(assm::al, assm::bl);
 657  E :    ASSERT_NO_REFS();
 658    :  
 659    :    // Simple immediate-register operation.
 660  E :    asm_.cmp(assm::al, Immediate(10, assm::kSize8Bit));
 661  E :    ASSERT_NO_REFS();
 662    :  
 663    :    // Simple register-register operation.
 664  E :    asm_.cmp(assm::eax, assm::ebx);
 665  E :    ASSERT_NO_REFS();
 666    :  
 667    :    // Simple immediate-register operation.
 668  E :    asm_.cmp(assm::eax, Immediate(10));
 669  E :    ASSERT_NO_REFS();
 670    :  
 671    :    // Immediate-with reference to register.
 672  E :    asm_.cmp(assm::eax, Immediate(test_block_, 0));
 673  E :    ASSERT_REFS(1, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_);
 674    :  
 675    :    // Torture test: both src and dst contain references.
 676  E :    asm_.cmp(Operand(Displacement(test_block_, 0)), Immediate(test_bb_));
 677    :    ASSERT_REFS(2, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_,
 678  E :                6, BasicBlockReference::REFERRED_TYPE_BASIC_BLOCK, test_bb_);
 679    :  
 680  E :    asm_.cmp(Operand(Displacement(test_block_, 0)), Immediate(10));
 681  E :    ASSERT_REFS(2, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_);
 682  E :  }
 683    :  
 684  E :  TEST_F(BasicBlockAssemblerTest, add) {
 685    :    // Simple register-register operation.
 686  E :    asm_.add(assm::al, assm::bl);
 687  E :    ASSERT_NO_REFS();
 688    :  
 689    :    // Simple immediate-register operation.
 690  E :    asm_.add(assm::al, Immediate(10, assm::kSize8Bit));
 691  E :    ASSERT_NO_REFS();
 692    :  
 693    :    // Simple register-register operation.
 694  E :    asm_.add(assm::eax, assm::ebx);
 695  E :    ASSERT_NO_REFS();
 696    :  
 697    :    // Simple immediate-register operation.
 698  E :    asm_.add(assm::eax, Immediate(10));
 699  E :    ASSERT_NO_REFS();
 700    :  
 701    :    // Immediate-with reference to register.
 702  E :    asm_.add(assm::eax, Immediate(test_block_, 0));
 703  E :    ASSERT_REFS(1, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_);
 704    :  
 705    :    // Torture test: both src and dst contain references.
 706  E :    asm_.add(Operand(Displacement(test_block_, 0)), Immediate(test_bb_));
 707    :    ASSERT_REFS(2, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_,
 708  E :                6, BasicBlockReference::REFERRED_TYPE_BASIC_BLOCK, test_bb_);
 709    :  
 710  E :    asm_.add(Operand(Displacement(test_block_, 0)), Immediate(10));
 711  E :    ASSERT_REFS(2, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_);
 712  E :  }
 713    :  
 714  E :  TEST_F(BasicBlockAssemblerTest, sub) {
 715    :    // Simple register-register operation.
 716  E :    asm_.sub(assm::al, assm::bl);
 717  E :    ASSERT_NO_REFS();
 718    :  
 719    :    // Simple immediate-register operation.
 720  E :    asm_.sub(assm::al, Immediate(10, assm::kSize8Bit));
 721  E :    ASSERT_NO_REFS();
 722    :  
 723    :    // Simple register-register operation.
 724  E :    asm_.sub(assm::eax, assm::ebx);
 725  E :    ASSERT_NO_REFS();
 726    :  
 727    :    // Simple immediate-register operation.
 728  E :    asm_.sub(assm::eax, Immediate(10));
 729  E :    ASSERT_NO_REFS();
 730    :  
 731    :    // Immediate-with reference to register.
 732  E :    asm_.sub(assm::eax, Immediate(test_block_, 0));
 733  E :    ASSERT_REFS(1, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_);
 734    :  
 735    :    // Torture test: both src and dst contain references.
 736  E :    asm_.sub(Operand(Displacement(test_block_, 0)), Immediate(test_bb_));
 737    :    ASSERT_REFS(2, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_,
 738  E :                6, BasicBlockReference::REFERRED_TYPE_BASIC_BLOCK, test_bb_);
 739    :  
 740  E :    asm_.sub(Operand(Displacement(test_block_, 0)), Immediate(10));
 741  E :    ASSERT_REFS(2, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_);
 742  E :  }
 743    :  
 744  E :  TEST_F(BasicBlockAssemblerTest, shl) {
 745    :    // Simple immediate-register operation.
 746  E :    asm_.shl(assm::eax, Immediate(1));
 747  E :    ASSERT_NO_REFS();
 748  E :  }
 749    :  
 750  E :  TEST_F(BasicBlockAssemblerTest, shr) {
 751    :    // Simple immediate-register operation.
 752  E :    asm_.shr(assm::eax, Immediate(1));
 753  E :    ASSERT_NO_REFS();
 754  E :  }
 755    :  
 756  E :  TEST_F(BasicBlockAssemblerTest, ret) {
 757  E :    asm_.ret();
 758  E :    ASSERT_NO_REFS();
 759    :  
 760  E :    asm_.ret(4);
 761  E :    ASSERT_NO_REFS();
 762  E :  }
 763    :  
 764  E :  TEST_F(BasicBlockAssemblerTest, xchg) {
 765  E :    asm_.xchg(assm::eax, assm::ecx);
 766  E :    ASSERT_NO_REFS();
 767    :  
 768  E :    asm_.xchg(assm::esp, assm::edx);
 769  E :    ASSERT_NO_REFS();
 770    :  
 771  E :    asm_.xchg(assm::ax, assm::cx);
 772  E :    ASSERT_NO_REFS();
 773    :  
 774  E :    asm_.xchg(assm::sp, assm::dx);
 775  E :    ASSERT_NO_REFS();
 776    :  
 777  E :    asm_.xchg(assm::al, assm::ch);
 778  E :    ASSERT_NO_REFS();
 779    :  
 780  E :    asm_.xchg(assm::dh, assm::bl);
 781  E :    ASSERT_NO_REFS();
 782  E :  }
 783    :  
 784  E :  TEST_F(BasicBlockAssemblerTest, UndefinedSourceRange) {
 785  E :    ASSERT_EQ(asm_.source_range(), SourceRange());
 786  E :    asm_.call(Immediate(test_block_, 0));
 787  E :    ASSERT_EQ(instructions_.back().source_range(), SourceRange());
 788  E :  }
 789    :  
 790  E :  TEST_F(BasicBlockAssemblerTest, SetSourceRange) {
 791  E :    SourceRange range(RelativeAddress(10), 10);
 792  E :    asm_.set_source_range(range);
 793  E :    asm_.call(Immediate(test_block_, 0));
 794  E :    ASSERT_EQ(instructions_.back().source_range(), range);
 795  E :  }
 796    :  
 797  E :  TEST_F(BasicBlockAssemblerTest, SetMultipleSourceRange) {
 798  E :    SourceRange range1(RelativeAddress(10), 10);
 799  E :    SourceRange range2(RelativeAddress(20), 20);
 800    :  
 801  E :    asm_.set_source_range(range1);
 802  E :    asm_.call(Immediate(test_block_, 0));
 803  E :    ASSERT_EQ(instructions_.back().source_range(), range1);
 804    :  
 805  E :    asm_.set_source_range(range2);
 806  E :    asm_.pop(assm::ebp);
 807  E :    ASSERT_EQ(instructions_.back().source_range(), range2);
 808    :  
 809  E :    asm_.ret(4);
 810  E :    ASSERT_EQ(instructions_.back().source_range(), range2);
 811  E :  }
 812    :  
 813    :  }  // namespace block_graph

Coverage information generated Thu Jan 14 17:40:38 2016.