Coverage for /Syzygy/block_graph/basic_block_assembler.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
99.1%3283310.C++source

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    :  namespace block_graph {
  18    :  
  19    :  namespace {
  20    :  
  21    :  typedef core::DisplacementImpl DisplacementImpl;
  22    :  typedef core::OperandImpl OperandImpl;
  23    :  typedef core::ValueImpl ValueImpl;
  24    :  typedef core::ValueSize ValueSize;
  25    :  
  26  E :  ValueSize ValueSizeFromConstant(uint32 input_value) {
  27    :    // IA32 assembly may/will sign-extend 8-bit literals, so we attempt to encode
  28    :    // in 8 bits only those literals whose value will be unchanged by that
  29    :    // treatment.
  30  E :    input_value |= 0x7F;
  31    :  
  32  E :    if (input_value == 0xFFFFFFFF || input_value == 0x7F)
  33  E :      return core::kSize8Bit;
  34    :  
  35  E :    return core::kSize32Bit;
  36  E :  }
  37    :  
  38    :  ValueImpl CopyValue(const UntypedReference* ref,
  39  E :                      const core::ValueImpl& value) {
  40    :    return ValueImpl(value.value(),
  41    :                     value.size(),
  42  E :                     value.reference() ? ref : NULL);
  43  E :  }
  44    :  
  45  E :  size_t ToBytes(core::ValueSize size) {
  46  E :    switch (size) {
  47  E :      case core::kSize8Bit: return 1;
  48  E :      case core::kSize32Bit: return 4;
  49    :    }
  50  i :    NOTREACHED();
  51  i :    return 0;
  52  E :  }
  53    :  
  54    :  // Completes a UntypedReference, converting it to a BasicBlockReference
  55    :  // using the provided type and size information.
  56    :  // @param ref_info The type and size information to use.
  57    :  // @param untyped_ref The untyped reference to be completed.
  58    :  // @returns the equivalent BasicBlockReference.
  59    :  BasicBlockReference CompleteUntypedReference(
  60    :      BlockGraph::ReferenceType type,
  61    :      size_t size,
  62  E :      const UntypedReference& untyped_ref) {
  63  E :    DCHECK(untyped_ref.IsValid());
  64    :  
  65    :    if (untyped_ref.referred_type() ==
  66  E :            BasicBlockReference::REFERRED_TYPE_BLOCK) {
  67  E :      DCHECK(untyped_ref.block() != NULL);
  68    :      return BasicBlockReference(type, size, untyped_ref.block(),
  69  E :                                 untyped_ref.offset(), untyped_ref.base());
  70    :    }
  71    :  
  72    :    DCHECK_EQ(BasicBlockReference::REFERRED_TYPE_BASIC_BLOCK,
  73  E :              untyped_ref.referred_type());
  74  E :    DCHECK(untyped_ref.basic_block() != NULL);
  75  E :    return BasicBlockReference(type, size, untyped_ref.basic_block());
  76  E :  }
  77    :  
  78    :  }  // namespace
  79    :  
  80  E :  Value::Value() {
  81  E :  }
  82    :  
  83  E :  Value::Value(uint32 value) : value_(value, ValueSizeFromConstant(value)) {
  84  E :  }
  85    :  
  86  E :  Value::Value(uint32 value, ValueSize size) : value_(value, size) {
  87  E :  }
  88    :  
  89    :  Value::Value(BasicBlock* bb)
  90    :      : reference_(bb),
  91  E :        value_(0, core::kSize32Bit, &reference_) {
  92  E :  }
  93    :  
  94    :  Value::Value(Block* block, Offset offset)
  95    :      : reference_(block, offset, offset),
  96  E :        value_(0, core::kSize32Bit, &reference_) {
  97  E :  }
  98    :  
  99    :  Value::Value(Block* block, Offset offset, Offset base)
 100    :      : reference_(block, offset, base),
 101    :        value_(0, core::kSize32Bit, &reference_) {
 102    :  }
 103    :  
 104    :  Value::Value(uint32 value, ValueSize size, const UntypedReference& ref)
 105  E :      : reference_(ref), value_(value, size, &reference_) {
 106  E :    DCHECK(ref.IsValid());
 107  E :  }
 108    :  
 109    :  Value::Value(const Value& other)
 110    :      : reference_(other.reference()),
 111  E :        value_(CopyValue(&reference_, other.value_)) {
 112  E :  }
 113    :  
 114    :  Value::Value(const UntypedReference& ref, const ValueImpl& value)
 115  E :      : reference_(ref), value_(CopyValue(&reference_, value)) {
 116  E :  }
 117    :  
 118  E :  Value::~Value() {
 119    :  #ifndef NDEBUG
 120  E :    if (reference_.IsValid()) {
 121  E :      DCHECK(value_.reference() == &reference_);
 122  E :    } else {
 123  E :      DCHECK(value_.reference() == NULL);
 124    :    }
 125    :  #endif
 126  E :  }
 127    :  
 128  E :  const Value& Value::operator=(const Value& other) {
 129  E :    reference_ = other.reference_;
 130  E :    value_ = CopyValue(&reference_, other.value_);
 131  E :    return *this;
 132  E :  }
 133    :  
 134  E :  bool Value::operator==(const Value& rhs) const {
 135  E :    if (reference_.IsValid())
 136  i :      return reference_ == rhs.reference();
 137  E :    return value_ == rhs.value_;
 138  E :  }
 139    :  
 140  E :  Operand::Operand(core::Register base) : operand_(base) {
 141  E :  }
 142    :  
 143    :  Operand::Operand(core::Register base, const Displacement& displ)
 144    :      : reference_(displ.reference()),
 145  E :        operand_(base, CopyValue(&reference_, displ.value_)) {
 146  E :  }
 147    :  
 148    :  Operand::Operand(const Displacement& displ)
 149    :      : reference_(displ.reference()),
 150  E :        operand_(CopyValue(&reference_, displ.value_)) {
 151  E :  }
 152    :  
 153    :  Operand::Operand(core::Register base,
 154    :                   core::Register index,
 155    :                   core::ScaleFactor scale,
 156    :                   const Displacement& displ)
 157    :      : reference_(displ.reference_),
 158  E :        operand_(base, index, scale, CopyValue(&reference_, displ.value_)) {
 159  E :  }
 160    :  
 161    :  Operand::Operand(core::Register base,
 162    :                   core::Register index,
 163    :                   core::ScaleFactor scale)
 164  E :      : operand_(base, index, scale) {
 165  E :  }
 166    :  
 167    :  Operand::Operand(core::Register index,
 168    :                   core::ScaleFactor scale,
 169    :                   const Displacement& displ)
 170    :      : reference_(displ.reference_),
 171  E :        operand_(index, scale, CopyValue(&reference_, displ.value_)) {
 172  E :  }
 173    :  
 174    :  Operand::Operand(const Operand& o)
 175    :      : reference_(o.reference_),
 176    :        operand_(o.base(), o.index(), o.scale(),
 177  E :                 CopyValue(&reference_, o.operand_.displacement())) {
 178  E :  }
 179    :  
 180  E :  Operand::~Operand() {
 181    :  #ifndef NDEBUG
 182  E :    if (reference_.IsValid()) {
 183  E :      DCHECK(operand_.displacement().reference() == &reference_);
 184  E :    } else {
 185  E :      DCHECK(operand_.displacement().reference() == NULL);
 186    :    }
 187    :  #endif
 188  E :  }
 189    :  
 190  E :  const Operand& Operand::operator=(const Operand& other) {
 191  E :    reference_ = other.reference_;
 192    :    operand_ =
 193    :        core::OperandImpl(other.base(), other.index(), other.scale(),
 194  E :                          CopyValue(&reference_, other.operand_.displacement()));
 195  E :    return *this;
 196  E :  }
 197    :  
 198    :  BasicBlockAssembler::BasicBlockSerializer::BasicBlockSerializer(
 199    :      const Instructions::iterator& where, Instructions* list)
 200  E :          : where_(where), list_(list), num_ref_infos_(0) {
 201  E :    DCHECK(list != NULL);
 202  E :  }
 203    :  
 204    :  void BasicBlockAssembler::BasicBlockSerializer::AppendInstruction(
 205    :      uint32 location, const uint8* bytes, size_t num_bytes,
 206  E :      const size_t *ref_locations, const void* const* refs, size_t num_refs) {
 207    :    // The number of reference infos we've been provided must match the number of
 208    :    // references we have been given.
 209  E :    DCHECK_EQ(num_ref_infos_, num_refs);
 210    :  
 211  E :    Instruction instruction;
 212  E :    CHECK(Instruction::FromBuffer(bytes, num_bytes, &instruction));
 213  E :    instruction.set_source_range(source_range_);
 214    :  
 215  E :    Instructions::iterator it = list_->insert(where_, instruction);
 216    :  
 217  E :    for (size_t i = 0; i < num_refs; ++i) {
 218    :      const UntypedReference* tref =
 219  E :          reinterpret_cast<const UntypedReference*>(refs[i]);
 220  E :      DCHECK(tref != NULL);
 221    :  
 222    :      BasicBlockReference bbref = CompleteUntypedReference(
 223  E :          ref_infos_[i].type, ref_infos_[i].size, *tref);
 224  E :      DCHECK(bbref.IsValid());
 225  E :      it->SetReference(ref_locations[i], bbref);
 226  E :    }
 227    :  
 228    :    // Clear the reference info for the next instruction.
 229  E :    num_ref_infos_ = 0;
 230  E :  }
 231    :  
 232    :  void BasicBlockAssembler::BasicBlockSerializer::PushReferenceInfo(
 233  E :      BlockGraph::ReferenceType type, core::ValueSize size) {
 234  E :    DCHECK_GT(2u, num_ref_infos_);
 235  E :    ref_infos_[num_ref_infos_].type = type;
 236  E :    ref_infos_[num_ref_infos_].size = ToBytes(size);
 237  E :    ++num_ref_infos_;
 238  E :  }
 239    :  
 240    :  BasicBlockAssembler::BasicBlockAssembler(const Instructions::iterator& where,
 241    :                                           Instructions* list)
 242  E :      : serializer_(where, list), asm_(0, &serializer_) {
 243  E :  }
 244    :  
 245    :  BasicBlockAssembler::BasicBlockAssembler(uint32 location,
 246    :                                           const Instructions::iterator& where,
 247    :                                           Instructions* list)
 248  E :      : serializer_(where, list), asm_(location, &serializer_) {
 249  E :  }
 250    :  
 251  E :  void BasicBlockAssembler::call(const Immediate& dst) {
 252    :    // In the context of BasicBlockAssembler it only makes sense for calls with
 253    :    // immediate parameters to be backed by a 32-bit reference.
 254  E :    PushMandatoryReferenceInfo(BlockGraph::PC_RELATIVE_REF, dst);
 255  E :    CheckReferenceSize(core::kSize32Bit, dst);
 256  E :    asm_.call(dst.value_);
 257  E :  }
 258    :  
 259  E :  void BasicBlockAssembler::call(const Operand& dst) {
 260    :    // If a call is backed by a reference it must be 32-bit.
 261  E :    PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, dst);
 262  E :    CheckReferenceSize(core::kSize32Bit, dst);
 263  E :    asm_.call(dst.operand_);
 264  E :  }
 265    :  
 266  E :  void BasicBlockAssembler::jmp(const Immediate& dst) {
 267    :    // In the context of BasicBlockAssembler it only makes sense for jumps with
 268    :    // immediate parameters to be backed by a reference.
 269  E :    PushMandatoryReferenceInfo(BlockGraph::PC_RELATIVE_REF, dst);
 270  E :    asm_.jmp(dst.value_);
 271  E :  }
 272    :  
 273  E :  void BasicBlockAssembler::jmp(const Operand& dst) {
 274  E :    PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, dst);
 275  E :    asm_.jmp(dst.operand_);
 276  E :  }
 277    :  
 278  E :  void BasicBlockAssembler::j(ConditionCode code, const Immediate& dst) {
 279    :    // In the context of BasicBlockAssembler it only makes sense for jumps with
 280    :    // immediate parameters to be backed by a reference.
 281  E :    PushMandatoryReferenceInfo(BlockGraph::PC_RELATIVE_REF, dst);
 282  E :    asm_.j(code, dst.value_);
 283  E :  }
 284    :  
 285  E :  void BasicBlockAssembler::set(ConditionCode code, Register dst) {
 286  E :    asm_.set(code, dst);
 287  E :  }
 288    :  
 289  E :  void BasicBlockAssembler::pushfd() {
 290  E :    asm_.pushfd();
 291  E :  }
 292    :  
 293  E :  void BasicBlockAssembler::popfd() {
 294  E :    asm_.popfd();
 295  E :  }
 296    :  
 297  E :  void BasicBlockAssembler::lahf() {
 298  E :    asm_.lahf();
 299  E :  }
 300    :  
 301  E :  void BasicBlockAssembler::sahf() {
 302  E :    asm_.sahf();
 303  E :  }
 304    :  
 305  E :  void BasicBlockAssembler::test_b(Register dst, Register src) {
 306  E :    asm_.test_b(dst, src);
 307  E :  }
 308    :  
 309  E :  void BasicBlockAssembler::test_b(Register dst, const Immediate& src) {
 310  E :    PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
 311  E :    asm_.test_b(dst, src.value_);
 312  E :  }
 313    :  
 314  E :  void BasicBlockAssembler::test(Register dst, Register src) {
 315  E :    asm_.test(dst, src);
 316  E :  }
 317    :  
 318    :  void BasicBlockAssembler::test(Register dst, const Operand& src) {
 319    :    PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
 320    :    asm_.test(dst, src.operand_);
 321    :  }
 322    :  
 323    :  void BasicBlockAssembler::test(const Operand& dst, Register src) {
 324    :    PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, dst);
 325    :    asm_.test(dst.operand_, src);
 326    :  }
 327    :  
 328  E :  void BasicBlockAssembler::test(Register dst, const Immediate& src) {
 329  E :    PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
 330  E :    asm_.test(dst, src.value_);
 331  E :  }
 332    :  
 333  E :  void BasicBlockAssembler::test(const Operand&  dst, const Immediate& src) {
 334  E :    PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, dst);
 335  E :    PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
 336  E :    asm_.test(dst.operand_, src.value_);
 337  E :  }
 338    :  
 339  E :  void BasicBlockAssembler::cmp_b(Register dst, Register src) {
 340  E :    asm_.cmp_b(dst, src);
 341  E :  }
 342    :  
 343  E :  void BasicBlockAssembler::cmp_b(Register dst, const Immediate& src) {
 344  E :    PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
 345  E :    asm_.cmp_b(dst, src.value_);
 346  E :  }
 347    :  
 348  E :  void BasicBlockAssembler::cmp(Register dst, Register src) {
 349  E :    asm_.cmp(dst, src);
 350  E :  }
 351    :  
 352    :  void BasicBlockAssembler::cmp(Register dst, const Operand& src) {
 353    :    PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
 354    :    asm_.cmp(dst, src.operand_);
 355    :  }
 356    :  
 357    :  void BasicBlockAssembler::cmp(const Operand& dst, Register src) {
 358    :    PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, dst);
 359    :    asm_.cmp(dst.operand_, src);
 360    :  }
 361    :  
 362  E :  void BasicBlockAssembler::cmp(Register dst, const Immediate& src) {
 363  E :    PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
 364  E :    asm_.cmp(dst, src.value_);
 365  E :  }
 366    :  
 367  E :  void BasicBlockAssembler::cmp(const Operand&  dst, const Immediate& src) {
 368  E :    PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, dst);
 369  E :    PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
 370  E :    asm_.cmp(dst.operand_, src.value_);
 371  E :  }
 372    :  
 373  E :  void BasicBlockAssembler::add_b(Register dst, Register src) {
 374  E :    asm_.add_b(dst, src);
 375  E :  }
 376    :  
 377  E :  void BasicBlockAssembler::add_b(Register dst, const Immediate& src) {
 378  E :    PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
 379  E :    asm_.add_b(dst, src.value_);
 380  E :  }
 381    :  
 382  E :  void BasicBlockAssembler::add(Register dst, Register src) {
 383  E :    asm_.add(dst, src);
 384  E :  }
 385    :  
 386    :  void BasicBlockAssembler::add(Register dst, const Operand& src) {
 387    :    PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
 388    :    asm_.add(dst, src.operand_);
 389    :  }
 390    :  
 391    :  void BasicBlockAssembler::add(const Operand& dst, Register src) {
 392    :    PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, dst);
 393    :    asm_.add(dst.operand_, src);
 394    :  }
 395    :  
 396  E :  void BasicBlockAssembler::add(Register dst, const Immediate& src) {
 397  E :    PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
 398  E :    asm_.add(dst, src.value_);
 399  E :  }
 400    :  
 401  E :  void BasicBlockAssembler::add(const Operand& dst, const Immediate& src) {
 402  E :    PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, dst);
 403  E :    PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
 404  E :    asm_.add(dst.operand_, src.value_);
 405  E :  }
 406    :  
 407  E :  void BasicBlockAssembler::sub_b(Register dst, Register src) {
 408  E :    asm_.sub_b(dst, src);
 409  E :  }
 410    :  
 411  E :  void BasicBlockAssembler::sub_b(Register dst, const Immediate& src) {
 412  E :    PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
 413  E :    asm_.sub_b(dst, src.value_);
 414  E :  }
 415    :  
 416  E :  void BasicBlockAssembler::sub(Register dst, Register src) {
 417  E :    asm_.sub(dst, src);
 418  E :  }
 419    :  
 420    :  void BasicBlockAssembler::sub(Register dst, const Operand& src) {
 421    :    PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
 422    :    asm_.sub(dst, src.operand_);
 423    :  }
 424    :  
 425    :  void BasicBlockAssembler::sub(const Operand& dst, Register src) {
 426    :    PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, dst);
 427    :    asm_.sub(dst.operand_, src);
 428    :  }
 429    :  
 430  E :  void BasicBlockAssembler::sub(Register dst, const Immediate& src) {
 431  E :    PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
 432  E :    asm_.sub(dst, src.value_);
 433  E :  }
 434    :  
 435  E :  void BasicBlockAssembler::sub(const Operand& dst, const Immediate& src) {
 436  E :    PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, dst);
 437  E :    PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
 438  E :    asm_.sub(dst.operand_, src.value_);
 439  E :  }
 440    :  
 441  E :  void BasicBlockAssembler::shl(Register dst, const Immediate& src) {
 442  E :    PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
 443  E :    asm_.shl(dst, src.value_);
 444  E :  }
 445    :  
 446  E :  void BasicBlockAssembler::shr(Register dst, const Immediate& src) {
 447  E :    PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
 448  E :    asm_.shr(dst, src.value_);
 449  E :  }
 450    :  
 451  E :  void BasicBlockAssembler::mov_b(const Operand& dst, const Immediate& src) {
 452  E :    PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, dst);
 453  E :    PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
 454  E :    CheckReferenceSize(core::kSize32Bit, dst);
 455  E :    CheckReferenceSize(core::kSize32Bit, src);
 456  E :    asm_.mov_b(dst.operand_, src.value_);
 457  E :  }
 458    :  
 459  E :  void BasicBlockAssembler::movzx_b(Register dst, const Operand& src) {
 460  E :    PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
 461  E :    CheckReferenceSize(core::kSize32Bit, src);
 462  E :    asm_.movzx_b(dst, src.operand_);
 463  E :  }
 464    :  
 465  E :  void BasicBlockAssembler::mov(Register dst, Register src) {
 466  E :    asm_.mov(dst, src);
 467  E :  }
 468    :  
 469  E :  void BasicBlockAssembler::mov(Register dst, const Operand& src) {
 470  E :    PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
 471  E :    CheckReferenceSize(core::kSize32Bit, src);
 472  E :    asm_.mov(dst, src.operand_);
 473  E :  }
 474    :  
 475  E :  void BasicBlockAssembler::mov(const Operand& dst, Register src) {
 476  E :    PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, dst);
 477  E :    CheckReferenceSize(core::kSize32Bit, dst);
 478  E :    asm_.mov(dst.operand_, src);
 479  E :  }
 480    :  
 481  E :  void BasicBlockAssembler::mov(Register dst, const Immediate& src) {
 482  E :    PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
 483  E :    CheckReferenceSize(core::kSize32Bit, src);
 484  E :    asm_.mov(dst, src.value_);
 485  E :  }
 486    :  
 487  E :  void BasicBlockAssembler::mov(const Operand& dst, const Immediate& src) {
 488  E :    PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, dst);
 489  E :    PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
 490  E :    CheckReferenceSize(core::kSize32Bit, dst);
 491  E :    CheckReferenceSize(core::kSize32Bit, src);
 492  E :    asm_.mov(dst.operand_, src.value_);
 493  E :  }
 494    :  
 495  E :  void BasicBlockAssembler::mov_fs(Register dst, const Operand& src) {
 496  E :    PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
 497  E :    CheckReferenceSize(core::kSize32Bit, src);
 498  E :    asm_.mov_fs(dst, src.operand_);
 499  E :  }
 500    :  
 501  E :  void BasicBlockAssembler::mov_fs(const Operand& dst, Register src) {
 502  E :    PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, dst);
 503  E :    CheckReferenceSize(core::kSize32Bit, dst);
 504  E :    asm_.mov_fs(dst.operand_, src);
 505  E :  }
 506    :  
 507  E :  void BasicBlockAssembler::lea(Register dst, const Operand& src) {
 508  E :    PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
 509  E :    CheckReferenceSize(core::kSize32Bit, src);
 510  E :    asm_.lea(dst, src.operand_);
 511  E :  }
 512    :  
 513  E :  void BasicBlockAssembler::push(Register src) {
 514  E :    asm_.push(src);
 515  E :  }
 516    :  
 517  E :  void BasicBlockAssembler::push(const Immediate& src) {
 518  E :    PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
 519  E :    CheckReferenceSize(core::kSize32Bit, src);
 520  E :    asm_.push(src.value_);
 521  E :  }
 522    :  
 523  E :  void BasicBlockAssembler::push(const Operand& src) {
 524  E :    PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
 525  E :    CheckReferenceSize(core::kSize32Bit, src);
 526  E :    asm_.push(src.operand_);
 527  E :  }
 528    :  
 529  E :  void BasicBlockAssembler::pop(Register dst) {
 530  E :    asm_.pop(dst);
 531  E :  }
 532    :  
 533  E :  void BasicBlockAssembler::pop(const Operand& dst) {
 534  E :    PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, dst);
 535  E :    CheckReferenceSize(core::kSize32Bit, dst);
 536  E :    asm_.pop(dst.operand_);
 537  E :  }
 538    :  
 539  E :  void BasicBlockAssembler::ret() {
 540  E :    asm_.ret();
 541  E :  }
 542    :  
 543  E :  void BasicBlockAssembler::ret(uint16 n) {
 544  E :    asm_.ret(n);
 545  E :  }
 546    :  
 547    :  void BasicBlockAssembler::PushMandatoryReferenceInfo(
 548  E :      ReferenceType type, const Immediate& imm) {
 549  E :    DCHECK(imm.value_.reference() != NULL);
 550  E :    serializer_.PushReferenceInfo(type, imm.value_.size());
 551  E :  }
 552    :  
 553    :  void BasicBlockAssembler::PushOptionalReferenceInfo(
 554  E :      ReferenceType type, const Immediate& imm) {
 555  E :    if (imm.value_.reference() == NULL)
 556  E :      return;
 557  E :    serializer_.PushReferenceInfo(type, imm.value_.size());
 558  E :  }
 559    :  
 560    :  void BasicBlockAssembler::PushOptionalReferenceInfo(
 561  E :      ReferenceType type, const Operand& op) {
 562  E :    if (op.operand_.displacement().reference() == NULL)
 563  E :      return;
 564  E :    serializer_.PushReferenceInfo(type, op.operand_.displacement().size());
 565  E :  }
 566    :  
 567    :  void BasicBlockAssembler::CheckReferenceSize(
 568  E :      core::ValueSize size, const Immediate& imm) const {
 569  E :    DCHECK(imm.value_.reference() == NULL || imm.value_.size() == size);
 570  E :  }
 571    :  
 572    :  void BasicBlockAssembler::CheckReferenceSize(
 573  E :      core::ValueSize size, const Operand& op) const {
 574    :    DCHECK(op.operand_.displacement().reference() == NULL ||
 575  E :           op.operand_.displacement().size() == size);
 576  E :  }
 577    :  
 578    :  }  // namespace block_graph

Coverage information generated Thu Jul 04 09:34:53 2013.