Coverage for /Syzygy/block_graph/analysis/liveness_analysis.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
94.8%2933090.C++source

Line-by-line coverage:

   1    :  // Copyright 2013 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/analysis/liveness_analysis.h"
  16    :  
  17    :  #include <set>
  18    :  #include <stack>
  19    :  #include <vector>
  20    :  
  21    :  #include "syzygy/block_graph/analysis/control_flow_analysis.h"
  22    :  #include "syzygy/block_graph/analysis/liveness_analysis_internal.h"
  23    :  #include "syzygy/core/assembler.h"
  24    :  #include "syzygy/core/disassembler_util.h"
  25    :  
  26    :  #include "mnemonics.h"  // NOLINT
  27    :  
  28    :  namespace block_graph {
  29    :  namespace analysis {
  30    :  namespace {
  31    :  
  32    :  using core::Register;
  33    :  typedef BasicBlockSubGraph::BBCollection BBCollection;
  34    :  typedef block_graph::BasicBlockSubGraph::BasicBlock BasicBlock;
  35    :  typedef block_graph::BasicBlockSubGraph::BasicBlock::Instructions Instructions;
  36    :  typedef block_graph::BasicBlockSubGraph::BasicBlock::Successors Successors;
  37    :  typedef block_graph::BasicBlockSubGraph::BasicCodeBlock BasicCodeBlock;
  38    :  typedef block_graph::Instruction::Representation Representation;
  39    :  typedef ControlFlowAnalysis::BasicBlockOrdering BasicBlockOrdering;
  40    :  typedef LivenessAnalysis::State State;
  41    :  typedef LivenessAnalysis::State::RegisterMask RegisterMask;
  42    :  typedef LivenessAnalysis::State::FlagsMask FlagsMask;
  43    :  
  44    :  }  // namespace
  45    :  
  46    :  State::State()
  47  E :      : flags_(StateHelper::REGBITS_ALL), registers_(StateHelper::REGBITS_ALL) {
  48  E :  }
  49    :  
  50  E :  State::State(const State& state) {
  51  E :    StateHelper::Copy(state, this);
  52  E :  }
  53    :  
  54  E :  bool State::IsLive(const Register& reg) const {
  55    :    // Convert from core::Register representation of registers to the bits
  56    :    // representation we use internally, by way of the Distorm _RegisterType.
  57    :    RegisterMask mask = StateHelper::RegisterToRegisterMask(
  58  E :        core::GetRegisterType(reg));
  59  E :    return StateHelper::IsPartiallySet(*this, mask);
  60  E :  }
  61    :  
  62  E :  bool State::AreArithmeticFlagsLive() const {
  63  E :    return StateHelper::AreArithmeticFlagsLive(*this);
  64  E :  }
  65    :  
  66  E :  LivenessAnalysis::LivenessAnalysis() : live_in_() {
  67  E :  }
  68    :  
  69    :  void LivenessAnalysis::GetStateAtEntryOf(const BasicBlock* bb,
  70  E :                                           State* state) const {
  71    :    // This function accepts a NULL basic block and returns a safe state with all
  72    :    // registers alive.
  73  E :    DCHECK(state != NULL);
  74    :  
  75  E :    if (bb != NULL) {
  76  E :      LiveMap::const_iterator look = live_in_.find(bb);
  77  E :      if (look != live_in_.end()) {
  78  E :        StateHelper::Copy(look->second, state);
  79  E :        return;
  80    :      }
  81    :    }
  82    :  
  83  E :    StateHelper::SetAll(state);
  84  E :  }
  85    :  
  86    :  void LivenessAnalysis::GetStateAtExitOf(const BasicBlock* bb,
  87  E :                                          State* state) const {
  88    :    // This function accepts a NULL basic block and returns a safe state with all
  89    :    // registers alive.
  90  E :    DCHECK(state != NULL);
  91    :  
  92    :    // Initialize liveness information assuming all registers are alive.
  93  E :    StateHelper::SetAll(state);
  94    :  
  95  E :    const BasicCodeBlock* code = BasicCodeBlock::Cast(bb);
  96  E :    if (code == NULL)
  97  E :      return;
  98    :  
  99  E :    const BasicBlock::Successors& successors = code->successors();
 100  E :    if (successors.empty())
 101  E :      return;
 102    :  
 103    :    // Merge current liveness information with every successor information.
 104  E :    StateHelper::Clear(state);
 105  E :    Successors::const_iterator succ_end = successors.end();
 106  E :    for (Successors::const_iterator succ = successors.begin();
 107  E :         succ != succ_end; ++succ) {
 108  E :      BasicBlock* successor_basic_block = succ->reference().basic_block();
 109  E :      if (successor_basic_block == NULL) {
 110    :        // Successor is not a BasicBlock. Assume all registers are alive.
 111  E :        StateHelper::SetAll(state);
 112  E :        return;
 113    :      }
 114    :  
 115    :      // Merge successor state into current state.
 116  E :      State successor_state;
 117  E :      GetStateAtEntryOf(successor_basic_block, &successor_state);
 118  E :      StateHelper::Union(successor_state, state);
 119    :  
 120    :      // Merge liveness information from the implicit instruction in successor.
 121  E :      if (StateHelper::GetUsesOf(*succ, &successor_state))
 122  E :        StateHelper::Union(successor_state, state);
 123  E :      else
 124  i :        StateHelper::SetAll(state);
 125  E :    }
 126  E :  }
 127    :  
 128    :  void LivenessAnalysis::PropagateBackward(const Instruction& instr,
 129  E :                                           State* state) {
 130  E :    DCHECK(state != NULL);
 131    :  
 132    :    // Skip 'nop' instructions. It's better to skip them (i.e. mov %eax, %eax).
 133  E :    if (instr.IsNop())
 134  E :      return;
 135    :  
 136    :    // Remove 'defs' from current state.
 137  E :    State defs;
 138  E :    if (StateHelper::GetDefsOf(instr, &defs))
 139  E :      StateHelper::Subtract(defs, state);
 140    :  
 141  E :    if (instr.IsCall() || instr.IsReturn()) {
 142    :      // TODO(etienneb): Can we verify the calling convention? If so we can do
 143    :      // better than SetAll here.
 144  E :      StateHelper::SetAll(state);
 145  E :    } else if (instr.IsBranch() ||
 146    :               instr.IsInterrupt() ||
 147  E :               instr.IsControlFlow()) {
 148    :      // Don't mess with these instructions.
 149  E :      StateHelper::SetAll(state);
 150    :    }
 151    :  
 152    :    // Add 'uses' of instruction to current state, or assume all alive when 'uses'
 153    :    // information is not available.
 154  E :    State uses;
 155  E :    if (StateHelper::GetUsesOf(instr, &uses))
 156  E :      StateHelper::Union(uses, state);
 157  E :    else
 158  E :      StateHelper::SetAll(state);
 159  E :  }
 160    :  
 161  E :  void LivenessAnalysis::Analyze(const BasicBlockSubGraph* subgraph) {
 162  E :    DCHECK(subgraph != NULL);
 163  E :    DCHECK(live_in_.empty());
 164    :  
 165    :    // Produce a post-order basic blocks ordering.
 166  E :    const BBCollection& basic_blocks = subgraph->basic_blocks();
 167  E :    std::vector<const BasicCodeBlock*> order;
 168  E :    ControlFlowAnalysis::FlattenBasicBlocksInPostOrder(basic_blocks, &order);
 169    :  
 170    :    // Initialize liveness information of each basic block (empty set).
 171  E :    BasicBlockOrdering::const_iterator fw_iter = order.begin();
 172  E :    for (; fw_iter != order.end(); ++fw_iter)
 173  E :      StateHelper::Clear(&live_in_[*fw_iter]);
 174    :  
 175    :    // Propagate liveness information until stable (fix-point). Each set may only
 176    :    // grow, thus we have a halting condition.
 177  E :    bool changed = true;
 178  E :    while (changed) {
 179  E :      changed = false;
 180    :  
 181  E :      BasicBlockOrdering::const_iterator  bb_iter = order.begin();
 182  E :      for (; bb_iter != order.end(); ++bb_iter) {
 183  E :        const BasicCodeBlock* bb = *bb_iter;
 184    :  
 185    :        // Merge current liveness information with every successor information.
 186  E :        State state;
 187  E :        GetStateAtExitOf(bb, &state);
 188    :  
 189    :        // Propagate liveness information backward until the basic block entry.
 190  E :        const Instructions& instructions = bb->instructions();
 191  E :        Instructions::const_reverse_iterator instr_iter = instructions.rbegin();
 192  E :        for (; instr_iter != instructions.rend(); ++instr_iter)
 193  E :          PropagateBackward(*instr_iter, &state);
 194    :  
 195    :        // Commit liveness information to the global state.
 196  E :        if (StateHelper::Union(state, &live_in_[bb]))
 197  E :          changed = true;
 198  E :      }
 199  E :    }
 200  E :  }
 201    :  
 202  E :  RegisterMask LivenessAnalysis::StateHelper::RegisterToRegisterMask(uint8 reg) {
 203  E :    switch (reg) {
 204    :      case R_AL:
 205  E :        return LivenessAnalysis::StateHelper::REGBITS_AL;
 206    :      case R_AH:
 207  E :        return LivenessAnalysis::StateHelper::REGBITS_AH;
 208    :      case R_AX:
 209  E :        return LivenessAnalysis::StateHelper::REGBITS_AX;
 210    :      case R_EAX:
 211  E :        return LivenessAnalysis::StateHelper::REGBITS_EAX;
 212    :      case R_RAX:
 213  i :        return LivenessAnalysis::StateHelper::REGBITS_RAX;
 214    :      case R_BL:
 215  E :        return LivenessAnalysis::StateHelper::REGBITS_BL;
 216    :      case R_BH:
 217  E :        return LivenessAnalysis::StateHelper::REGBITS_BH;
 218    :      case R_BX:
 219  E :        return LivenessAnalysis::StateHelper::REGBITS_BX;
 220    :      case R_EBX:
 221  E :        return LivenessAnalysis::StateHelper::REGBITS_EBX;
 222    :      case R_RBX:
 223  i :        return LivenessAnalysis::StateHelper::REGBITS_RBX;
 224    :      case R_CL:
 225  E :        return LivenessAnalysis::StateHelper::REGBITS_CL;
 226    :      case R_CH:
 227  E :        return LivenessAnalysis::StateHelper::REGBITS_CH;
 228    :      case R_CX:
 229  E :        return LivenessAnalysis::StateHelper::REGBITS_CX;
 230    :      case R_ECX:
 231  E :        return LivenessAnalysis::StateHelper::REGBITS_ECX;
 232    :      case R_RCX:
 233  i :        return LivenessAnalysis::StateHelper::REGBITS_RCX;
 234    :      case R_DL:
 235  E :        return LivenessAnalysis::StateHelper::REGBITS_DL;
 236    :      case R_DH:
 237  E :        return LivenessAnalysis::StateHelper::REGBITS_DH;
 238    :      case R_DX:
 239  E :        return LivenessAnalysis::StateHelper::REGBITS_DX;
 240    :      case R_EDX:
 241  E :        return LivenessAnalysis::StateHelper::REGBITS_EDX;
 242    :      case R_RDX:
 243  i :        return LivenessAnalysis::StateHelper::REGBITS_RDX;
 244    :      case R_SI:
 245  E :        return LivenessAnalysis::StateHelper::REGBITS_SI;
 246    :      case R_ESI:
 247  E :        return LivenessAnalysis::StateHelper::REGBITS_ESI;
 248    :      case R_RSI:
 249  i :        return LivenessAnalysis::StateHelper::REGBITS_RSI;
 250    :      case R_DI:
 251  E :        return LivenessAnalysis::StateHelper::REGBITS_DI;
 252    :      case R_EDI:
 253  E :        return LivenessAnalysis::StateHelper::REGBITS_EDI;
 254    :      case R_RDI:
 255  i :        return LivenessAnalysis::StateHelper::REGBITS_RDI;
 256    :      case R_SP:
 257  E :        return LivenessAnalysis::StateHelper::REGBITS_SP;
 258    :      case R_ESP:
 259  E :        return LivenessAnalysis::StateHelper::REGBITS_ESP;
 260    :      case R_RSP:
 261  i :        return LivenessAnalysis::StateHelper::REGBITS_RSP;
 262    :      case R_BP:
 263  E :        return LivenessAnalysis::StateHelper::REGBITS_BP;
 264    :      case R_EBP:
 265  E :        return LivenessAnalysis::StateHelper::REGBITS_EBP;
 266    :      case R_RBP:
 267  i :        return LivenessAnalysis::StateHelper::REGBITS_RBP;
 268    :      default:
 269    :        // Unhandled registers are ignored.
 270  E :        return 0;
 271    :    }
 272    :  
 273  i :    NOTREACHED();
 274  E :  }
 275    :  
 276  E :  void LivenessAnalysis::StateHelper::Clear(State* state) {
 277  E :    DCHECK(state != NULL);
 278  E :    state->flags_ = 0;
 279  E :    state->registers_ = 0;
 280  E :  }
 281    :  
 282  E :  void LivenessAnalysis::StateHelper::SetAll(State* state) {
 283  E :    DCHECK(state != NULL);
 284  E :    state->flags_ = StateHelper::REGBITS_ALL;
 285  E :    state->registers_ = REGBITS_ALL;
 286  E :  }
 287    :  
 288    :  bool LivenessAnalysis::StateHelper::AreArithmeticFlagsLive(
 289  E :      const State& state) {
 290  E :    return (state.flags_ & (D_ZF | D_SF | D_CF | D_OF | D_PF | D_AF)) != 0;
 291  E :  }
 292    :  
 293    :  bool LivenessAnalysis::StateHelper::IsSet(
 294  E :      const State& state, RegisterMask mask) {
 295  E :    return (state.registers_ & mask) == mask;
 296  E :  }
 297    :  
 298    :  bool LivenessAnalysis::StateHelper::IsPartiallySet(
 299  E :      const State& state, RegisterMask mask) {
 300  E :    return (state.registers_ & mask) != 0;
 301  E :  }
 302    :  
 303  E :  void LivenessAnalysis::StateHelper::Set(RegisterMask mask, State* state) {
 304  E :    DCHECK(state != NULL);
 305  E :    state->registers_ |= mask;
 306  E :  }
 307    :  
 308  E :  void LivenessAnalysis::StateHelper::SetFlags(FlagsMask mask, State* state) {
 309  E :    DCHECK(state != NULL);
 310  E :    state->flags_ |= mask;
 311  E :  }
 312    :  
 313  E :  void LivenessAnalysis::StateHelper::Copy(const State& src, State* state) {
 314  E :    DCHECK(state != NULL);
 315  E :    state->flags_ = src.flags_;
 316  E :    state->registers_ = src.registers_;
 317  E :  }
 318    :  
 319  E :  bool LivenessAnalysis::StateHelper::Union(const State& src, State* state) {
 320  E :    DCHECK(state != NULL);
 321    :  
 322    :    bool changed = ((state->flags_ | src.flags_) != state->flags_) ||
 323  E :                   ((state->registers_ | src.registers_) != state->registers_);
 324  E :    state->flags_ |= src.flags_;
 325  E :    state->registers_ |= src.registers_;
 326  E :    return changed;
 327  E :  }
 328    :  
 329  E :  void LivenessAnalysis::StateHelper::Subtract(const State& src, State* state) {
 330  E :    DCHECK(state != NULL);
 331  E :    state->flags_ &= ~(src.flags_);
 332  E :    state->registers_ &= ~(src.registers_);
 333  E :  }
 334    :  
 335    :  void LivenessAnalysis::StateHelper::StateDefOperand(
 336  E :      const _Operand& operand, State* state) {
 337  E :    DCHECK(state != NULL);
 338  E :    if (operand.type == O_REG)
 339  E :      Set(RegisterToRegisterMask(operand.index), state);
 340  E :  }
 341    :  
 342    :  void LivenessAnalysis::StateHelper::StateUseOperand(
 343    :      const Instruction& instr,
 344    :      const _Operand& operand,
 345  E :      State* state) {
 346  E :    DCHECK(state != NULL);
 347    :  
 348  E :    const Representation& repr = instr.representation();
 349    :  
 350  E :    switch (operand.type) {
 351    :      case O_REG:
 352    :      case O_SMEM:
 353  E :        Set(RegisterToRegisterMask(operand.index), state);
 354  E :        break;
 355    :      case O_MEM:
 356  E :        Set(RegisterToRegisterMask(operand.index), state);
 357  E :        Set(RegisterToRegisterMask(repr.base), state);
 358    :        break;
 359    :    }
 360  E :  }
 361    :  
 362    :  void LivenessAnalysis::StateHelper::StateUseOperandLHS(
 363    :       const Instruction& instr,
 364    :       const _Operand& operand,
 365  E :       State* state) {
 366  E :    DCHECK(state != NULL);
 367    :  
 368  E :    if (operand.type == O_REG)
 369  E :      return;
 370  E :    StateUseOperand(instr, operand, state);
 371  E :  }
 372    :  
 373    :  bool LivenessAnalysis::StateHelper::GetDefsOf(
 374  E :      const Instruction& instr, State* state) {
 375  E :    DCHECK(state != NULL);
 376    :  
 377  E :    Clear(state);
 378    :  
 379  E :    const Representation& repr = instr.representation();
 380    :  
 381    :    // Get information on flags (eflags register).
 382  E :    SetFlags(repr.modifiedFlagsMask | repr.undefinedFlagsMask, state);
 383    :  
 384    :    // Handle instructions with 'REP' prefix.
 385  E :    if ((FLAG_GET_PREFIX(repr.flags) & (FLAG_REPNZ | FLAG_REP)) != 0) {
 386  E :      switch (repr.opcode) {
 387    :        case I_MOVS:
 388  E :          Set(RegisterToRegisterMask(R_ECX), state);
 389  E :          Set(RegisterToRegisterMask(R_ESI), state);
 390  E :          Set(RegisterToRegisterMask(R_EDI), state);
 391  E :          return true;
 392    :        case I_STOS:
 393  E :          Set(RegisterToRegisterMask(R_ECX), state);
 394  E :          Set(RegisterToRegisterMask(R_EDI), state);
 395  E :          return true;
 396  i :        default: return false;
 397    :      }
 398    :    }
 399    :  
 400    :    // Get information on operand (general purpose registers).
 401  E :    switch (repr.opcode) {
 402    :      case I_CMP:
 403    :      case I_FCOM:
 404    :      case I_FCOMP:
 405    :      case I_FCOMPP:
 406    :      case I_FCOMI:
 407    :      case I_FCOMIP:
 408    :      case I_FIST:
 409    :      case I_FISTP:
 410    :      case I_FST:
 411    :      case I_FSTP:
 412    :      case I_TEST:
 413  E :        return true;
 414    :      case I_ADD:
 415    :      case I_ADC:
 416    :      case I_AND:
 417    :      case I_DEC:
 418    :      case I_INC:
 419    :      case I_FADD:
 420    :      case I_FADDP:
 421    :      case I_FILD:
 422    :      case I_FLD:
 423    :      case I_FLD1:
 424    :      case I_FLDZ:
 425    :      case I_FMUL:
 426    :      case I_FMULP:
 427    :      case I_FSUB:
 428    :      case I_FSUBP:
 429    :      case I_LEA:
 430    :      case I_MOV:
 431    :      case I_MOVZX:
 432    :      case I_MOVSX:
 433    :      case I_NEG:
 434    :      case I_NOT:
 435    :      case I_OR:
 436    :      case I_ROL:
 437    :      case I_ROR:
 438    :      case I_SAR:
 439    :      case I_SBB:
 440    :      case I_SETA:
 441    :      case I_SETAE:
 442    :      case I_SETB:
 443    :      case I_SETBE:
 444    :      case I_SETG:
 445    :      case I_SETGE:
 446    :      case I_SETL:
 447    :      case I_SETLE:
 448    :      case I_SETNO:
 449    :      case I_SETNP:
 450    :      case I_SETNS:
 451    :      case I_SETNZ:
 452    :      case I_SETO:
 453    :      case I_SETP:
 454    :      case I_SETS:
 455    :      case I_SETZ:
 456    :      case I_SHL:
 457    :      case I_SHR:
 458    :      case I_SUB:
 459    :      case I_XOR:
 460  E :        StateDefOperand(repr.ops[0], state);
 461  E :        return true;
 462    :      case I_POP:
 463    :      case I_POPF:
 464  E :        StateDefOperand(repr.ops[0], state);
 465  E :        Set(RegisterToRegisterMask(R_ESP), state);
 466  E :        return true;
 467    :      case I_CALL:
 468    :      case I_PUSH:
 469    :      case I_PUSHF:
 470    :      case I_RET:
 471  E :        Set(RegisterToRegisterMask(R_ESP), state);
 472  E :        return true;
 473    :      case I_LEAVE:
 474  E :        Set(RegisterToRegisterMask(R_EBP), state);
 475  E :        Set(RegisterToRegisterMask(R_ESP), state);
 476  E :        return true;
 477    :      case I_LAHF:
 478  E :        Set(REGBITS_AH, state);
 479  E :        return true;
 480    :      case I_SAHF:
 481    :        // Store register ah into flags (fix a DiStorm bug).
 482  E :        SetFlags(D_AF | D_CF | D_PF | D_SF| D_ZF, state);
 483  E :        return true;
 484    :      case I_MOVS:
 485  E :        Set(RegisterToRegisterMask(R_ESI), state);
 486  E :        Set(RegisterToRegisterMask(R_EDI), state);
 487  E :        return true;
 488    :      case I_STOS:
 489  E :        Set(RegisterToRegisterMask(R_EDI), state);
 490  E :        return true;
 491    :      case I_CDQ:
 492  E :        Set(RegisterToRegisterMask(R_EAX), state);
 493  E :        return true;
 494    :      default:
 495  E :        return false;
 496    :    }
 497    :  
 498  i :    NOTREACHED();
 499  E :  }
 500    :  
 501    :  bool LivenessAnalysis::StateHelper::GetUsesOf(
 502  E :      const Instruction& instr, State* state) {
 503  E :    DCHECK(state != NULL);
 504    :  
 505  E :    Clear(state);
 506    :  
 507  E :    const Representation& repr = instr.representation();
 508    :  
 509    :    // Get information on flags (eflags register).
 510  E :    SetFlags(repr.testedFlagsMask, state);
 511    :  
 512    :    // Handle a special case: xor-initialization (i.e. xor eax, eax).
 513    :    if (repr.opcode == I_XOR &&
 514    :        repr.ops[0].type == O_REG &&
 515    :        repr.ops[1].type == O_REG &&
 516  E :        repr.ops[0].index == repr.ops[1].index) {
 517    :      // We can assume no uses.
 518  E :      return true;
 519    :    }
 520    :  
 521    :    // Handle instructions with 'REP' prefix.
 522  E :    if ((FLAG_GET_PREFIX(repr.flags) & (FLAG_REPNZ | FLAG_REP)) != 0) {
 523  E :      switch (repr.opcode) {
 524    :        case I_MOVS:
 525  E :          Set(RegisterToRegisterMask(R_ECX), state);
 526  E :          Set(RegisterToRegisterMask(R_ESI), state);
 527  E :          Set(RegisterToRegisterMask(R_EDI), state);
 528  E :          return true;
 529    :        case I_STOS:
 530  E :          Set(RegisterToRegisterMask(R_EAX), state);
 531  E :          Set(RegisterToRegisterMask(R_ECX), state);
 532  E :          Set(RegisterToRegisterMask(R_EDI), state);
 533  E :          return true;
 534  i :        default: return false;
 535    :      }
 536    :    }
 537    :  
 538    :    // Get information on operand (general purpose registers).
 539  E :    switch (repr.opcode) {
 540    :      case I_ADD:
 541    :      case I_ADC:
 542    :      case I_AND:
 543    :      case I_CMP:
 544    :      case I_FADD:
 545    :      case I_FADDP:
 546    :      case I_FCOM:
 547    :      case I_FCOMP:
 548    :      case I_FCOMPP:
 549    :      case I_FCOMI:
 550    :      case I_FCOMIP:
 551    :      case I_FICOM:
 552    :      case I_FICOMP:
 553    :      case I_FILD:
 554    :      case I_FIST:
 555    :      case I_FISTP:
 556    :      case I_FLD:
 557    :      case I_FLD1:
 558    :      case I_FLDZ:
 559    :      case I_FMUL:
 560    :      case I_FMULP:
 561    :      case I_FST:
 562    :      case I_FSTP:
 563    :      case I_FSUB:
 564    :      case I_FSUBP:
 565    :      case I_DEC:
 566    :      case I_INC:
 567    :      case I_NEG:
 568    :      case I_NOT:
 569    :      case I_ROL:
 570    :      case I_ROR:
 571    :      case I_OR:
 572    :      case I_SBB:
 573    :      case I_SAR:
 574    :      case I_SETA:
 575    :      case I_SETAE:
 576    :      case I_SETB:
 577    :      case I_SETBE:
 578    :      case I_SETG:
 579    :      case I_SETGE:
 580    :      case I_SETL:
 581    :      case I_SETLE:
 582    :      case I_SETNO:
 583    :      case I_SETNP:
 584    :      case I_SETNS:
 585    :      case I_SETNZ:
 586    :      case I_SETO:
 587    :      case I_SETP:
 588    :      case I_SETS:
 589    :      case I_SETZ:
 590    :      case I_SHL:
 591    :      case I_SHR:
 592    :      case I_SUB:
 593    :      case I_TEST:
 594    :      case I_XOR:
 595  E :        StateUseOperand(instr, repr.ops[0], state);
 596  E :        StateUseOperand(instr, repr.ops[1], state);
 597  E :        return true;
 598    :      case I_LEA:
 599    :      case I_MOV:
 600    :      case I_MOVZX:
 601    :      case I_MOVSX:
 602  E :        StateUseOperandLHS(instr, repr.ops[0], state);
 603  E :        StateUseOperand(instr, repr.ops[1], state);
 604  E :        return true;
 605    :      case I_PUSHF:
 606  E :        SetFlags(REGBITS_ALL, state);
 607  E :        Set(RegisterToRegisterMask(R_ESP), state);
 608  E :        return true;
 609    :      case I_LAHF:
 610  E :        SetFlags(D_AF | D_CF | D_PF | D_SF| D_ZF, state);
 611  E :        return true;
 612    :      case I_SAHF:
 613  E :        Set(REGBITS_AH, state);
 614  E :        return true;
 615    :      case I_POP:
 616    :      case I_POPF:
 617  E :        StateUseOperandLHS(instr, repr.ops[0], state);
 618  E :        Set(RegisterToRegisterMask(R_ESP), state);
 619  E :        return true;
 620    :      case I_CALL:
 621    :      case I_PUSH:
 622    :      case I_RET:
 623  E :        StateUseOperand(instr, repr.ops[0], state);
 624  E :        Set(RegisterToRegisterMask(R_ESP), state);
 625  E :        return true;
 626    :      case I_LEAVE:
 627  E :        Set(RegisterToRegisterMask(R_EBP), state);
 628  E :        return true;
 629    :      case I_MOVS:
 630  E :        Set(RegisterToRegisterMask(R_ESI), state);
 631  E :        Set(RegisterToRegisterMask(R_EDI), state);
 632  E :        return true;
 633    :      case I_STOS:
 634  E :        Set(RegisterToRegisterMask(R_EAX), state);
 635  E :        Set(RegisterToRegisterMask(R_EDI), state);
 636  E :        return true;
 637    :      case I_CDQ:
 638  E :        Set(RegisterToRegisterMask(R_EAX), state);
 639  E :        return true;
 640    :      default:
 641  E :        return false;
 642    :    }
 643    :  
 644  i :    NOTREACHED();
 645  E :  }
 646    :  
 647    :  bool LivenessAnalysis::StateHelper::GetUsesOf(
 648  E :      const Successor& successor, State* state) {
 649  E :    DCHECK(state != NULL);
 650  E :    switch (successor.condition()) {
 651    :      case Successor::kConditionAbove:
 652    :      case Successor::kConditionBelowOrEqual:
 653  E :        SetFlags(D_CF | D_ZF, state);
 654  E :        return true;
 655    :      case Successor::kConditionBelow:
 656    :      case Successor::kConditionAboveOrEqual:
 657  E :        SetFlags(D_CF, state);
 658  E :        return true;
 659    :      case Successor::kConditionEqual:
 660    :      case Successor::kConditionNotEqual:
 661  E :        SetFlags(D_ZF, state);
 662  E :        return true;
 663    :      case Successor::kConditionGreater:
 664    :      case Successor::kConditionLessOrEqual:
 665  E :        SetFlags(D_ZF | D_SF | D_OF, state);
 666  E :        return true;
 667    :      case Successor::kConditionLess:
 668    :      case Successor::kConditionGreaterOrEqual:
 669  E :        SetFlags(D_SF | D_OF, state);
 670  E :        return true;
 671    :      case Successor::kConditionOverflow:
 672    :      case Successor::kConditionNotOverflow:
 673  E :        SetFlags(D_OF, state);
 674  E :        return true;
 675    :      case Successor::kConditionParity:
 676    :      case Successor::kConditionNotParity:
 677  E :        SetFlags(D_PF, state);
 678  E :        return true;
 679    :      case Successor::kConditionSigned:
 680    :      case Successor::kConditionNotSigned:
 681  E :        SetFlags(D_SF, state);
 682  E :        return true;
 683    :      case Successor::kConditionTrue:
 684  E :        return true;
 685    :      default:
 686  i :        return false;
 687    :    }
 688    :  
 689  i :    NOTREACHED();
 690  E :  }
 691    :  
 692    :  }  // namespace analysis
 693    :  }  // namespace block_graph

Coverage information generated Wed Dec 11 11:34:16 2013.