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
|