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