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 : // Unittests for liveness analysis.
16 :
17 : #include "syzygy/block_graph/analysis/liveness_analysis.h"
18 :
19 : #include "base/bind.h"
20 : #include "gmock/gmock.h"
21 : #include "gtest/gtest.h"
22 : #include "syzygy/block_graph/basic_block_assembler.h"
23 : #include "syzygy/block_graph/analysis/liveness_analysis_internal.h"
24 :
25 : #include "mnemonics.h" // NOLINT
26 :
27 : namespace block_graph {
28 : namespace analysis {
29 :
30 : namespace {
31 :
32 : typedef BasicBlockSubGraph::BBCollection BBCollection;
33 : typedef block_graph::analysis::LivenessAnalysis::State State;
34 : typedef block_graph::analysis::LivenessAnalysis::StateHelper StateHelper;
35 : typedef block_graph::BasicBlockSubGraph::BasicBlock BasicBlock;
36 : typedef block_graph::BasicBlockSubGraph::BasicBlock::Instructions Instructions;
37 : typedef block_graph::BasicBlockSubGraph::BasicBlock::Successors Successors;
38 : typedef block_graph::BasicBlockSubGraph::BasicCodeBlock BasicCodeBlock;
39 : typedef block_graph::BasicBlockSubGraph::BlockDescription BlockDescription;
40 :
41 : // _asm mov eax, 0
42 : const uint8 kMovEaxZero[5] = { 0xB8, 0x00, 0x00, 0x00, 0x00 };
43 : // _asm mov ebx, 0
44 : const uint8 kMovEbxZero[5] = { 0xBB, 0x00, 0x00, 0x00, 0x00 };
45 : // _asm mov ecx, 0
46 : const uint8 kMovEcxZero[5] = { 0xB9, 0x00, 0x00, 0x00, 0x00 };
47 : // _asm mov edx, 0
48 : const uint8 kMovEdxZero[5] = { 0xBA, 0x00, 0x00, 0x00, 0x00 };
49 : // _asm mov esi, 0
50 : const uint8 kMovEsiZero[5] = { 0xBE, 0x00, 0x00, 0x00, 0x00 };
51 : // _asm mov edi, 0
52 : const uint8 kMovEdiZero[5] = { 0xBF, 0x00, 0x00, 0x00, 0x00 };
53 : // _asm mov esp, 0
54 : const uint8 kMovEspZero[5] = { 0xBC, 0x00, 0x00, 0x00, 0x00 };
55 : // _asm mov ebp, 0
56 : const uint8 kMovEbpZero[5] = { 0xBD, 0x00, 0x00, 0x00, 0x00 };
57 : // _asm cmp eax, ebx
58 : const uint8 kCmpEaxEbx[2] = { 0x3B, 0xC3 };
59 : // _asm mov ax, 0
60 : const uint8 kMovAxZero[4] = { 0x66, 0xB8, 0x00, 0x00 };
61 : // _asm mov al, 0
62 : const uint8 kMovAlZero[2] = { 0xB0, 0x00 };
63 :
64 : class LivenessAnalysisTest : public testing::Test {
65 : public:
66 : LivenessAnalysisTest();
67 :
68 E : inline bool is_def(const assm::Register& reg) const {
69 E : return defs_.IsLive(reg);
70 E : }
71 :
72 E : inline bool is_use(const assm::Register& reg) const {
73 E : return uses_.IsLive(reg);
74 E : }
75 :
76 E : inline bool is_live(const assm::Register& reg) const {
77 E : return state_.IsLive(reg);
78 E : }
79 :
80 E : inline bool are_arithmetic_flags_live() const {
81 E : return state_.AreArithmeticFlagsLive();
82 E : }
83 :
84 : template<size_t N>
85 : void AddInstructionFromBuffer(const uint8 (& data)[N]);
86 : void DefineAllRegisters();
87 : void AnalyzeInstructionsWithoutReset();
88 : void AnalyzeInstructions();
89 :
90 : template<size_t N>
91 : void UpdateDefsUsesFromBuffer(const uint8 (& data)[N]);
92 :
93 : template<size_t N>
94 : void AnalyzeSingleInstructionFromBuffer(const uint8 (& data)[N]);
95 :
96 : bool CheckCarryFlagInstruction(bool expect_on, bool expect_off);
97 :
98 : void AddSuccessorBetween(Successor::Condition condition,
99 : BasicCodeBlock* from,
100 : BasicCodeBlock* to);
101 :
102 : protected:
103 : BlockGraph block_graph_;
104 : BlockGraph::Block* test_block_;
105 : BasicBlock::Instructions instructions_;
106 : BasicBlockAssembler asm_;
107 : LivenessAnalysis liveness_;
108 : LivenessAnalysis::State state_;
109 : LivenessAnalysis::State defs_;
110 : LivenessAnalysis::State uses_;
111 : };
112 :
113 : LivenessAnalysisTest::LivenessAnalysisTest()
114 : : testing::Test(),
115 : test_block_(NULL),
116 : instructions_(),
117 : asm_(instructions_.end(), &instructions_),
118 : liveness_(),
119 E : state_() {
120 E : test_block_ = block_graph_.AddBlock(BlockGraph::CODE_BLOCK, 10, "test block");
121 E : }
122 :
123 : template<size_t N>
124 E : void LivenessAnalysisTest::UpdateDefsUsesFromBuffer(const uint8 (& data)[N]) {
125 : // Decode an instruction.
126 E : DCHECK_GT(assm::kMaxInstructionLength, N);
127 :
128 E : block_graph::Instruction temp;
129 E : ASSERT_TRUE(block_graph::Instruction::FromBuffer(&data[0], N, &temp));
130 :
131 : // Expect to decode the entire buffer.
132 E : ASSERT_TRUE(temp.size() == N);
133 :
134 : // Analyze the defs/uses of this instruction.
135 E : StateHelper::GetDefsOf(temp, &defs_);
136 E : StateHelper::GetUsesOf(temp, &uses_);
137 E : }
138 :
139 : template<size_t N>
140 E : void LivenessAnalysisTest::AddInstructionFromBuffer(const uint8 (& data)[N]) {
141 : // Decode an instruction and append it to basicblock_.
142 E : DCHECK_GT(assm::kMaxInstructionLength, N);
143 :
144 E : block_graph::Instruction temp;
145 E : ASSERT_TRUE(block_graph::Instruction::FromBuffer(&data[0], N, &temp));
146 :
147 : // Expect to decode the entire buffer.
148 E : ASSERT_TRUE(temp.size() == N);
149 :
150 : // Append this instruction to the basic block.
151 E : instructions_.push_back(temp);
152 E : }
153 :
154 E : void LivenessAnalysisTest::DefineAllRegisters() {
155 : // Inserts instructions into basicblock_ so all registers are defined.
156 E : AddInstructionFromBuffer(kMovEaxZero);
157 E : AddInstructionFromBuffer(kMovEbxZero);
158 E : AddInstructionFromBuffer(kMovEcxZero);
159 E : AddInstructionFromBuffer(kMovEdxZero);
160 E : AddInstructionFromBuffer(kMovEsiZero);
161 E : AddInstructionFromBuffer(kMovEdiZero);
162 E : AddInstructionFromBuffer(kMovEspZero);
163 E : AddInstructionFromBuffer(kMovEbpZero);
164 :
165 : // Define arithmetic flags.
166 E : AddInstructionFromBuffer(kCmpEaxEbx);
167 E : }
168 :
169 E : void LivenessAnalysisTest::AnalyzeInstructionsWithoutReset() {
170 : // Perform a backward liveness analysis on instructions in basicblock_.
171 : // Results are kept in 'state_' and may be accessed through IsLive and
172 : // AreArithmeticFlagsLive.
173 E : Instructions::reverse_iterator instr_iter = instructions_.rbegin();
174 E : for (; instr_iter != instructions_.rend(); ++instr_iter) {
175 E : const Instruction& instr = *instr_iter;
176 E : liveness_.PropagateBackward(instr, &state_);
177 E : }
178 E : }
179 :
180 E : void LivenessAnalysisTest::AnalyzeInstructions() {
181 E : LivenessAnalysis::StateHelper::SetAll(&state_);
182 E : AnalyzeInstructionsWithoutReset();
183 E : }
184 :
185 : template<size_t N>
186 : void LivenessAnalysisTest::AnalyzeSingleInstructionFromBuffer(
187 E : const uint8 (& data)[N]) {
188 : // This function creates a basic block with an instruction under test,
189 : // followed by instructions to define all registers and flags. This way, the
190 : // analysis may assume everything was dead before the instruction.
191 E : instructions_.clear();
192 E : StateHelper::SetAll(&state_);
193 :
194 E : AddInstructionFromBuffer(data);
195 E : DefineAllRegisters();
196 E : AnalyzeInstructions();
197 :
198 : // Retrieve defs/uses of this instruction.
199 E : UpdateDefsUsesFromBuffer(data);
200 E : }
201 :
202 : bool LivenessAnalysisTest::CheckCarryFlagInstruction(
203 E : bool expect_on, bool expect_off) {
204 E : LivenessAnalysis::State flags;
205 E : StateHelper::Clear(&flags);
206 E : StateHelper::SetFlags(~(D_CF), &state_);
207 :
208 : // Try with the carry flag on.
209 E : StateHelper::Clear(&state_);
210 E : StateHelper::SetFlags(D_CF, &state_);
211 E : AnalyzeInstructionsWithoutReset();
212 E : StateHelper::Subtract(flags, &state_);
213 E : if (are_arithmetic_flags_live() != expect_on)
214 i : return false;
215 :
216 : // Try with the carry flag off.
217 E : StateHelper::Clear(&state_);
218 E : AnalyzeInstructionsWithoutReset();
219 E : StateHelper::Subtract(flags, &state_);
220 E : if (are_arithmetic_flags_live() != expect_off)
221 i : return false;
222 :
223 E : return true;
224 E : }
225 :
226 : void LivenessAnalysisTest::AddSuccessorBetween(Successor::Condition condition,
227 : BasicCodeBlock* from,
228 E : BasicCodeBlock* to) {
229 : from->successors().push_back(
230 : Successor(condition,
231 : BasicBlockReference(BlockGraph::RELATIVE_REF,
232 : BlockGraph::Reference::kMaximumSize,
233 : to),
234 E : 0));
235 E : }
236 :
237 E : TEST(LivenessAnalysisStateTest, StateRegisterMaskOperations) {
238 : // On creation, a state assumes all registers are alive.
239 E : State state_full;
240 E : EXPECT_TRUE(StateHelper::IsSet(state_full, StateHelper::REGBITS_ALL));
241 E : EXPECT_TRUE(StateHelper::IsSet(state_full, StateHelper::REGBITS_AX));
242 :
243 : // The Clear operation should not keep any register partially defined.
244 E : State state_empty;
245 E : StateHelper::Clear(&state_empty);
246 : EXPECT_FALSE(
247 E : StateHelper::IsPartiallySet(state_empty, StateHelper::REGBITS_ALL));
248 : EXPECT_FALSE(
249 E : StateHelper::IsPartiallySet(state_empty, StateHelper::REGBITS_AX));
250 :
251 : // Test sub-registers definition.
252 E : State state_ax;
253 E : State state_cx;
254 E : StateHelper::Clear(&state_ax);
255 E : StateHelper::Clear(&state_cx);
256 E : StateHelper::Set(StateHelper::REGBITS_AX, &state_ax);
257 E : StateHelper::Set(StateHelper::REGBITS_CX, &state_cx);
258 E : EXPECT_TRUE(StateHelper::IsPartiallySet(state_ax, StateHelper::REGBITS_EAX));
259 E : EXPECT_TRUE(StateHelper::IsSet(state_ax, StateHelper::REGBITS_AL));
260 E : EXPECT_TRUE(StateHelper::IsSet(state_ax, StateHelper::REGBITS_AH));
261 E : EXPECT_TRUE(StateHelper::IsSet(state_ax, StateHelper::REGBITS_AX));
262 E : EXPECT_TRUE(StateHelper::IsPartiallySet(state_cx, StateHelper::REGBITS_ECX));
263 E : EXPECT_TRUE(StateHelper::IsSet(state_cx, StateHelper::REGBITS_CL));
264 E : EXPECT_TRUE(StateHelper::IsSet(state_cx, StateHelper::REGBITS_CH));
265 E : EXPECT_TRUE(StateHelper::IsSet(state_cx, StateHelper::REGBITS_CX));
266 :
267 : // Test IsLive operation.
268 E : EXPECT_TRUE(state_full.IsLive(assm::eax));
269 E : EXPECT_TRUE(state_full.IsLive(assm::ecx));
270 E : EXPECT_FALSE(state_empty.IsLive(assm::eax));
271 E : EXPECT_FALSE(state_empty.IsLive(assm::ecx));
272 E : EXPECT_TRUE(state_ax.IsLive(assm::eax));
273 E : EXPECT_FALSE(state_ax.IsLive(assm::ecx));
274 E : EXPECT_FALSE(state_cx.IsLive(assm::eax));
275 E : EXPECT_TRUE(state_cx.IsLive(assm::ecx));
276 :
277 : // Test copy constructor.
278 E : State state_copy(state_ax);
279 : EXPECT_TRUE(
280 E : StateHelper::IsPartiallySet(state_copy, StateHelper::REGBITS_EAX));
281 E : EXPECT_TRUE(StateHelper::IsSet(state_copy, StateHelper::REGBITS_AL));
282 E : EXPECT_TRUE(StateHelper::IsSet(state_copy, StateHelper::REGBITS_AH));
283 E : EXPECT_TRUE(StateHelper::IsSet(state_copy, StateHelper::REGBITS_AX));
284 :
285 : // Test Copy operation.
286 E : State state_copy_ax;
287 E : StateHelper::Copy(state_ax, &state_copy_ax);
288 : EXPECT_TRUE(
289 E : StateHelper::IsPartiallySet(state_copy_ax, StateHelper::REGBITS_EAX));
290 E : EXPECT_TRUE(StateHelper::IsSet(state_copy_ax, StateHelper::REGBITS_AL));
291 E : EXPECT_TRUE(StateHelper::IsSet(state_copy_ax, StateHelper::REGBITS_AH));
292 E : EXPECT_TRUE(StateHelper::IsSet(state_copy_ax, StateHelper::REGBITS_AX));
293 :
294 : // Test Union operation.
295 E : State state_merged;
296 E : StateHelper::Clear(&state_merged);
297 : EXPECT_FALSE(
298 E : StateHelper::IsPartiallySet(state_merged, StateHelper::REGBITS_AX));
299 : EXPECT_FALSE(
300 E : StateHelper::IsPartiallySet(state_merged, StateHelper::REGBITS_CX));
301 E : StateHelper::Union(state_ax, &state_merged);
302 : EXPECT_TRUE(
303 E : StateHelper::IsPartiallySet(state_merged, StateHelper::REGBITS_AX));
304 : EXPECT_FALSE(
305 E : StateHelper::IsPartiallySet(state_merged, StateHelper::REGBITS_CX));
306 E : StateHelper::Union(state_cx, &state_merged);
307 : EXPECT_TRUE(
308 E : StateHelper::IsPartiallySet(state_merged, StateHelper::REGBITS_AX));
309 : EXPECT_TRUE(
310 E : StateHelper::IsPartiallySet(state_merged, StateHelper::REGBITS_CX));
311 :
312 : // Test Subtract operation
313 E : StateHelper::Subtract(state_ax, &state_merged);
314 : EXPECT_FALSE(
315 E : StateHelper::IsPartiallySet(state_merged, StateHelper::REGBITS_AX));
316 : EXPECT_TRUE(
317 E : StateHelper::IsPartiallySet(state_merged, StateHelper::REGBITS_CX));
318 E : StateHelper::Subtract(state_cx, &state_merged);
319 : EXPECT_FALSE(
320 E : StateHelper::IsPartiallySet(state_merged, StateHelper::REGBITS_AX));
321 : EXPECT_FALSE(
322 E : StateHelper::IsPartiallySet(state_merged, StateHelper::REGBITS_CX));
323 E : }
324 :
325 E : TEST(LivenessAnalysisStateTest, StateFlagsMaskOperations) {
326 : // On creation, a state assumes all flags are alive.
327 E : State state_full;
328 E : EXPECT_TRUE(state_full.AreArithmeticFlagsLive());
329 :
330 : // The Clear operation should not keep any flags alive.
331 E : State state_empty;
332 E : StateHelper::Clear(&state_empty);
333 E : EXPECT_FALSE(state_empty.AreArithmeticFlagsLive());
334 :
335 : // Partially defined flags must be considered alive.
336 E : State state_flagA;
337 E : State state_flagB;
338 E : State state_flagC;
339 E : StateHelper::Clear(&state_flagA);
340 E : StateHelper::Clear(&state_flagB);
341 E : StateHelper::SetFlags(0xF0F0, &state_flagA);
342 E : StateHelper::SetFlags(0xFFFF, &state_flagB);
343 :
344 E : EXPECT_TRUE(state_flagA.AreArithmeticFlagsLive());
345 E : EXPECT_TRUE(state_flagB.AreArithmeticFlagsLive());
346 :
347 : // Test Subtract operation.
348 E : State state_flag_ari1;
349 E : State state_flag_ari2;
350 E : StateHelper::Clear(&state_flag_ari1);
351 E : StateHelper::Clear(&state_flag_ari2);
352 E : StateHelper::SetFlags(D_ZF | D_SF | D_CF, &state_flag_ari1);
353 E : StateHelper::SetFlags(D_OF | D_PF | D_AF, &state_flag_ari2);
354 :
355 E : EXPECT_TRUE(state_flag_ari1.AreArithmeticFlagsLive());
356 E : EXPECT_TRUE(state_flag_ari2.AreArithmeticFlagsLive());
357 :
358 E : State state_merged;
359 E : EXPECT_TRUE(state_merged.AreArithmeticFlagsLive());
360 E : StateHelper::Subtract(state_flag_ari1, &state_merged);
361 E : EXPECT_TRUE(state_merged.AreArithmeticFlagsLive());
362 E : StateHelper::Subtract(state_flag_ari2, &state_merged);
363 E : EXPECT_FALSE(state_merged.AreArithmeticFlagsLive());
364 E : }
365 :
366 E : TEST_F(LivenessAnalysisTest, Mov1Analysis) {
367 E : asm_.mov(assm::eax, Immediate(10));
368 E : asm_.mov(assm::ecx, assm::ebx);
369 E : AnalyzeInstructions();
370 E : EXPECT_FALSE(is_live(assm::eax));
371 E : EXPECT_FALSE(is_live(assm::ax));
372 E : EXPECT_FALSE(is_live(assm::ah));
373 E : EXPECT_TRUE(is_live(assm::ebx));
374 E : EXPECT_TRUE(is_live(assm::bx));
375 E : EXPECT_TRUE(is_live(assm::bl));
376 E : EXPECT_FALSE(is_live(assm::ecx));
377 E : }
378 :
379 E : TEST_F(LivenessAnalysisTest, Mov2Analysis) {
380 E : asm_.mov(assm::eax, assm::ebx);
381 E : asm_.mov(assm::edx, Immediate(10));
382 E : asm_.mov(assm::ecx, Immediate(test_block_, 0));
383 E : AnalyzeInstructions();
384 E : EXPECT_FALSE(is_live(assm::eax));
385 E : EXPECT_FALSE(is_live(assm::ax));
386 E : EXPECT_FALSE(is_live(assm::ah));
387 E : EXPECT_TRUE(is_live(assm::ebx));
388 E : EXPECT_TRUE(is_live(assm::bx));
389 E : EXPECT_TRUE(is_live(assm::bl));
390 E : EXPECT_FALSE(is_live(assm::ecx));
391 E : EXPECT_FALSE(is_live(assm::edx));
392 E : }
393 :
394 E : TEST_F(LivenessAnalysisTest, DefineAllRegisters) {
395 : // Validate the tester by defining all registers and using none.
396 E : DefineAllRegisters();
397 E : AnalyzeInstructions();
398 E : EXPECT_FALSE(is_live(assm::eax));
399 E : EXPECT_FALSE(is_live(assm::ax));
400 E : EXPECT_FALSE(is_live(assm::al));
401 E : EXPECT_FALSE(is_live(assm::ah));
402 E : EXPECT_FALSE(is_live(assm::ebx));
403 E : EXPECT_FALSE(is_live(assm::bx));
404 E : EXPECT_FALSE(is_live(assm::bl));
405 E : EXPECT_FALSE(is_live(assm::bh));
406 E : EXPECT_FALSE(is_live(assm::ecx));
407 E : EXPECT_FALSE(is_live(assm::cx));
408 E : EXPECT_FALSE(is_live(assm::cl));
409 E : EXPECT_FALSE(is_live(assm::ch));
410 E : EXPECT_FALSE(is_live(assm::edx));
411 E : EXPECT_FALSE(is_live(assm::dx));
412 E : EXPECT_FALSE(is_live(assm::dl));
413 E : EXPECT_FALSE(is_live(assm::dh));
414 E : EXPECT_FALSE(is_live(assm::esi));
415 E : EXPECT_FALSE(is_live(assm::si));
416 E : EXPECT_FALSE(is_live(assm::edi));
417 E : EXPECT_FALSE(is_live(assm::di));
418 E : EXPECT_FALSE(are_arithmetic_flags_live());
419 E : }
420 :
421 E : TEST_F(LivenessAnalysisTest, Defs1Analysis) {
422 : // Validate the tester by defining all registers and using some of them.
423 E : AddInstructionFromBuffer(kMovEaxZero);
424 E : AddInstructionFromBuffer(kMovEcxZero);
425 E : AddInstructionFromBuffer(kMovEsiZero);
426 E : AnalyzeInstructions();
427 E : EXPECT_FALSE(is_live(assm::eax));
428 E : EXPECT_FALSE(is_live(assm::ax));
429 E : EXPECT_FALSE(is_live(assm::ah));
430 E : EXPECT_TRUE(is_live(assm::ebx));
431 E : EXPECT_TRUE(is_live(assm::bx));
432 E : EXPECT_TRUE(is_live(assm::bl));
433 E : EXPECT_FALSE(is_live(assm::ecx));
434 E : EXPECT_FALSE(is_live(assm::cx));
435 E : EXPECT_FALSE(is_live(assm::cl));
436 E : EXPECT_TRUE(is_live(assm::edx));
437 E : EXPECT_TRUE(is_live(assm::dx));
438 E : EXPECT_TRUE(is_live(assm::dl));
439 E : EXPECT_FALSE(is_live(assm::esi));
440 E : EXPECT_FALSE(is_live(assm::si));
441 E : EXPECT_TRUE(is_live(assm::edi));
442 E : EXPECT_TRUE(is_live(assm::di));
443 E : }
444 :
445 E : TEST_F(LivenessAnalysisTest, Defs2Analysis) {
446 : // Validate the tester by defining all registers and using some of them.
447 E : AddInstructionFromBuffer(kMovEbxZero);
448 E : AddInstructionFromBuffer(kMovEdxZero);
449 E : AddInstructionFromBuffer(kMovEdiZero);
450 E : AnalyzeInstructions();
451 E : EXPECT_TRUE(is_live(assm::eax));
452 E : EXPECT_TRUE(is_live(assm::ax));
453 E : EXPECT_TRUE(is_live(assm::al));
454 E : EXPECT_FALSE(is_live(assm::ebx));
455 E : EXPECT_FALSE(is_live(assm::bx));
456 E : EXPECT_FALSE(is_live(assm::bh));
457 E : EXPECT_TRUE(is_live(assm::ecx));
458 E : EXPECT_TRUE(is_live(assm::cx));
459 E : EXPECT_TRUE(is_live(assm::cl));
460 E : EXPECT_FALSE(is_live(assm::edx));
461 E : EXPECT_FALSE(is_live(assm::dx));
462 E : EXPECT_FALSE(is_live(assm::dl));
463 E : EXPECT_TRUE(is_live(assm::esi));
464 E : EXPECT_TRUE(is_live(assm::si));
465 E : EXPECT_FALSE(is_live(assm::edi));
466 E : EXPECT_FALSE(is_live(assm::di));
467 E : }
468 :
469 E : TEST_F(LivenessAnalysisTest, Analysis16Bit) {
470 E : AddInstructionFromBuffer(kMovAxZero);
471 E : AnalyzeInstructions();
472 E : EXPECT_TRUE(is_live(assm::eax));
473 E : EXPECT_FALSE(is_live(assm::ax));
474 E : EXPECT_FALSE(is_live(assm::al));
475 E : EXPECT_FALSE(is_live(assm::ah));
476 E : }
477 :
478 E : TEST_F(LivenessAnalysisTest, Analysis8Bit) {
479 E : AddInstructionFromBuffer(kMovAlZero);
480 E : AnalyzeInstructions();
481 E : EXPECT_TRUE(is_live(assm::eax));
482 E : EXPECT_TRUE(is_live(assm::ax));
483 E : EXPECT_FALSE(is_live(assm::al));
484 E : EXPECT_TRUE(is_live(assm::ah));
485 E : }
486 :
487 E : TEST_F(LivenessAnalysisTest, OperandTypeLeft) {
488 : // Validate the support of all DiStorm operand types (as first operand).
489 : // _asm add eax, ecx
490 : static const uint8 kOpReg1[] = { 0x03, 0xC1 };
491 E : AnalyzeSingleInstructionFromBuffer(kOpReg1);
492 E : EXPECT_TRUE(is_live(assm::eax));
493 E : EXPECT_FALSE(is_live(assm::ebx));
494 E : EXPECT_TRUE(is_live(assm::ecx));
495 E : EXPECT_FALSE(is_live(assm::edx));
496 :
497 : // _asm add [eax], ecx
498 : static const uint8 kOpSmem[] = { 0x01, 0x08 };
499 E : AnalyzeSingleInstructionFromBuffer(kOpSmem);
500 E : EXPECT_TRUE(is_live(assm::eax));
501 E : EXPECT_FALSE(is_live(assm::ebx));
502 E : EXPECT_TRUE(is_live(assm::ecx));
503 E : EXPECT_FALSE(is_live(assm::edx));
504 :
505 : // _asm add [eax + 42], ecx
506 : static const uint8 kOpSmemOffet[] = { 0x01, 0x48, 0x2A };
507 E : AnalyzeSingleInstructionFromBuffer(kOpSmemOffet);
508 E : EXPECT_TRUE(is_live(assm::eax));
509 E : EXPECT_FALSE(is_live(assm::ebx));
510 E : EXPECT_TRUE(is_live(assm::ecx));
511 E : EXPECT_FALSE(is_live(assm::edx));
512 :
513 : // _asm add [eax + ebx*2 + 42], ecx
514 : static const uint8 kOpMemOffset[] = { 0x01, 0x4C, 0x58, 0x2A };
515 E : AnalyzeSingleInstructionFromBuffer(kOpMemOffset);
516 E : EXPECT_TRUE(is_live(assm::eax));
517 E : EXPECT_TRUE(is_live(assm::ebx));
518 E : EXPECT_TRUE(is_live(assm::ecx));
519 E : EXPECT_FALSE(is_live(assm::edx));
520 :
521 : // _asm add DWORD PTR [X], ecx
522 : static const uint8 kOpDispl[] = { 0x01, 0x0D, 0x80, 0x1E, 0xF2, 0x00 };
523 E : AnalyzeSingleInstructionFromBuffer(kOpDispl);
524 E : EXPECT_FALSE(is_live(assm::eax));
525 E : EXPECT_FALSE(is_live(assm::ebx));
526 E : EXPECT_TRUE(is_live(assm::ecx));
527 E : EXPECT_FALSE(is_live(assm::edx));
528 E : }
529 :
530 E : TEST_F(LivenessAnalysisTest, OperandTypeRight) {
531 : // Validate the support of all DiStorm operand types (as second operand).
532 : // _asm add ecx, 1
533 : static const uint8 kOpReg1[] = { 0x83, 0xC1, 0x01 };
534 E : AnalyzeSingleInstructionFromBuffer(kOpReg1);
535 E : EXPECT_FALSE(is_live(assm::eax));
536 E : EXPECT_FALSE(is_live(assm::ebx));
537 E : EXPECT_TRUE(is_live(assm::ecx));
538 E : EXPECT_FALSE(is_live(assm::edx));
539 :
540 : // _asm add ecx, eax
541 : static const uint8 kOpReg2[] = { 0x03, 0xC8 };
542 E : AnalyzeSingleInstructionFromBuffer(kOpReg2);
543 E : EXPECT_TRUE(is_live(assm::eax));
544 E : EXPECT_FALSE(is_live(assm::ebx));
545 E : EXPECT_TRUE(is_live(assm::ecx));
546 E : EXPECT_FALSE(is_live(assm::edx));
547 :
548 : // _asm add ecx, [eax]
549 : static const uint8 kOpSmem[] = { 0x03, 0x08 };
550 E : AnalyzeSingleInstructionFromBuffer(kOpSmem);
551 E : EXPECT_TRUE(is_live(assm::eax));
552 E : EXPECT_FALSE(is_live(assm::ebx));
553 E : EXPECT_TRUE(is_live(assm::ecx));
554 E : EXPECT_FALSE(is_live(assm::edx));
555 :
556 : // _asm add ecx, [eax + 42]
557 : static const uint8 kOpSmemOffet[] = { 0x03, 0x48, 0x2A };
558 E : AnalyzeSingleInstructionFromBuffer(kOpSmemOffet);
559 E : EXPECT_TRUE(is_live(assm::eax));
560 E : EXPECT_FALSE(is_live(assm::ebx));
561 E : EXPECT_TRUE(is_live(assm::ecx));
562 E : EXPECT_FALSE(is_live(assm::edx));
563 :
564 : // _asm add ecx, [eax + ebx*2 + 42]
565 : static const uint8 kOpMemOffset[] = { 0x03, 0x4C, 0x58, 0x2A };
566 E : AnalyzeSingleInstructionFromBuffer(kOpMemOffset);
567 E : EXPECT_TRUE(is_live(assm::eax));
568 E : EXPECT_TRUE(is_live(assm::ebx));
569 E : EXPECT_TRUE(is_live(assm::ecx));
570 E : EXPECT_FALSE(is_live(assm::edx));
571 :
572 : // _asm add ecx, DWORD PTR [X]
573 : static const uint8 kOpDispl[] = { 0x03, 0x0D, 0x80, 0x1E, 0x27, 0x00 };
574 E : AnalyzeSingleInstructionFromBuffer(kOpDispl);
575 E : EXPECT_FALSE(is_live(assm::eax));
576 E : EXPECT_FALSE(is_live(assm::ebx));
577 E : EXPECT_TRUE(is_live(assm::ecx));
578 E : EXPECT_FALSE(is_live(assm::edx));
579 E : }
580 :
581 E : TEST_F(LivenessAnalysisTest, InstructionWithoutDefine) {
582 : // Validate instructions that fully overwrite and use the destination.
583 : // _asm cmp eax, [ecx]
584 : static const uint8 kCmp[] = { 0x3B, 0x01 };
585 E : AnalyzeSingleInstructionFromBuffer(kCmp);
586 E : EXPECT_TRUE(is_live(assm::eax));
587 E : EXPECT_TRUE(is_live(assm::ecx));
588 :
589 : // _asm test ebx, [edx+12]
590 : static const uint8 kTest[] = { 0x85, 0x5A, 0x0C };
591 E : AnalyzeSingleInstructionFromBuffer(kTest);
592 E : EXPECT_TRUE(is_live(assm::ebx));
593 E : EXPECT_TRUE(is_live(assm::edx));
594 E : }
595 :
596 E : TEST_F(LivenessAnalysisTest, InstructionsWithDefine) {
597 : // Validate instructions that fully overwrite the destination.
598 : // _asm mov ebx, [edx+12]
599 : static const uint8 kCmp[] = { 0x8B, 0x5A, 0x0C };
600 E : AnalyzeSingleInstructionFromBuffer(kCmp);
601 E : EXPECT_FALSE(is_live(assm::ebx));
602 E : EXPECT_TRUE(is_live(assm::edx));
603 :
604 : // _asm lea ebx, [edx+12]
605 : static const uint8 kTest[] = { 0x8D, 0x5A, 0x0C };
606 E : AnalyzeSingleInstructionFromBuffer(kTest);
607 E : EXPECT_FALSE(is_live(assm::ebx));
608 E : EXPECT_TRUE(is_live(assm::edx));
609 E : }
610 :
611 E : TEST_F(LivenessAnalysisTest, InstructionsWithPartialDefine) {
612 : // Registers partially defined must be considered alive.
613 : // _asm mov bl, dl
614 : static const uint8 kCmp[] = { 0xB3, 0x0C };
615 : // _asm mov DWORD PTR [X], ebx
616 : static const uint8 kStore[] = { 0x89, 0x1D, 0x80, 0x1E, 0x10, 0x01 };
617 E : AddInstructionFromBuffer(kCmp);
618 E : AddInstructionFromBuffer(kStore);
619 E : AnalyzeInstructions();
620 :
621 E : EXPECT_TRUE(is_live(assm::ebx));
622 E : EXPECT_TRUE(is_live(assm::bx));
623 E : EXPECT_FALSE(is_live(assm::bl));
624 E : EXPECT_TRUE(is_live(assm::bh));
625 :
626 E : EXPECT_TRUE(is_live(assm::edx));
627 E : EXPECT_TRUE(is_live(assm::dx));
628 E : EXPECT_TRUE(is_live(assm::dl));
629 E : EXPECT_TRUE(is_live(assm::dh));
630 E : }
631 :
632 E : TEST_F(LivenessAnalysisTest, InstructionsWithPartialDefineAll) {
633 : static const uint8 kMovAl[] = { 0xB0, 0x00 };
634 : static const uint8 kMovBl[] = { 0xB1, 0x00 };
635 : static const uint8 kMovCl[] = { 0xB2, 0x00 };
636 : static const uint8 kMovDl[] = { 0xB3, 0x00 };
637 : static const uint8 kMovAh[] = { 0xB4, 0x00 };
638 : static const uint8 kMovBh[] = { 0xB7, 0x00 };
639 : static const uint8 kMovCh[] = { 0xB5, 0x00 };
640 : static const uint8 kMovDh[] = { 0xB6, 0x00 };
641 : static const uint8 kMovAx[] = { 0x66, 0xB8, 0x00, 0x00 };
642 : static const uint8 kMovBx[] = { 0x66, 0xBB, 0x00, 0x00 };
643 : static const uint8 kMovCx[] = { 0x66, 0xB9, 0x00, 0x00 };
644 : static const uint8 kMovDx[] = { 0x66, 0xBA, 0x00, 0x00 };
645 : static const uint8 kMovSi[] = { 0x66, 0xBE, 0x00, 0x00 };
646 : static const uint8 kMovDi[] = { 0x66, 0xBF, 0x00, 0x00 };
647 : static const uint8 kMovSp[] = { 0x66, 0xBC, 0x00, 0x00 };
648 : static const uint8 kMovBp[] = { 0x66, 0xBD, 0x00, 0x00 };
649 :
650 : // 8-bit partial registers.
651 E : AddInstructionFromBuffer(kMovAl);
652 E : AddInstructionFromBuffer(kMovBl);
653 E : AddInstructionFromBuffer(kMovCl);
654 E : AddInstructionFromBuffer(kMovDl);
655 :
656 E : AddInstructionFromBuffer(kMovAh);
657 E : AddInstructionFromBuffer(kMovBh);
658 E : AddInstructionFromBuffer(kMovCh);
659 E : AddInstructionFromBuffer(kMovDh);
660 :
661 : // 16-bit partial registers.
662 E : AddInstructionFromBuffer(kMovAx);
663 E : AddInstructionFromBuffer(kMovBx);
664 E : AddInstructionFromBuffer(kMovCx);
665 E : AddInstructionFromBuffer(kMovDx);
666 :
667 E : AddInstructionFromBuffer(kMovSi);
668 E : AddInstructionFromBuffer(kMovDi);
669 E : AddInstructionFromBuffer(kMovSp);
670 E : AddInstructionFromBuffer(kMovBp);
671 :
672 E : AnalyzeInstructions();
673 :
674 E : EXPECT_TRUE(is_live(assm::eax));
675 E : EXPECT_TRUE(is_live(assm::ecx));
676 E : EXPECT_TRUE(is_live(assm::edx));
677 E : EXPECT_TRUE(is_live(assm::eax));
678 E : EXPECT_TRUE(is_live(assm::esi));
679 E : EXPECT_TRUE(is_live(assm::edi));
680 E : EXPECT_TRUE(is_live(assm::esp));
681 E : EXPECT_TRUE(is_live(assm::ebp));
682 E : }
683 :
684 E : TEST_F(LivenessAnalysisTest, ArithmeticUnaryInstructions) {
685 : // _asm dec eax
686 : static const uint8 kDec1[] = { 0x48 };
687 E : AnalyzeSingleInstructionFromBuffer(kDec1);
688 E : EXPECT_TRUE(is_live(assm::eax));
689 :
690 : // _asm dec [ebx + 1]
691 : static const uint8 kDec2[] = { 0xFE, 0x4B, 0x01 };
692 E : AnalyzeSingleInstructionFromBuffer(kDec2);
693 E : EXPECT_TRUE(is_live(assm::ebx));
694 :
695 : // _asm dec [esi + ebx*2 + 1]
696 : static const uint8 kDec3[] = { 0xFE, 0x4C, 0x5E, 0x01 };
697 E : AnalyzeSingleInstructionFromBuffer(kDec3);
698 E : EXPECT_TRUE(is_live(assm::esi));
699 E : EXPECT_TRUE(is_live(assm::ebx));
700 :
701 : // _asm dec WORD PTR [X]
702 : static const uint8 kDec4[] = { 0x66, 0xFF, 0x0D, 0x80, 0x1E, 0x92, 0x00 };
703 E : AnalyzeSingleInstructionFromBuffer(kDec4);
704 E : EXPECT_FALSE(is_live(assm::eax));
705 E : EXPECT_FALSE(is_live(assm::ebx));
706 E : EXPECT_FALSE(is_live(assm::ecx));
707 E : EXPECT_FALSE(is_live(assm::edx));
708 :
709 : // _asm not ebx
710 : static const uint8 kNot1[] = { 0xF7, 0xD3 };
711 E : AnalyzeSingleInstructionFromBuffer(kNot1);
712 E : EXPECT_TRUE(is_live(assm::ebx));
713 :
714 : // _asm not [ebx]
715 : static const uint8 kNot2[] = { 0xF6, 0x13 };
716 E : AnalyzeSingleInstructionFromBuffer(kNot2);
717 E : EXPECT_TRUE(is_live(assm::ebx));
718 :
719 : // _asm neg ebx
720 : static const uint8 kNeg1[] = { 0xF7, 0xDB };
721 E : AnalyzeSingleInstructionFromBuffer(kNeg1);
722 E : EXPECT_TRUE(is_live(assm::ebx));
723 :
724 : // _asm neg [ebx]
725 : static const uint8 kNeg2[] = { 0xF6, 0x1B };
726 E : AnalyzeSingleInstructionFromBuffer(kNeg2);
727 E : EXPECT_TRUE(is_live(assm::ebx));
728 :
729 : // _asm inc edx
730 : static const uint8 kInc[] = { 0x42 };
731 E : AnalyzeSingleInstructionFromBuffer(kInc);
732 E : EXPECT_TRUE(is_live(assm::edx));
733 :
734 : // _asm inc dh
735 : static const uint8 kIncHalf[] = { 0xFE, 0xC6 };
736 E : AnalyzeSingleInstructionFromBuffer(kIncHalf);
737 E : EXPECT_TRUE(is_live(assm::edx));
738 E : EXPECT_TRUE(is_def(assm::dh));
739 E : EXPECT_FALSE(is_def(assm::dl));
740 E : EXPECT_TRUE(is_use(assm::dh));
741 E : EXPECT_FALSE(is_use(assm::dl));
742 E : }
743 :
744 E : TEST_F(LivenessAnalysisTest, DecIncFlagsInstructions) {
745 : // NOTE: inc/dec do not touch the carry flag.
746 : // _asm inc edx
747 : static const uint8 kInc[] = { 0x42 };
748 E : AddInstructionFromBuffer(kInc);
749 E : EXPECT_TRUE(CheckCarryFlagInstruction(true, false));
750 E : instructions_.clear();
751 :
752 : // _asm dec eax
753 : static const uint8 kDec1[] = { 0x48 };
754 E : AddInstructionFromBuffer(kDec1);
755 E : EXPECT_TRUE(CheckCarryFlagInstruction(true, false));
756 E : instructions_.clear();
757 E : }
758 :
759 E : TEST_F(LivenessAnalysisTest, ArithmeticBinaryInstructions) {
760 : // _asm add ebx, ecx
761 : static const uint8 kAdd[] = { 0x03, 0xD9 };
762 E : AnalyzeSingleInstructionFromBuffer(kAdd);
763 E : EXPECT_TRUE(is_live(assm::ebx));
764 E : EXPECT_TRUE(is_live(assm::ecx));
765 E : EXPECT_TRUE(is_def(assm::ebx));
766 E : EXPECT_TRUE(is_use(assm::ebx));
767 E : EXPECT_TRUE(is_use(assm::ecx));
768 :
769 : // _asm adc ebx, edx
770 : static const uint8 kAdc[] = { 0x13, 0xDA };
771 E : AnalyzeSingleInstructionFromBuffer(kAdc);
772 E : EXPECT_TRUE(is_live(assm::ebx));
773 E : EXPECT_TRUE(is_live(assm::edx));
774 :
775 : // _asm sub esi, edi
776 : static const uint8 kSub[] = { 0x2B, 0xF7 };
777 E : AnalyzeSingleInstructionFromBuffer(kSub);
778 E : EXPECT_TRUE(is_live(assm::esi));
779 E : EXPECT_TRUE(is_live(assm::edi));
780 :
781 : // _asm sbb ebx, [eax + edx + 12]
782 : static const uint8 KSbb[] = { 0x1B, 0x5C, 0x10, 0x0C };
783 E : AnalyzeSingleInstructionFromBuffer(KSbb);
784 E : EXPECT_TRUE(is_live(assm::eax));
785 E : EXPECT_TRUE(is_live(assm::ebx));
786 E : EXPECT_TRUE(is_live(assm::edx));
787 :
788 : // _asm and ebx, ecx
789 : static const uint8 kAnd[] = { 0x23, 0xD9 };
790 E : AnalyzeSingleInstructionFromBuffer(kAnd);
791 E : EXPECT_TRUE(is_live(assm::ebx));
792 E : EXPECT_TRUE(is_live(assm::ecx));
793 :
794 : // _asm or esi, [edi]
795 : static const uint8 kOr[] = { 0x0B, 0x37 };
796 E : AnalyzeSingleInstructionFromBuffer(kOr);
797 E : EXPECT_TRUE(is_live(assm::esi));
798 E : EXPECT_TRUE(is_live(assm::edi));
799 :
800 : // _asm xor [esi], edi
801 : static const uint8 kXor[] = { 0x31, 0x3E };
802 E : AnalyzeSingleInstructionFromBuffer(kXor);
803 E : EXPECT_TRUE(is_live(assm::esi));
804 E : EXPECT_TRUE(is_live(assm::edi));
805 :
806 : // _asm shl ebx, 1
807 : static const uint8 kShl1[] = { 0xD1, 0xE3 };
808 E : AnalyzeSingleInstructionFromBuffer(kShl1);
809 E : EXPECT_TRUE(is_live(assm::ebx));
810 :
811 : // _asm shr esi, 2
812 : static const uint8 kShr1[] = { 0xC1, 0xEE, 0x02 };
813 E : AnalyzeSingleInstructionFromBuffer(kShr1);
814 E : EXPECT_TRUE(is_live(assm::esi));
815 :
816 : // _asm sar ecx, 3
817 : static const uint8 kSar1[] = { 0xC1, 0xF9, 0x03 };
818 E : AnalyzeSingleInstructionFromBuffer(kSar1);
819 E : EXPECT_TRUE(is_live(assm::ecx));
820 :
821 : // _asm rol ebx, 1
822 : static const uint8 kRol1[] = { 0xD1, 0xC3 };
823 E : AnalyzeSingleInstructionFromBuffer(kRol1);
824 E : EXPECT_TRUE(is_live(assm::ebx));
825 :
826 : // _asm ror esi, 2
827 : static const uint8 kRor1[] = { 0xC1, 0xCE, 0x02 };
828 E : AnalyzeSingleInstructionFromBuffer(kRor1);
829 E : EXPECT_TRUE(is_live(assm::esi));
830 :
831 : // _asm shl ebx, cl
832 : static const uint8 kShl2[] = { 0xD3, 0xE3 };
833 E : AnalyzeSingleInstructionFromBuffer(kShl2);
834 E : EXPECT_TRUE(is_live(assm::ebx));
835 E : EXPECT_TRUE(is_live(assm::ecx));
836 :
837 : // _asm shr esi, cl
838 : static const uint8 kShr2[] = { 0xD3, 0xEE };
839 E : AnalyzeSingleInstructionFromBuffer(kShr2);
840 E : EXPECT_TRUE(is_live(assm::esi));
841 E : EXPECT_TRUE(is_live(assm::ecx));
842 :
843 : // _asm sar edx, cl
844 : static const uint8 kSar2[] = { 0xD3, 0xFA };
845 E : AnalyzeSingleInstructionFromBuffer(kSar2);
846 E : EXPECT_TRUE(is_live(assm::edx));
847 E : EXPECT_TRUE(is_live(assm::ecx));
848 :
849 : // _asm rol ebx, cl
850 : static const uint8 kRol2[] = { 0xD3, 0xC3 };
851 E : AnalyzeSingleInstructionFromBuffer(kRol2);
852 E : EXPECT_TRUE(is_live(assm::ebx));
853 E : EXPECT_TRUE(is_live(assm::ecx));
854 :
855 : // _asm ror esi, cl
856 : static const uint8 kRor2[] = { 0xD3, 0xCE };
857 E : AnalyzeSingleInstructionFromBuffer(kRor2);
858 E : EXPECT_TRUE(is_live(assm::esi));
859 E : EXPECT_TRUE(is_live(assm::ecx));
860 E : }
861 :
862 E : TEST_F(LivenessAnalysisTest, ArithmeticFlagsInstructions) {
863 : // _asm adc ebx, edx
864 : static const uint8 kAdc[] = { 0x13, 0xDA };
865 E : AnalyzeSingleInstructionFromBuffer(kAdc);
866 E : EXPECT_TRUE(CheckCarryFlagInstruction(true, true));
867 :
868 : // _asm sbb ebx, [eax + edx + 12]
869 : static const uint8 KSbb[] = { 0x1B, 0x5C, 0x10, 0x0C };
870 E : AnalyzeSingleInstructionFromBuffer(KSbb);
871 E : EXPECT_TRUE(CheckCarryFlagInstruction(true, true));
872 E : }
873 :
874 E : TEST_F(LivenessAnalysisTest, MultiplicationInstructions) {
875 : // _asm mul ecx
876 : static const uint8 kMul32[] = { 0xF7, 0xE1 };
877 E : AnalyzeSingleInstructionFromBuffer(kMul32);
878 E : EXPECT_FALSE(are_arithmetic_flags_live());
879 E : EXPECT_TRUE(is_live(assm::eax));
880 E : EXPECT_FALSE(is_live(assm::ebx));
881 E : EXPECT_TRUE(is_live(assm::ecx));
882 E : EXPECT_FALSE(is_live(assm::edx));
883 E : EXPECT_TRUE(is_def(assm::eax));
884 E : EXPECT_FALSE(is_def(assm::ecx));
885 E : EXPECT_TRUE(is_def(assm::edx));
886 E : EXPECT_TRUE(is_use(assm::eax));
887 E : EXPECT_TRUE(is_use(assm::ecx));
888 E : EXPECT_FALSE(is_use(assm::edx));
889 :
890 : // _asm mul cx
891 : static const uint8 kMul16[] = { 0x66, 0xF7, 0xE1 };
892 E : AnalyzeSingleInstructionFromBuffer(kMul16);
893 E : EXPECT_FALSE(are_arithmetic_flags_live());
894 E : EXPECT_TRUE(is_live(assm::eax));
895 E : EXPECT_FALSE(is_live(assm::ebx));
896 E : EXPECT_TRUE(is_live(assm::ecx));
897 E : EXPECT_FALSE(is_live(assm::edx));
898 E : EXPECT_TRUE(is_def(assm::eax));
899 E : EXPECT_FALSE(is_def(assm::ecx));
900 E : EXPECT_TRUE(is_use(assm::eax));
901 E : EXPECT_TRUE(is_use(assm::ecx));
902 :
903 : // _asm mul cl
904 : static const uint8 kMul8[] = { 0xF6, 0xE1 };
905 E : AnalyzeSingleInstructionFromBuffer(kMul8);
906 E : EXPECT_FALSE(are_arithmetic_flags_live());
907 E : EXPECT_TRUE(is_live(assm::eax));
908 E : EXPECT_FALSE(is_live(assm::ebx));
909 E : EXPECT_TRUE(is_live(assm::ecx));
910 E : EXPECT_FALSE(is_live(assm::edx));
911 E : EXPECT_FALSE(is_live(assm::ah));
912 E : EXPECT_TRUE(is_def(assm::eax));
913 E : EXPECT_TRUE(is_def(assm::ah));
914 E : EXPECT_FALSE(is_def(assm::ecx));
915 E : EXPECT_FALSE(is_def(assm::cl));
916 E : EXPECT_TRUE(is_use(assm::eax));
917 E : EXPECT_FALSE(is_use(assm::ah));
918 E : EXPECT_TRUE(is_use(assm::al));
919 E : EXPECT_TRUE(is_use(assm::ecx));
920 E : EXPECT_FALSE(is_use(assm::ch));
921 E : EXPECT_TRUE(is_use(assm::cl));
922 :
923 : // _asm mul ah
924 : static const uint8 kMul16High[] = { 0xF6, 0xE4 };
925 E : AnalyzeSingleInstructionFromBuffer(kMul16High);
926 E : EXPECT_FALSE(are_arithmetic_flags_live());
927 E : EXPECT_TRUE(is_live(assm::eax));
928 E : EXPECT_FALSE(is_live(assm::ebx));
929 E : EXPECT_FALSE(is_live(assm::ecx));
930 E : EXPECT_FALSE(is_live(assm::edx));
931 E : EXPECT_TRUE(is_live(assm::ah));
932 E : EXPECT_TRUE(is_def(assm::eax));
933 E : EXPECT_TRUE(is_def(assm::ah));
934 E : EXPECT_TRUE(is_def(assm::al));
935 E : EXPECT_FALSE(is_def(assm::dl));
936 E : EXPECT_TRUE(is_use(assm::ah));
937 E : EXPECT_TRUE(is_use(assm::al));
938 E : EXPECT_FALSE(is_use(assm::dl));
939 :
940 : // _asm imul ecx
941 : static const uint8 kIMul32[] = { 0xF7, 0xE9 };
942 E : AnalyzeSingleInstructionFromBuffer(kIMul32);
943 E : EXPECT_FALSE(are_arithmetic_flags_live());
944 E : EXPECT_TRUE(is_live(assm::eax));
945 E : EXPECT_FALSE(is_live(assm::ebx));
946 E : EXPECT_TRUE(is_live(assm::ecx));
947 E : EXPECT_FALSE(is_live(assm::edx));
948 E : EXPECT_TRUE(is_def(assm::al));
949 E : EXPECT_TRUE(is_def(assm::dl));
950 E : EXPECT_TRUE(is_use(assm::ecx));
951 :
952 : // _asm imul cx
953 : static const uint8 kIMul16[] = { 0xF7, 0xE9 };
954 E : AnalyzeSingleInstructionFromBuffer(kIMul16);
955 E : EXPECT_FALSE(are_arithmetic_flags_live());
956 E : EXPECT_TRUE(is_live(assm::eax));
957 E : EXPECT_FALSE(is_live(assm::ebx));
958 E : EXPECT_TRUE(is_live(assm::ecx));
959 E : EXPECT_FALSE(is_live(assm::edx));
960 E : EXPECT_TRUE(is_def(assm::al));
961 E : EXPECT_TRUE(is_def(assm::dl));
962 E : EXPECT_TRUE(is_use(assm::ecx));
963 :
964 : // _asm imul cl
965 : static const uint8 kIMul8[] = { 0xF6, 0xE9 };
966 E : AnalyzeSingleInstructionFromBuffer(kIMul8);
967 E : EXPECT_FALSE(are_arithmetic_flags_live());
968 E : EXPECT_TRUE(is_live(assm::eax));
969 E : EXPECT_FALSE(is_live(assm::ebx));
970 E : EXPECT_TRUE(is_live(assm::ecx));
971 E : EXPECT_FALSE(is_live(assm::edx));
972 E : EXPECT_FALSE(is_live(assm::ch));
973 E : EXPECT_TRUE(is_def(assm::al));
974 E : EXPECT_FALSE(is_def(assm::dl));
975 E : EXPECT_TRUE(is_use(assm::ecx));
976 :
977 : // _asm imul ah
978 : static const uint8 kIMul16High[] = { 0xF6, 0xEC };
979 E : AnalyzeSingleInstructionFromBuffer(kIMul16High);
980 E : EXPECT_FALSE(are_arithmetic_flags_live());
981 E : EXPECT_TRUE(is_live(assm::eax));
982 E : EXPECT_FALSE(is_live(assm::ebx));
983 E : EXPECT_FALSE(is_live(assm::ecx));
984 E : EXPECT_FALSE(is_live(assm::edx));
985 E : EXPECT_TRUE(is_live(assm::ah));
986 E : EXPECT_TRUE(is_def(assm::al));
987 E : EXPECT_TRUE(is_def(assm::ah));
988 E : EXPECT_TRUE(is_use(assm::al));
989 E : EXPECT_TRUE(is_use(assm::ah));
990 E : EXPECT_FALSE(is_def(assm::dl));
991 :
992 : // _asm imul eax, 3
993 : static const uint8 kIMul32ByCst[] = { 0x6B, 0xC0, 0x03 };
994 E : AnalyzeSingleInstructionFromBuffer(kIMul32ByCst);
995 E : EXPECT_FALSE(are_arithmetic_flags_live());
996 E : EXPECT_TRUE(is_live(assm::eax));
997 E : EXPECT_FALSE(is_live(assm::ebx));
998 E : EXPECT_FALSE(is_live(assm::ecx));
999 E : EXPECT_FALSE(is_live(assm::edx));
1000 E : EXPECT_TRUE(is_def(assm::eax));
1001 E : EXPECT_TRUE(is_use(assm::eax));
1002 E : EXPECT_FALSE(is_def(assm::dl));
1003 :
1004 : // _asm imul ecx, 3
1005 : static const uint8 kIMul32EcxByCst[] = { 0x6B, 0xC9, 0x03 };
1006 E : AnalyzeSingleInstructionFromBuffer(kIMul32EcxByCst);
1007 E : EXPECT_FALSE(are_arithmetic_flags_live());
1008 E : EXPECT_FALSE(are_arithmetic_flags_live());
1009 E : EXPECT_FALSE(is_live(assm::eax));
1010 E : EXPECT_FALSE(is_live(assm::ebx));
1011 E : EXPECT_TRUE(is_live(assm::ecx));
1012 E : EXPECT_FALSE(is_live(assm::edx));
1013 E : EXPECT_FALSE(is_def(assm::eax));
1014 E : EXPECT_TRUE(is_def(assm::ecx));
1015 E : EXPECT_FALSE(is_def(assm::dl));
1016 E : EXPECT_FALSE(is_use(assm::eax));
1017 E : EXPECT_TRUE(is_use(assm::ecx));
1018 E : }
1019 :
1020 E : TEST_F(LivenessAnalysisTest, ConversionInstructions) {
1021 : static const uint8 kCdq[] = { 0x99 };
1022 E : AnalyzeSingleInstructionFromBuffer(kCdq);
1023 E : EXPECT_TRUE(is_live(assm::eax));
1024 E : EXPECT_FALSE(is_live(assm::edx));
1025 E : EXPECT_FALSE(are_arithmetic_flags_live());
1026 E : EXPECT_TRUE(is_def(assm::eax));
1027 E : EXPECT_TRUE(is_def(assm::edx));
1028 E : EXPECT_TRUE(is_use(assm::eax));
1029 E : EXPECT_FALSE(is_use(assm::edx));
1030 :
1031 : static const uint8 kCwd[] = { 0x66, 0x99 };
1032 E : AnalyzeSingleInstructionFromBuffer(kCwd);
1033 E : EXPECT_TRUE(is_live(assm::eax));
1034 E : EXPECT_FALSE(is_live(assm::edx));
1035 E : EXPECT_FALSE(are_arithmetic_flags_live());
1036 E : EXPECT_TRUE(is_def(assm::eax));
1037 E : EXPECT_FALSE(is_def(assm::edx));
1038 E : EXPECT_TRUE(is_use(assm::eax));
1039 E : EXPECT_FALSE(is_use(assm::edx));
1040 E : }
1041 :
1042 E : TEST_F(LivenessAnalysisTest, EpilogueInstructions) {
1043 : static const uint8 kLeave[] = { 0xC9 };
1044 E : AnalyzeSingleInstructionFromBuffer(kLeave);
1045 E : EXPECT_TRUE(is_live(assm::ebp));
1046 E : EXPECT_TRUE(is_live(assm::esp));
1047 E : EXPECT_FALSE(are_arithmetic_flags_live());
1048 E : EXPECT_TRUE(is_def(assm::esp));
1049 E : EXPECT_TRUE(is_def(assm::ebp));
1050 E : EXPECT_TRUE(is_use(assm::esp));
1051 E : EXPECT_TRUE(is_use(assm::esp));
1052 E : }
1053 :
1054 E : TEST_F(LivenessAnalysisTest, StackInstructions) {
1055 : // Validate instructions that push/pop on the stack.
1056 : // _asm push eax
1057 : static const uint8 kPushd[] = { 0x50 };
1058 E : AnalyzeSingleInstructionFromBuffer(kPushd);
1059 E : EXPECT_TRUE(is_live(assm::esp));
1060 E : EXPECT_TRUE(is_live(assm::eax));
1061 E : EXPECT_TRUE(is_def(assm::esp));
1062 E : EXPECT_TRUE(is_use(assm::esp));
1063 :
1064 : // _asm pop eax
1065 : static const uint8 kPopd[] = { 0x58 };
1066 E : AnalyzeSingleInstructionFromBuffer(kPopd);
1067 E : EXPECT_TRUE(is_live(assm::esp));
1068 E : EXPECT_FALSE(is_live(assm::eax));
1069 E : EXPECT_TRUE(is_def(assm::esp));
1070 E : EXPECT_TRUE(is_use(assm::esp));
1071 :
1072 : // _asm push ax
1073 : static const uint8 kPush[] = { 0x66, 0x50 };
1074 E : AnalyzeSingleInstructionFromBuffer(kPush);
1075 E : EXPECT_TRUE(is_live(assm::esp));
1076 E : EXPECT_TRUE(is_live(assm::eax));
1077 E : EXPECT_TRUE(is_def(assm::esp));
1078 E : EXPECT_TRUE(is_use(assm::esp));
1079 :
1080 : // _asm pop ax
1081 : static const uint8 kPop[] = { 0x66, 0x58 };
1082 E : AnalyzeSingleInstructionFromBuffer(kPop);
1083 E : EXPECT_TRUE(is_live(assm::esp));
1084 E : EXPECT_FALSE(is_live(assm::eax));
1085 E : EXPECT_TRUE(is_def(assm::esp));
1086 E : EXPECT_TRUE(is_use(assm::esp));
1087 :
1088 : static const uint8 kPopSMem[] = { 0x66, 0x8F, 0x00 };
1089 E : AnalyzeSingleInstructionFromBuffer(kPopSMem);
1090 E : EXPECT_TRUE(is_live(assm::esp));
1091 E : EXPECT_TRUE(is_live(assm::eax));
1092 E : EXPECT_TRUE(is_def(assm::esp));
1093 E : EXPECT_TRUE(is_use(assm::esp));
1094 E : }
1095 :
1096 E : TEST_F(LivenessAnalysisTest, SetFlagInstructions) {
1097 : // Validate instructions that consume flags. Ensure flags are used.
1098 :
1099 : // _asm seta al
1100 : static const uint8 kSetA[] = { 0x0F, 0x97, 0xC0 };
1101 E : AnalyzeSingleInstructionFromBuffer(kSetA);
1102 E : EXPECT_TRUE(are_arithmetic_flags_live());
1103 E : EXPECT_TRUE(is_def(assm::al));
1104 E : EXPECT_FALSE(is_use(assm::al));
1105 :
1106 : // _asm setae al
1107 : static const uint8 kSetAE[] = { 0x0F, 0x93, 0xC0 };
1108 E : AnalyzeSingleInstructionFromBuffer(kSetAE);
1109 E : EXPECT_TRUE(are_arithmetic_flags_live());
1110 :
1111 : // _asm setb al
1112 : static const uint8 kSetB[] = { 0x0F, 0x92, 0xC0 };
1113 E : AnalyzeSingleInstructionFromBuffer(kSetB);
1114 E : EXPECT_TRUE(are_arithmetic_flags_live());
1115 :
1116 : // _asm setbe al
1117 : static const uint8 kSetBE[] = { 0x0F, 0x96, 0xC0 };
1118 E : AnalyzeSingleInstructionFromBuffer(kSetBE);
1119 E : EXPECT_TRUE(are_arithmetic_flags_live());
1120 :
1121 : // _asm setg al
1122 : static const uint8 kSetG[] = { 0x0F, 0x9F, 0xC0 };
1123 E : AnalyzeSingleInstructionFromBuffer(kSetG);
1124 E : EXPECT_TRUE(are_arithmetic_flags_live());
1125 :
1126 : // _asm setge al
1127 : static const uint8 kSetGE[] = { 0x0F, 0x9D, 0xC0 };
1128 E : AnalyzeSingleInstructionFromBuffer(kSetGE);
1129 E : EXPECT_TRUE(are_arithmetic_flags_live());
1130 :
1131 : // _asm setl al
1132 : static const uint8 kSetL[] = { 0x0F, 0x9C, 0xC0 };
1133 E : AnalyzeSingleInstructionFromBuffer(kSetL);
1134 E : EXPECT_TRUE(are_arithmetic_flags_live());
1135 :
1136 : // _asm setle al
1137 : static const uint8 kSetLE[] = { 0x0F, 0x9E, 0xC0 };
1138 E : AnalyzeSingleInstructionFromBuffer(kSetLE);
1139 E : EXPECT_TRUE(are_arithmetic_flags_live());
1140 :
1141 : // _asm setno al
1142 : static const uint8 kSetNO[] = { 0x0F, 0x91, 0xC0 };
1143 E : AnalyzeSingleInstructionFromBuffer(kSetNO);
1144 E : EXPECT_TRUE(are_arithmetic_flags_live());
1145 :
1146 : // _asm setnp al
1147 : static const uint8 kSetNP[] = { 0x0F, 0x9B, 0xC0 };
1148 E : AnalyzeSingleInstructionFromBuffer(kSetNP);
1149 E : EXPECT_TRUE(are_arithmetic_flags_live());
1150 :
1151 : // _asm setns al
1152 : static const uint8 kSetNS[] = { 0x0F, 0x99, 0xC0 };
1153 E : AnalyzeSingleInstructionFromBuffer(kSetNS);
1154 E : EXPECT_TRUE(are_arithmetic_flags_live());
1155 :
1156 : // _asm setnz al
1157 : static const uint8 kSetNZ[] = { 0x0F, 0x95, 0xC0 };
1158 E : AnalyzeSingleInstructionFromBuffer(kSetNZ);
1159 E : EXPECT_TRUE(are_arithmetic_flags_live());
1160 :
1161 : // _asm seto al
1162 : static const uint8 kSetO[] = { 0x0F, 0x90, 0xC0 };
1163 E : AnalyzeSingleInstructionFromBuffer(kSetO);
1164 E : EXPECT_TRUE(are_arithmetic_flags_live());
1165 :
1166 : // _asm setp al
1167 : static const uint8 kSetP[] = { 0x0F, 0x9A, 0xC0 };
1168 E : AnalyzeSingleInstructionFromBuffer(kSetP);
1169 E : EXPECT_TRUE(are_arithmetic_flags_live());
1170 :
1171 : // _asm sets al
1172 : static const uint8 kSetS[] = { 0x0F, 0x98, 0xC0 };
1173 E : AnalyzeSingleInstructionFromBuffer(kSetS);
1174 E : EXPECT_TRUE(are_arithmetic_flags_live());
1175 :
1176 : // _asm setz al
1177 : static const uint8 kSetZ[] = { 0x0F, 0x94, 0xC0 };
1178 E : AnalyzeSingleInstructionFromBuffer(kSetZ);
1179 E : EXPECT_TRUE(are_arithmetic_flags_live());
1180 E : }
1181 :
1182 E : TEST_F(LivenessAnalysisTest, PushPopFlagsInstructions) {
1183 : // Validate instructions that push/pop flags. Ensure flags are used, and stack
1184 : // pointer is modified.
1185 :
1186 : // _asm pushfd
1187 : static const uint8 kPushfd[] = { 0x9C };
1188 E : AnalyzeSingleInstructionFromBuffer(kPushfd);
1189 E : EXPECT_TRUE(are_arithmetic_flags_live());
1190 E : EXPECT_TRUE(is_live(assm::esp));
1191 E : EXPECT_TRUE(is_def(assm::esp));
1192 E : EXPECT_TRUE(is_use(assm::esp));
1193 :
1194 : // _asm popfd
1195 : static const uint8 kPopfd[] = { 0x9D };
1196 E : AnalyzeSingleInstructionFromBuffer(kPopfd);
1197 E : EXPECT_FALSE(are_arithmetic_flags_live());
1198 E : EXPECT_TRUE(is_live(assm::esp));
1199 E : EXPECT_TRUE(is_def(assm::esp));
1200 E : EXPECT_TRUE(is_use(assm::esp));
1201 :
1202 : // _asm pushf
1203 : static const uint8 kPushf[] = { 0x66, 0x9C };
1204 E : AnalyzeSingleInstructionFromBuffer(kPushf);
1205 E : EXPECT_TRUE(are_arithmetic_flags_live());
1206 E : EXPECT_TRUE(is_live(assm::esp));
1207 E : EXPECT_TRUE(is_def(assm::esp));
1208 E : EXPECT_TRUE(is_use(assm::esp));
1209 :
1210 : // _asm popf
1211 : static const uint8 kPopf[] = { 0x66, 0x9D };
1212 E : AnalyzeSingleInstructionFromBuffer(kPopf);
1213 E : EXPECT_FALSE(are_arithmetic_flags_live());
1214 E : EXPECT_TRUE(is_live(assm::esp));
1215 E : EXPECT_TRUE(is_def(assm::esp));
1216 E : EXPECT_TRUE(is_use(assm::esp));
1217 E : }
1218 :
1219 E : TEST_F(LivenessAnalysisTest, LoadStoreFlagsInstructions) {
1220 : // Validate instructions that load/store flags. Ensure flags are defined or
1221 : // used, and stack pointer is not modified.
1222 :
1223 : // _asm sahf
1224 : static const uint8 kSahf[] = { 0x9E };
1225 E : AnalyzeSingleInstructionFromBuffer(kSahf);
1226 E : EXPECT_FALSE(are_arithmetic_flags_live());
1227 E : EXPECT_FALSE(is_live(assm::esp));
1228 E : EXPECT_TRUE(is_live(assm::eax));
1229 E : EXPECT_FALSE(is_def(assm::ah));
1230 E : EXPECT_TRUE(is_use(assm::ah));
1231 :
1232 : // _asm lahf
1233 : static const uint8 kLahf[] = { 0x9F };
1234 E : AnalyzeSingleInstructionFromBuffer(kLahf);
1235 E : EXPECT_TRUE(are_arithmetic_flags_live());
1236 E : EXPECT_FALSE(is_live(assm::esp));
1237 E : EXPECT_FALSE(is_live(assm::eax));
1238 E : EXPECT_TRUE(is_def(assm::ah));
1239 E : EXPECT_FALSE(is_use(assm::ah));
1240 E : }
1241 :
1242 E : TEST_F(LivenessAnalysisTest, ExtendMovInstructions) {
1243 : // _asm movsx eax, cl
1244 : static const uint8 kMovsx1[] = { 0x0F, 0xBE, 0xC1 };
1245 E : AnalyzeSingleInstructionFromBuffer(kMovsx1);
1246 E : EXPECT_FALSE(are_arithmetic_flags_live());
1247 E : EXPECT_FALSE(is_live(assm::eax));
1248 E : EXPECT_TRUE(is_live(assm::ecx));
1249 E : EXPECT_TRUE(is_def(assm::ah));
1250 E : EXPECT_FALSE(is_use(assm::ch));
1251 :
1252 : // _asm movsx eax, BYTE PTR [ecx]
1253 : static const uint8 kMovsx2[] = { 0x0F, 0xBE, 0x01 };
1254 E : AnalyzeSingleInstructionFromBuffer(kMovsx2);
1255 E : EXPECT_FALSE(are_arithmetic_flags_live());
1256 E : EXPECT_FALSE(is_live(assm::eax));
1257 E : EXPECT_TRUE(is_live(assm::ecx));
1258 :
1259 : // _asm movzx eax, cl
1260 : static const uint8 kMovzx1[] = { 0x0F, 0xB6, 0xC1 };
1261 E : AnalyzeSingleInstructionFromBuffer(kMovzx1);
1262 E : EXPECT_FALSE(are_arithmetic_flags_live());
1263 E : EXPECT_FALSE(is_live(assm::eax));
1264 E : EXPECT_TRUE(is_live(assm::ecx));
1265 :
1266 : // _asm movzx eax, BYTE PTR [ecx]
1267 : static const uint8 kMovzx2[] = { 0x0F, 0xB6, 0x01 };
1268 E : AnalyzeSingleInstructionFromBuffer(kMovzx2);
1269 E : EXPECT_FALSE(are_arithmetic_flags_live());
1270 E : EXPECT_FALSE(is_live(assm::eax));
1271 E : EXPECT_TRUE(is_live(assm::ecx));
1272 E : }
1273 :
1274 E : TEST_F(LivenessAnalysisTest, StringInstructions) {
1275 : // movs dword ptr es:[edi], dword ptr [esi]
1276 : static const uint8 kMovsl[] = { 0xA5 };
1277 E : AnalyzeSingleInstructionFromBuffer(kMovsl);
1278 E : EXPECT_TRUE(is_live(assm::esi));
1279 E : EXPECT_TRUE(is_live(assm::edi));
1280 E : EXPECT_FALSE(is_live(assm::ecx));
1281 E : EXPECT_FALSE(are_arithmetic_flags_live());
1282 E : EXPECT_TRUE(is_def(assm::esi));
1283 E : EXPECT_TRUE(is_def(assm::edi));
1284 E : EXPECT_TRUE(is_use(assm::esi));
1285 E : EXPECT_TRUE(is_use(assm::edi));
1286 :
1287 : // movs byte ptr es:[edi], byte ptr [esi]
1288 : static const uint8 kMovsb[] = { 0xA4 };
1289 E : AnalyzeSingleInstructionFromBuffer(kMovsb);
1290 E : EXPECT_TRUE(is_live(assm::esi));
1291 E : EXPECT_TRUE(is_live(assm::edi));
1292 E : EXPECT_FALSE(is_live(assm::ecx));
1293 E : EXPECT_FALSE(are_arithmetic_flags_live());
1294 :
1295 : // stos dword ptr es:[edi]
1296 : static const uint8 kStosl[] = { 0xAB };
1297 E : AnalyzeSingleInstructionFromBuffer(kStosl);
1298 E : EXPECT_FALSE(is_live(assm::esi));
1299 E : EXPECT_TRUE(is_live(assm::edi));
1300 E : EXPECT_FALSE(is_live(assm::ecx));
1301 E : EXPECT_FALSE(are_arithmetic_flags_live());
1302 E : EXPECT_FALSE(is_def(assm::esi));
1303 E : EXPECT_TRUE(is_def(assm::edi));
1304 E : EXPECT_FALSE(is_use(assm::esi));
1305 E : EXPECT_TRUE(is_use(assm::edi));
1306 :
1307 : // stos byte ptr es:[edi]
1308 : static const uint8 Stosb[] = { 0xAA };
1309 E : AnalyzeSingleInstructionFromBuffer(Stosb);
1310 E : EXPECT_FALSE(is_live(assm::esi));
1311 E : EXPECT_TRUE(is_live(assm::edi));
1312 E : EXPECT_FALSE(is_live(assm::ecx));
1313 E : EXPECT_FALSE(are_arithmetic_flags_live());
1314 E : }
1315 :
1316 E : TEST_F(LivenessAnalysisTest, PrefixedStringInstructions) {
1317 : // repne movs dword ptr es:[edi], dword ptr [esi]
1318 : static const uint8 kMovsl[] = { 0xF2, 0xA5 };
1319 E : AnalyzeSingleInstructionFromBuffer(kMovsl);
1320 E : EXPECT_TRUE(is_live(assm::esi));
1321 E : EXPECT_TRUE(is_live(assm::edi));
1322 E : EXPECT_TRUE(is_live(assm::ecx));
1323 E : EXPECT_FALSE(are_arithmetic_flags_live());
1324 :
1325 : // repne movs byte ptr es:[edi], byte ptr [esi]
1326 : static const uint8 kMovsb[] = { 0xF2, 0xA4 };
1327 E : AnalyzeSingleInstructionFromBuffer(kMovsb);
1328 E : EXPECT_TRUE(is_live(assm::esi));
1329 E : EXPECT_TRUE(is_live(assm::edi));
1330 E : EXPECT_TRUE(is_live(assm::ecx));
1331 E : EXPECT_FALSE(are_arithmetic_flags_live());
1332 :
1333 : // repne stos dword ptr es:[edi]
1334 : static const uint8 kStosl[] = { 0xF2, 0xAB };
1335 E : AnalyzeSingleInstructionFromBuffer(kStosl);
1336 E : EXPECT_FALSE(is_live(assm::esi));
1337 E : EXPECT_TRUE(is_live(assm::edi));
1338 E : EXPECT_TRUE(is_live(assm::ecx));
1339 E : EXPECT_FALSE(are_arithmetic_flags_live());
1340 :
1341 : // repne stos byte ptr es:[edi]
1342 : static const uint8 Stosb[] = { 0xF2, 0xAA };
1343 E : AnalyzeSingleInstructionFromBuffer(Stosb);
1344 E : EXPECT_FALSE(is_live(assm::esi));
1345 E : EXPECT_TRUE(is_live(assm::edi));
1346 E : EXPECT_TRUE(is_live(assm::ecx));
1347 E : EXPECT_FALSE(are_arithmetic_flags_live());
1348 E : }
1349 :
1350 E : TEST_F(LivenessAnalysisTest, FloatingPointInstructions) {
1351 : // _asm fld1
1352 : static const uint8 kFld1[] = { 0xD9, 0xE8 };
1353 : // _asm fldz
1354 : static const uint8 kFldz[] = { 0xD9, 0xEE };
1355 : // _asm fadd
1356 : static const uint8 kFadd[] = { 0xDE, 0xC1 };
1357 : // _asm faddp st(3), st(0)
1358 : static const uint8 kFaddp[] = { 0xDE, 0xC3 };
1359 : // _asm fsub
1360 : static const uint8 kFsub[] = { 0xDE, 0xE9 };
1361 : // _asm fsubp st(3), st(0)
1362 : static const uint8 kFsubp[] = { 0xDE, 0xEB };
1363 : // _asm fmul
1364 : static const uint8 kFmul[] = { 0xDE, 0xC9 };
1365 : // _asm fmulp st(3), st(0)
1366 : static const uint8 kFmulp[] = { 0xDE, 0xCB };
1367 :
1368 : // Floating point instructions don't touch any register nor general registers.
1369 E : AddInstructionFromBuffer(kFld1);
1370 E : AddInstructionFromBuffer(kFldz);
1371 E : AddInstructionFromBuffer(kFadd);
1372 E : AddInstructionFromBuffer(kFaddp);
1373 E : AddInstructionFromBuffer(kFsub);
1374 E : AddInstructionFromBuffer(kFsubp);
1375 E : AddInstructionFromBuffer(kFmul);
1376 E : AddInstructionFromBuffer(kFmulp);
1377 E : DefineAllRegisters();
1378 E : AnalyzeInstructions();
1379 :
1380 E : EXPECT_FALSE(is_live(assm::eax));
1381 E : EXPECT_FALSE(is_live(assm::ebx));
1382 E : EXPECT_FALSE(is_live(assm::ecx));
1383 E : EXPECT_FALSE(is_live(assm::edx));
1384 E : EXPECT_FALSE(is_live(assm::esi));
1385 E : EXPECT_FALSE(is_live(assm::edi));
1386 E : EXPECT_FALSE(are_arithmetic_flags_live());
1387 E : }
1388 :
1389 E : TEST_F(LivenessAnalysisTest, FloatingPointMemoryInstructions) {
1390 : // _asm fld DWORD PTR [eax + ecx]
1391 : static const uint8 kFld[] = { 0xD9, 0x04, 0x08 };
1392 E : AnalyzeSingleInstructionFromBuffer(kFld);
1393 E : EXPECT_TRUE(is_live(assm::eax));
1394 E : EXPECT_FALSE(is_live(assm::ebx));
1395 E : EXPECT_TRUE(is_live(assm::ecx));
1396 E : EXPECT_FALSE(are_arithmetic_flags_live());
1397 :
1398 : // _asm fst DWORD PTR [eax + ecx]
1399 : static const uint8 kFst[] = { 0xD9, 0x14, 0x08 };
1400 E : AnalyzeSingleInstructionFromBuffer(kFst);
1401 E : EXPECT_TRUE(is_live(assm::eax));
1402 E : EXPECT_FALSE(is_live(assm::ebx));
1403 E : EXPECT_TRUE(is_live(assm::ecx));
1404 E : EXPECT_FALSE(are_arithmetic_flags_live());
1405 :
1406 : // _asm fstp DWORD PTR [eax + ecx]
1407 : static const uint8 kFstp[] = { 0xD9, 0x1C, 0x08 };
1408 E : AnalyzeSingleInstructionFromBuffer(kFstp);
1409 E : EXPECT_TRUE(is_live(assm::eax));
1410 E : EXPECT_FALSE(is_live(assm::ebx));
1411 E : EXPECT_TRUE(is_live(assm::ecx));
1412 E : EXPECT_FALSE(are_arithmetic_flags_live());
1413 :
1414 : // _asm fadd DWORD PTR [eax]
1415 : static const uint8 kFadd[] = { 0xD8, 0x00 };
1416 E : AnalyzeSingleInstructionFromBuffer(kFadd);
1417 E : EXPECT_TRUE(is_live(assm::eax));
1418 E : EXPECT_FALSE(are_arithmetic_flags_live());
1419 :
1420 : // _asm fsub DWORD PTR [ecx]
1421 : static const uint8 kFsub[] = { 0xD8, 0x21 };
1422 E : AnalyzeSingleInstructionFromBuffer(kFsub);
1423 E : EXPECT_TRUE(is_live(assm::ecx));
1424 E : EXPECT_FALSE(are_arithmetic_flags_live());
1425 :
1426 : // _asm fmul DWORD PTR [esi]
1427 : static const uint8 kFmul[] = { 0xD8, 0x0E };
1428 E : AnalyzeSingleInstructionFromBuffer(kFmul);
1429 E : EXPECT_TRUE(is_live(assm::esi));
1430 E : EXPECT_FALSE(are_arithmetic_flags_live());
1431 :
1432 : // _asm fild DWORD PTR [eax]
1433 : static const uint8 kFild[] = { 0xDB, 0x00 };
1434 E : AnalyzeSingleInstructionFromBuffer(kFild);
1435 E : EXPECT_TRUE(is_live(assm::eax));
1436 E : EXPECT_FALSE(are_arithmetic_flags_live());
1437 :
1438 : // _asm fist DWORD PTR [eax]
1439 : static const uint8 kFist[] = { 0xDB, 0x10 };
1440 E : AnalyzeSingleInstructionFromBuffer(kFist);
1441 E : EXPECT_TRUE(is_live(assm::eax));
1442 E : EXPECT_FALSE(are_arithmetic_flags_live());
1443 :
1444 : // _asm fistp DWORD PTR [eax]
1445 : static const uint8 kFistp[] = { 0xDB, 0x18 };
1446 E : AnalyzeSingleInstructionFromBuffer(kFistp);
1447 E : EXPECT_TRUE(is_live(assm::eax));
1448 E : EXPECT_FALSE(are_arithmetic_flags_live());
1449 E : }
1450 :
1451 E : TEST_F(LivenessAnalysisTest, FloatingPointCompareInstructions) {
1452 : // _asm fcom
1453 : static const uint8 kFcom[] = { 0xD8, 0xD1 };
1454 E : AnalyzeSingleInstructionFromBuffer(kFcom);
1455 E : EXPECT_FALSE(are_arithmetic_flags_live());
1456 :
1457 : // _asm fcomp
1458 : static const uint8 kFcomp[] = { 0xD8, 0xD9 };
1459 E : AnalyzeSingleInstructionFromBuffer(kFcomp);
1460 E : EXPECT_FALSE(are_arithmetic_flags_live());
1461 :
1462 : // _asm fcompp
1463 : static const uint8 kFcompp[] = { 0xDE, 0xD9 };
1464 E : AnalyzeSingleInstructionFromBuffer(kFcompp);
1465 E : EXPECT_FALSE(are_arithmetic_flags_live());
1466 :
1467 : // _asm fcomi
1468 : static const uint8 kFcomi[] = { 0xDB, 0xF1 };
1469 E : AnalyzeSingleInstructionFromBuffer(kFcomi);
1470 E : EXPECT_FALSE(are_arithmetic_flags_live());
1471 :
1472 : // _asm fcomip
1473 : static const uint8 fcomip[] = { 0xDF, 0xF1 };
1474 E : AnalyzeSingleInstructionFromBuffer(fcomip);
1475 E : EXPECT_FALSE(are_arithmetic_flags_live());
1476 E : }
1477 :
1478 E : TEST_F(LivenessAnalysisTest, FloatingPointCompareMemoryInstructions) {
1479 : // _asm fcom qword ptr [edx+ecx*8]
1480 : static const uint8 kFcom[] = { 0xDC, 0x14, 0xCA };
1481 E : AnalyzeSingleInstructionFromBuffer(kFcom);
1482 E : EXPECT_FALSE(is_live(assm::eax));
1483 E : EXPECT_FALSE(is_live(assm::ebx));
1484 E : EXPECT_TRUE(is_live(assm::ecx));
1485 E : EXPECT_TRUE(is_live(assm::edx));
1486 E : EXPECT_FALSE(are_arithmetic_flags_live());
1487 :
1488 : // _asm fcomp word ptr [edx+ecx*8]
1489 : static const uint8 kFcomp[] = { 0xDC, 0x1C, 0xCA };
1490 E : AnalyzeSingleInstructionFromBuffer(kFcomp);
1491 E : EXPECT_FALSE(is_live(assm::eax));
1492 E : EXPECT_FALSE(is_live(assm::ebx));
1493 E : EXPECT_TRUE(is_live(assm::ecx));
1494 E : EXPECT_TRUE(is_live(assm::edx));
1495 E : EXPECT_FALSE(are_arithmetic_flags_live());
1496 :
1497 : // _asm ficom qword ptr [edx+ecx*8]
1498 : static const uint8 kFicom[] = { 0xDE, 0x14, 0xCA };
1499 E : AnalyzeSingleInstructionFromBuffer(kFicom);
1500 E : EXPECT_FALSE(is_live(assm::eax));
1501 E : EXPECT_FALSE(is_live(assm::ebx));
1502 E : EXPECT_TRUE(is_live(assm::ecx));
1503 E : EXPECT_TRUE(is_live(assm::edx));
1504 E : EXPECT_FALSE(are_arithmetic_flags_live());
1505 :
1506 : // _asm ficomp word ptr [edx+ecx*8]
1507 : static const uint8 kFicomp[] = { 0xDE, 0x1C, 0xCA };
1508 E : AnalyzeSingleInstructionFromBuffer(kFicomp);
1509 E : EXPECT_FALSE(is_live(assm::eax));
1510 E : EXPECT_FALSE(is_live(assm::ebx));
1511 E : EXPECT_TRUE(is_live(assm::ecx));
1512 E : EXPECT_TRUE(is_live(assm::edx));
1513 E : EXPECT_FALSE(are_arithmetic_flags_live());
1514 :
1515 : // _asm ficom dword ptr [eax]
1516 : static const uint8 kFicom2[] = { 0xDA, 0x10 };
1517 E : AnalyzeSingleInstructionFromBuffer(kFicom2);
1518 E : EXPECT_TRUE(is_live(assm::eax));
1519 E : EXPECT_FALSE(is_live(assm::edx));
1520 E : EXPECT_FALSE(are_arithmetic_flags_live());
1521 :
1522 : // _asm ficomp dword ptr [eax]
1523 : static const uint8 ficomp2[] = { 0xDA, 0x18 };
1524 E : AnalyzeSingleInstructionFromBuffer(ficomp2);
1525 E : EXPECT_TRUE(is_live(assm::eax));
1526 E : EXPECT_FALSE(is_live(assm::edx));
1527 E : EXPECT_FALSE(are_arithmetic_flags_live());
1528 E : }
1529 :
1530 E : TEST_F(LivenessAnalysisTest, FloatingPointCompareWithFlagsInstructions) {
1531 : // Some floating point operations modify eflags.
1532 :
1533 : // _asm fcomi
1534 : static const uint8 kFcomi[] = { 0xDB, 0xF1 };
1535 E : AddInstructionFromBuffer(kFcomi);
1536 E : EXPECT_TRUE(CheckCarryFlagInstruction(false, false));
1537 E : instructions_.clear();
1538 :
1539 : // _asm fcomip
1540 : static const uint8 fcomip[] = { 0xDF, 0xF1 };
1541 E : AddInstructionFromBuffer(fcomip);
1542 E : EXPECT_TRUE(CheckCarryFlagInstruction(false, false));
1543 E : instructions_.clear();
1544 E : }
1545 :
1546 E : TEST_F(LivenessAnalysisTest, UnknownInstruction) {
1547 : // Ensure unknown instructions are processed correctly.
1548 : static const uint8 kRdtsc[] = { 0x0F, 0x31 };
1549 E : AnalyzeSingleInstructionFromBuffer(kRdtsc);
1550 E : EXPECT_TRUE(is_live(assm::eax));
1551 E : EXPECT_TRUE(is_live(assm::ecx));
1552 E : EXPECT_TRUE(is_live(assm::esi));
1553 E : EXPECT_TRUE(is_live(assm::ebp));
1554 E : EXPECT_TRUE(are_arithmetic_flags_live());
1555 E : }
1556 :
1557 E : TEST_F(LivenessAnalysisTest, XorInitializationSpecialCase) {
1558 : // Validate an initialization pattern used by x86 compiler.
1559 : // Ensure the flags are assumed modified, and the register is unused.
1560 :
1561 : // _asm xor eax, eax
1562 : static const uint8 kXor1[] = { 0x33, 0xC0 };
1563 E : AnalyzeSingleInstructionFromBuffer(kXor1);
1564 E : EXPECT_FALSE(is_live(assm::eax));
1565 E : EXPECT_FALSE(are_arithmetic_flags_live());
1566 E : EXPECT_TRUE(is_def(assm::eax));
1567 E : EXPECT_FALSE(is_use(assm::eax));
1568 :
1569 : // _asm xor ebx, ebx
1570 : static const uint8 kXor2[] = { 0x33, 0xDB };
1571 E : AnalyzeSingleInstructionFromBuffer(kXor2);
1572 E : EXPECT_FALSE(is_live(assm::eax));
1573 E : EXPECT_FALSE(are_arithmetic_flags_live());
1574 E : EXPECT_TRUE(is_def(assm::ebx));
1575 E : EXPECT_FALSE(is_use(assm::ebx));
1576 :
1577 : // _asm xor ecx, ecx
1578 : static const uint8 kXor3[] = { 0x33, 0xC9 };
1579 E : AnalyzeSingleInstructionFromBuffer(kXor3);
1580 E : EXPECT_FALSE(is_live(assm::eax));
1581 E : EXPECT_FALSE(are_arithmetic_flags_live());
1582 E : EXPECT_TRUE(is_def(assm::ecx));
1583 E : EXPECT_FALSE(is_use(assm::ecx));
1584 E : }
1585 :
1586 E : TEST_F(LivenessAnalysisTest, NopInstructionSpecialCase) {
1587 : // Nop should be ignored by the analysis.
1588 E : asm_.mov(assm::eax, assm::eax);
1589 E : asm_.mov(assm::eax, Immediate(10));
1590 E : AnalyzeInstructions();
1591 E : EXPECT_FALSE(is_live(assm::eax));
1592 E : }
1593 :
1594 E : TEST_F(LivenessAnalysisTest, GetStateAtEntryOfWithNull) {
1595 : // It is valid to pass a NULL pointer to get a state.
1596 E : liveness_.GetStateAtEntryOf(NULL, &state_);
1597 E : EXPECT_TRUE(is_live(assm::eax));
1598 E : EXPECT_TRUE(is_live(assm::esi));
1599 E : EXPECT_TRUE(are_arithmetic_flags_live());
1600 E : }
1601 :
1602 E : TEST_F(LivenessAnalysisTest, GetStateAtExitOfWithNull) {
1603 : // It is valid to pass a NULL pointer to get a state.
1604 E : liveness_.GetStateAtExitOf(NULL, &state_);
1605 E : EXPECT_TRUE(is_live(assm::eax));
1606 E : EXPECT_TRUE(is_live(assm::esi));
1607 E : EXPECT_TRUE(are_arithmetic_flags_live());
1608 E : }
1609 :
1610 E : TEST_F(LivenessAnalysisTest, LivenessAnalysisOverControlFlow) {
1611 E : BasicBlockSubGraph subgraph;
1612 :
1613 : // Build and analyze this flow graph:
1614 : // [if1]
1615 : // / \
1616 : // / \
1617 : // [true1] [false1]
1618 : // mov esi, 1 mov esi, 2
1619 : // mov edi, 2
1620 : // \ /
1621 : // \ /
1622 : // [if2] <-----------
1623 : // / \ \
1624 : // / \ \
1625 : // [true2] [false2] \
1626 : // mov eax, ebx mov ebp, esi |
1627 : // mov esi, edi |
1628 : // mov edi, ebp |
1629 : // mov eax, [esi] |
1630 : // \ / |
1631 : // \ / |
1632 : // [end2] /
1633 : // mov ecx, eax /
1634 : // \ /
1635 : // -----------------/
1636 :
1637 : // Create the control flow graph.
1638 E : BasicCodeBlock* if1 = subgraph.AddBasicCodeBlock("if1");
1639 E : BasicCodeBlock* true1 = subgraph.AddBasicCodeBlock("true1");
1640 E : BasicCodeBlock* false1 = subgraph.AddBasicCodeBlock("false1");
1641 E : BasicCodeBlock* if2 = subgraph.AddBasicCodeBlock("if2");
1642 E : BasicCodeBlock* true2 = subgraph.AddBasicCodeBlock("true2");
1643 E : BasicCodeBlock* false2 = subgraph.AddBasicCodeBlock("false2");
1644 E : BasicCodeBlock* end2 = subgraph.AddBasicCodeBlock("end2");
1645 :
1646 E : ASSERT_TRUE(if1 != NULL);
1647 E : ASSERT_TRUE(true1 != NULL);
1648 E : ASSERT_TRUE(false1 != NULL);
1649 E : ASSERT_TRUE(if2 != NULL);
1650 E : ASSERT_TRUE(true2 != NULL);
1651 E : ASSERT_TRUE(false2 != NULL);
1652 E : ASSERT_TRUE(end2 != NULL);
1653 :
1654 E : AddSuccessorBetween(Successor::kConditionEqual, if1, true1);
1655 E : AddSuccessorBetween(Successor::kConditionNotEqual, if1, false1);
1656 E : AddSuccessorBetween(Successor::kConditionTrue, true1, if2);
1657 E : AddSuccessorBetween(Successor::kConditionTrue, false1, if2);
1658 :
1659 E : AddSuccessorBetween(Successor::kConditionOverflow, if2, true2);
1660 E : AddSuccessorBetween(Successor::kConditionNotOverflow, if2, false2);
1661 E : AddSuccessorBetween(Successor::kConditionLess, true2, end2);
1662 E : AddSuccessorBetween(Successor::kConditionLess, false2, end2);
1663 :
1664 E : AddSuccessorBetween(Successor::kConditionTrue, end2, if2);
1665 :
1666 : // Insert instructions into basic blocks.
1667 : BasicBlockAssembler asm_end2(end2->instructions().end(),
1668 E : &end2->instructions());
1669 E : asm_end2.mov(assm::ecx, assm::eax);
1670 :
1671 : BasicBlockAssembler asm_true2(true2->instructions().end(),
1672 E : &true2->instructions());
1673 E : asm_true2.mov(assm::eax, assm::ebx);
1674 :
1675 : BasicBlockAssembler asm_false2(false2->instructions().end(),
1676 E : &false2->instructions());
1677 E : asm_false2.mov(assm::ebp, assm::esi);
1678 E : asm_false2.mov(assm::esi, assm::edi);
1679 E : asm_false2.mov(assm::edi, assm::ebp);
1680 E : asm_false2.mov(assm::eax, Operand(assm::esi));
1681 :
1682 : BasicBlockAssembler asm_true1(true1->instructions().end(),
1683 E : &true1->instructions());
1684 E : asm_true1.mov(assm::esi, Immediate(1));
1685 :
1686 : BasicBlockAssembler asm_false1(false1->instructions().end(),
1687 E : &false1->instructions());
1688 E : asm_false1.mov(assm::esi, Immediate(2));
1689 E : asm_false1.mov(assm::edi, Immediate(2));
1690 :
1691 : // Perform global liveness analysis.
1692 E : liveness_.Analyze(&subgraph);
1693 :
1694 : // Validate fix-point propagation.
1695 E : liveness_.GetStateAtEntryOf(end2, &state_);
1696 E : EXPECT_TRUE(is_live(assm::eax));
1697 E : EXPECT_TRUE(is_live(assm::ebx));
1698 E : EXPECT_FALSE(is_live(assm::ecx));
1699 E : EXPECT_TRUE(is_live(assm::esi));
1700 E : EXPECT_TRUE(is_live(assm::edi));
1701 E : EXPECT_FALSE(is_live(assm::ebp));
1702 :
1703 E : liveness_.GetStateAtEntryOf(true2, &state_);
1704 E : EXPECT_FALSE(is_live(assm::eax));
1705 E : EXPECT_TRUE(is_live(assm::ebx));
1706 E : EXPECT_FALSE(is_live(assm::ecx));
1707 E : EXPECT_TRUE(is_live(assm::esi));
1708 E : EXPECT_TRUE(is_live(assm::edi));
1709 E : EXPECT_FALSE(is_live(assm::ebp));
1710 :
1711 E : liveness_.GetStateAtEntryOf(false2, &state_);
1712 E : EXPECT_FALSE(is_live(assm::eax));
1713 E : EXPECT_TRUE(is_live(assm::ebx));
1714 E : EXPECT_FALSE(is_live(assm::ecx));
1715 E : EXPECT_TRUE(is_live(assm::esi));
1716 E : EXPECT_TRUE(is_live(assm::edi));
1717 E : EXPECT_FALSE(is_live(assm::ebp));
1718 :
1719 E : liveness_.GetStateAtEntryOf(if2, &state_);
1720 E : EXPECT_FALSE(is_live(assm::eax));
1721 E : EXPECT_TRUE(is_live(assm::ebx));
1722 E : EXPECT_FALSE(is_live(assm::ecx));
1723 E : EXPECT_TRUE(is_live(assm::esi));
1724 E : EXPECT_TRUE(is_live(assm::edi));
1725 E : EXPECT_FALSE(is_live(assm::ebp));
1726 :
1727 E : liveness_.GetStateAtEntryOf(true1, &state_);
1728 E : EXPECT_FALSE(is_live(assm::eax));
1729 E : EXPECT_TRUE(is_live(assm::ebx));
1730 E : EXPECT_FALSE(is_live(assm::ecx));
1731 E : EXPECT_FALSE(is_live(assm::esi));
1732 E : EXPECT_TRUE(is_live(assm::edi));
1733 E : EXPECT_FALSE(is_live(assm::ebp));
1734 :
1735 E : liveness_.GetStateAtEntryOf(false1, &state_);
1736 E : EXPECT_FALSE(is_live(assm::eax));
1737 E : EXPECT_TRUE(is_live(assm::ebx));
1738 E : EXPECT_FALSE(is_live(assm::ecx));
1739 E : EXPECT_FALSE(is_live(assm::esi));
1740 E : EXPECT_FALSE(is_live(assm::edi));
1741 E : EXPECT_FALSE(is_live(assm::ebp));
1742 :
1743 E : liveness_.GetStateAtEntryOf(if1, &state_);
1744 E : EXPECT_FALSE(is_live(assm::eax));
1745 E : EXPECT_TRUE(is_live(assm::ebx));
1746 E : EXPECT_FALSE(is_live(assm::ecx));
1747 E : EXPECT_FALSE(is_live(assm::esi));
1748 E : EXPECT_TRUE(is_live(assm::edi));
1749 E : EXPECT_FALSE(is_live(assm::ebp));
1750 E : }
1751 :
1752 E : TEST_F(LivenessAnalysisTest, AnalyzeWithData) {
1753 E : BasicBlockSubGraph subgraph;
1754 E : const uint8 raw_data[] = { 0, 1, 2, 3, 4 };
1755 :
1756 : BlockDescription* block = subgraph.AddBlockDescription(
1757 E : "b1", "b1.obj", BlockGraph::CODE_BLOCK, 7, 2, 42);
1758 :
1759 E : BasicCodeBlock* bb = subgraph.AddBasicCodeBlock("bb");
1760 : BasicDataBlock* data =
1761 E : subgraph.AddBasicDataBlock("data", sizeof(raw_data), &raw_data[0]);
1762 :
1763 E : block->basic_block_order.push_back(bb);
1764 E : block->basic_block_order.push_back(data);
1765 :
1766 E : BasicBlockAssembler asm_bb(bb->instructions().end(), &bb->instructions());
1767 E : asm_bb.mov(assm::eax, assm::ebx);
1768 E : asm_bb.ret();
1769 :
1770 : // Analyze the flow graph.
1771 E : liveness_.Analyze(&subgraph);
1772 :
1773 E : liveness_.GetStateAtEntryOf(bb, &state_);
1774 E : EXPECT_FALSE(is_live(assm::eax));
1775 E : EXPECT_TRUE(is_live(assm::ebx));
1776 E : EXPECT_TRUE(is_live(assm::esi));
1777 :
1778 E : liveness_.GetStateAtEntryOf(data, &state_);
1779 E : EXPECT_TRUE(is_live(assm::eax));
1780 E : EXPECT_TRUE(is_live(assm::ebx));
1781 E : EXPECT_TRUE(is_live(assm::esi));
1782 E : }
1783 :
1784 : } // namespace
1785 :
1786 : } // namespace analysis
1787 : } // namespace block_graph
|