Coverage for /Syzygy/block_graph/basic_block_assembler_unittest.cc

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

Coverage information generated Thu Mar 26 16:15:41 2015.