1 : // Copyright 2012 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 : //
15 : // Tests for the basic block classes.
16 :
17 : #include "syzygy/block_graph/block_builder.h"
18 :
19 : #include "gmock/gmock.h"
20 : #include "gtest/gtest.h"
21 : #include "syzygy/block_graph/basic_block.h"
22 : #include "syzygy/block_graph/basic_block_subgraph.h"
23 : #include "syzygy/block_graph/basic_block_test_util.h"
24 : #include "syzygy/block_graph/block_graph.h"
25 :
26 : namespace block_graph {
27 :
28 : namespace {
29 :
30 : typedef BlockGraph::Block Block;
31 : typedef BlockGraph::Label Label;
32 : typedef BlockGraph::Reference Reference;
33 : typedef Block::Referrer Referrer;
34 :
35 : const uint8 kEmptyData[32] = { 0 };
36 :
37 : // Instructions we'll need in order to build the test subgraph.
38 : // TODO(rogerm): Share these definitions from a central location for all the
39 : // basic-block, builder and assembler/decomposer unit-tests.
40 : const uint8 kCall[5] = { 0xE8, 0x00, 0x00, 0x00, 0x00 };
41 : const uint8 kNop1[1] = { 0x90 };
42 : const uint8 kNop2[2] = { 0x66, 0x90 };
43 : const uint8 kNop3[3] = { 0x66, 0x66, 0x90 };
44 : const uint8 kNop7[7] = { 0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00 };
45 : const uint8 kNop9[9] = { 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 };
46 :
47 : class BlockBuilderTest : public testing::BasicBlockTest {
48 : public:
49 : static Instruction* AddInstruction(BasicCodeBlock* bb,
50 : const uint8* buf,
51 E : size_t len) {
52 E : CHECK(bb != NULL);
53 E : Instruction tmp;
54 E : EXPECT_TRUE(Instruction::FromBuffer(buf, len, &tmp));
55 E : EXPECT_EQ(len, tmp.size());
56 :
57 E : bb->instructions().push_back(tmp);
58 E : return &bb->instructions().back();
59 E : }
60 :
61 : BasicCodeBlock* CreateCodeBB(const base::StringPiece& name,
62 E : size_t len) {
63 E : Instruction nop;
64 E : EXPECT_EQ(1U, nop.size());
65 E : BasicCodeBlock* bb = subgraph_.AddBasicCodeBlock(name);
66 E : EXPECT_TRUE(bb != NULL);
67 E : for (size_t i = 0; i < len; ++i)
68 E : bb->instructions().push_back(nop);
69 E : return bb;
70 E : }
71 :
72 E : Block* CreateLayout(size_t size1, size_t size2, size_t size3, size_t size4) {
73 : // Generate a set of puzzle blocks.
74 E : BasicCodeBlock* bb1 = CreateCodeBB("bb1", size1);
75 E : BasicCodeBlock* bb2 = CreateCodeBB("bb2", size2);
76 E : BasicCodeBlock* bb3 = CreateCodeBB("bb3", size3);
77 E : BasicCodeBlock* bb4 = CreateCodeBB("bb3", size4);
78 :
79 : // BB1 has BB4 and BB2 as successors.
80 : bb1->successors().push_back(
81 : Successor(Successor::kConditionEqual,
82 : BasicBlockReference(BlockGraph::RELATIVE_REF, 4, bb4),
83 E : 0));
84 : bb1->successors().push_back(
85 : Successor(Successor::kConditionNotEqual,
86 : BasicBlockReference(BlockGraph::RELATIVE_REF, 4, bb2),
87 E : 0));
88 :
89 : // BB2 has BB1 as successor.
90 : bb2->successors().push_back(
91 : Successor(Successor::kConditionTrue,
92 : BasicBlockReference(BlockGraph::RELATIVE_REF, 4, bb1),
93 E : 0));
94 :
95 : // BB3 has BB4 as successor.
96 : bb3->successors().push_back(
97 : Successor(Successor::kConditionTrue,
98 : BasicBlockReference(BlockGraph::RELATIVE_REF, 4, bb4),
99 E : 0));
100 :
101 : BasicBlockSubGraph::BlockDescription* d1 = subgraph_.AddBlockDescription(
102 E : "new_block", "new_compiland", BlockGraph::CODE_BLOCK, 0, 1, 0);
103 E : d1->basic_block_order.push_back(bb1);
104 E : d1->basic_block_order.push_back(bb2);
105 E : d1->basic_block_order.push_back(bb3);
106 E : d1->basic_block_order.push_back(bb4);
107 :
108 E : BlockBuilder builder(&block_graph_);
109 E : EXPECT_TRUE(builder.Merge(&subgraph_));
110 E : EXPECT_EQ(1, builder.new_blocks().size());
111 :
112 E : Block* new_block = builder.new_blocks()[0];
113 E : EXPECT_TRUE(new_block != NULL);
114 E : return new_block;
115 E : }
116 : };
117 :
118 : } // namespace
119 :
120 : // A comparison operator for TagInfo objects. Needed for use with ContainerEq.
121 E : bool operator==(const TagInfo& ti1, const TagInfo& ti2) {
122 : return ti1.type == ti2.type && ti1.block == ti2.block &&
123 E : ti1.offset == ti2.offset && ti1.size == ti2.size;
124 E : }
125 :
126 : // This test constructs the following subgraph then merges it into block graph.
127 : // It adds tags to each element and also ensures that the tagging mechanism
128 : // works as expected.
129 : //
130 : // +-------+
131 : // | Data |
132 : // +---+---+
133 : // |
134 : // +--> +---------+
135 : // bb1 0 | 5 bytes | Ref: 4-byte ref to code block @ 1, Label1 (code+call).
136 : // +---------+
137 : // | 2 bytes | Successor: 1-byte ref to bb1 @ 6.
138 : // +---------+
139 : // | 2 bytes | Successor: 1-byte ref to bb3 @ 8.
140 : // +---------+
141 : // bb2 9 | 2 bytes | Label2 (code).
142 : // +---------+
143 : // | 3 bytes |
144 : // +---------+
145 : // bb3 14 | 2 bytes | Label3 (code).
146 : // +---------+
147 : // | 1 byte |
148 : // +---------+ Successor: elided here. Label4.
149 : // bb4 17 | 7 bytes |
150 : // +---------+
151 : // | 9 bytes |
152 : // +---------+
153 : // | 2 bytes | Successor: 1-byte ref to bb2 @ 34.
154 : // +---------+
155 : // | 1 byte | Injected NOP due to data alignment.
156 : // data 36 +---------+ Label5 (data).
157 : // | 4 bytes | Ref: 4-byte ref to bb1 @ 36.
158 : // +---------+
159 : // | 4 bytes | Ref: 4-byte ref to bb2 @ 40.
160 : // +---------+
161 : // | 4 bytes | Ref: 4-byte ref to bb3 @ 44.
162 : // 48 +---------+
163 : //
164 E : TEST_F(BlockBuilderTest, Merge) {
165 : // Setup a code block which is referenced from a data block and references
166 : // another code block.
167 : BlockGraph::Block* original =
168 E : block_graph_.AddBlock(BlockGraph::CODE_BLOCK, 32, "original");
169 E : ASSERT_TRUE(original != NULL);
170 E : BlockGraph::BlockId original_id = original->id();
171 : BlockGraph::Block* other =
172 E : block_graph_.AddBlock(BlockGraph::DATA_BLOCK, 4, "other");
173 E : ASSERT_TRUE(other != NULL);
174 E : BlockGraph::BlockId other_id = other->id();
175 : ASSERT_TRUE(other->SetReference(
176 E : 0, BlockGraph::Reference(BlockGraph::ABSOLUTE_REF, 4, original, 0, 0)));
177 :
178 : // Verify some expectations.
179 E : ASSERT_EQ(2, block_graph_.blocks().size());
180 E : ASSERT_EQ(1, original->referrers().size());
181 :
182 : // Generate a mock decomposition of the original block.
183 E : subgraph_.set_original_block(original);
184 E : BasicCodeBlock* bb1 = subgraph_.AddBasicCodeBlock("bb1");
185 E : ASSERT_TRUE(bb1 != NULL);
186 E : bb1->tags().insert(bb1);
187 E : BasicCodeBlock* bb2 = subgraph_.AddBasicCodeBlock("bb2");
188 E : ASSERT_TRUE(bb2 != NULL);
189 E : bb2->tags().insert(bb2);
190 E : BasicCodeBlock* bb3 = subgraph_.AddBasicCodeBlock("bb3");
191 E : ASSERT_TRUE(bb3 != NULL);
192 E : bb3->tags().insert(bb3);
193 E : BasicCodeBlock* bb4 = subgraph_.AddBasicCodeBlock("bb4");
194 E : ASSERT_TRUE(bb4 != NULL);
195 E : bb4->tags().insert(bb4);
196 E : BasicDataBlock* table = subgraph_.AddBasicDataBlock("table", 12, kEmptyData);
197 E : ASSERT_TRUE(table != NULL);
198 E : table->tags().insert(table);
199 :
200 : // Flesh out bb1 with an instruction having a reference and 2 successors.
201 E : Instruction* inst = AddInstruction(bb1, kCall, sizeof(kCall));
202 E : Label label_1("1", BlockGraph::CODE_LABEL | BlockGraph::CALL_SITE_LABEL);
203 E : inst->set_label(label_1);
204 E : ASSERT_TRUE(inst != NULL);
205 E : BasicBlockReference bb1_abs_ref(BlockGraph::ABSOLUTE_REF, 4, other, 0, 0);
206 E : bb1_abs_ref.tags().insert(&bb1_abs_ref);
207 E : ASSERT_TRUE(inst->references().insert(std::make_pair(1, bb1_abs_ref)).second);
208 E : Instruction* bb1_inst1 = inst;
209 E : bb1_inst1->tags().insert(bb1_inst1);
210 E : BasicBlockReference bb1_succ1_ref(BlockGraph::RELATIVE_REF, 4, bb1);
211 E : bb1_succ1_ref.tags().insert(&bb1_succ1_ref);
212 E : Successor bb1_succ1(Successor::kConditionEqual, bb1_succ1_ref, 0);
213 E : bb1_succ1.tags().insert(&bb1_succ1);
214 E : bb1->successors().push_back(bb1_succ1);
215 : bb1->successors().push_back(
216 : Successor(Successor::kConditionNotEqual,
217 : BasicBlockReference(BlockGraph::RELATIVE_REF, 4, bb3),
218 E : 0));
219 E : ASSERT_TRUE(bb1->referrers().insert(BasicBlockReferrer(other, 0)).second);
220 :
221 : // Flesh out bb2 with some instructions and no successor.
222 E : inst = AddInstruction(bb2, kNop2, sizeof(kNop2));
223 E : Label label_2("2", BlockGraph::CODE_LABEL);
224 E : inst->set_label(label_2);
225 E : ASSERT_TRUE(inst != NULL);
226 E : ASSERT_TRUE(AddInstruction(bb2, kNop3, sizeof(kNop3)) != NULL);
227 :
228 : // Flesh out bb3 with some instructions and a single successor.
229 : // We set tags on the successor and its reference. Since these are elided
230 : // we expect zero-sized entries in the tag info map.
231 E : inst = AddInstruction(bb3, kNop2, sizeof(kNop2));
232 E : Label label_3("3", BlockGraph::CODE_LABEL);
233 E : inst->set_label(label_3);
234 E : ASSERT_TRUE(inst != NULL);
235 E : ASSERT_TRUE(AddInstruction(bb3, kNop1, sizeof(kNop1)) != NULL);
236 E : BasicBlockReference bb3_succ_ref(BlockGraph::RELATIVE_REF, 4, bb4);
237 E : bb3_succ_ref.tags().insert(&bb3_succ_ref);
238 E : Successor bb3_succ(Successor::kConditionTrue, bb3_succ_ref, 0);
239 E : bb3_succ.tags().insert(&bb3_succ);
240 E : bb3->successors().push_back(bb3_succ);
241 E : Label label_4("4", BlockGraph::CODE_LABEL);
242 E : bb3->successors().back().set_label(label_4);
243 :
244 : // Flesh out bb4 with some instructions and a single successor.
245 E : ASSERT_TRUE(AddInstruction(bb4, kNop7, sizeof(kNop7)) != NULL);
246 E : ASSERT_TRUE(AddInstruction(bb4, kNop9, sizeof(kNop9)) != NULL);
247 : bb4->successors().push_back(
248 : Successor(Successor::kConditionTrue,
249 : BasicBlockReference(BlockGraph::RELATIVE_REF, 4, bb2),
250 E : 0));
251 :
252 : // Flesh out table with references. Make the table aligned so that we test
253 : // our NOP insertion code.
254 E : Label label_5("5", BlockGraph::DATA_LABEL | BlockGraph::JUMP_TABLE_LABEL);
255 E : table->set_label(label_5);
256 E : table->set_alignment(4);
257 : ASSERT_TRUE(table->references().insert(std::make_pair(
258 E : 0, BasicBlockReference(BlockGraph::ABSOLUTE_REF, 4, bb1))).second);
259 : ASSERT_TRUE(table->references().insert(std::make_pair(
260 E : 4, BasicBlockReference(BlockGraph::ABSOLUTE_REF, 4, bb2))).second);
261 E : BasicBlockReference table_ref3(BlockGraph::ABSOLUTE_REF, 4, bb3);
262 E : table_ref3.tags().insert(&table_ref3);
263 E : ASSERT_TRUE(table->references().insert(std::make_pair(8, table_ref3)).second);
264 :
265 : BasicBlockSubGraph::BlockDescription* d1 = subgraph_.AddBlockDescription(
266 E : "new_block", "new block compiland", BlockGraph::CODE_BLOCK, 0, 1, 0);
267 E : d1->basic_block_order.push_back(bb1);
268 E : d1->basic_block_order.push_back(bb2);
269 E : d1->basic_block_order.push_back(bb3);
270 E : d1->basic_block_order.push_back(bb4);
271 E : d1->basic_block_order.push_back(table);
272 :
273 E : BlockBuilder builder(&block_graph_);
274 E : ASSERT_TRUE(builder.Merge(&subgraph_));
275 E : EXPECT_EQ(NULL, block_graph_.GetBlockById(original_id));
276 E : EXPECT_EQ(other, block_graph_.GetBlockById(other_id));
277 E : EXPECT_EQ(2, block_graph_.blocks().size());
278 E : ASSERT_EQ(1, builder.new_blocks().size());
279 E : BlockGraph::Block* new_block = builder.new_blocks().front();
280 E : EXPECT_EQ(new_block, block_graph_.GetBlockById(new_block->id()));
281 E : EXPECT_EQ(48U, new_block->size());
282 E : EXPECT_EQ(new_block->data_size(), new_block->size());
283 E : EXPECT_EQ(table->alignment(), new_block->alignment());
284 :
285 : // Validate the tags.
286 E : TagInfoMap expected_tags;
287 E : expected_tags[bb1].push_back(TagInfo(kBasicCodeBlockTag, new_block, 0, 9));
288 E : expected_tags[bb2].push_back(TagInfo(kBasicCodeBlockTag, new_block, 9, 5));
289 E : expected_tags[bb3].push_back(TagInfo(kBasicCodeBlockTag, new_block, 14, 3));
290 E : expected_tags[bb4].push_back(TagInfo(kBasicCodeBlockTag, new_block, 17, 18));
291 : expected_tags[table].push_back(
292 E : TagInfo(kBasicDataBlockTag, new_block, 36, 12));
293 E : expected_tags[bb1_inst1].push_back(TagInfo(kInstructionTag, new_block, 0, 5));
294 : expected_tags[&bb1_abs_ref].push_back(
295 E : TagInfo(kReferenceTag, new_block, 1, 4));
296 : expected_tags[&bb1_succ1_ref].push_back(
297 E : TagInfo(kReferenceTag, new_block, 6, 1));
298 E : expected_tags[&bb1_succ1].push_back(TagInfo(kSuccessorTag, new_block, 5, 2));
299 : expected_tags[&bb3_succ_ref].push_back(
300 E : TagInfo(kReferenceTag, new_block, 17, 0));
301 E : expected_tags[&bb3_succ].push_back(TagInfo(kSuccessorTag, new_block, 17, 0));
302 : expected_tags[&table_ref3].push_back(
303 E : TagInfo(kReferenceTag, new_block, 44, 4));
304 E : EXPECT_THAT(builder.tag_info_map(), ::testing::ContainerEq(expected_tags));
305 :
306 : // Validate the new block's references.
307 E : Block::ReferenceMap expected_references;
308 : expected_references[1] = Reference(
309 E : BlockGraph::ABSOLUTE_REF, 4, other, 0, 0);
310 : expected_references[6] = Reference(
311 E : BlockGraph::PC_RELATIVE_REF, 1, new_block, 0, 0);
312 : expected_references[8] = Reference(
313 E : BlockGraph::PC_RELATIVE_REF, 1, new_block, 14, 14);
314 : expected_references[34] = Reference(
315 E : BlockGraph::PC_RELATIVE_REF, 1, new_block, 9, 9);
316 : expected_references[36] = Reference(
317 E : BlockGraph::ABSOLUTE_REF, 4, new_block, 0, 0);
318 : expected_references[40] = Reference(
319 E : BlockGraph::ABSOLUTE_REF, 4, new_block, 9, 9);
320 : expected_references[44] = Reference(
321 E : BlockGraph::ABSOLUTE_REF, 4, new_block, 14, 14);
322 E : EXPECT_EQ(expected_references, new_block->references());
323 :
324 : // Validate the new block's referrers.
325 E : Block::ReferrerSet expected_referrers;
326 E : expected_referrers.insert(Referrer(other, 0));
327 E : expected_referrers.insert(Referrer(new_block, 6));
328 E : expected_referrers.insert(Referrer(new_block, 8));
329 E : expected_referrers.insert(Referrer(new_block, 34));
330 E : expected_referrers.insert(Referrer(new_block, 36));
331 E : expected_referrers.insert(Referrer(new_block, 40));
332 E : expected_referrers.insert(Referrer(new_block, 44));
333 E : EXPECT_EQ(expected_referrers, new_block->referrers());
334 :
335 : // Validate the references of the other block.
336 E : Block::ReferenceMap expected_other_references;
337 : expected_other_references[0] = Reference(
338 E : BlockGraph::ABSOLUTE_REF, 4, new_block, 0, 0);
339 E : EXPECT_EQ(expected_other_references, other->references());
340 :
341 : // Validate the referrers of the other block.
342 E : Block::ReferrerSet expected_other_referrers;
343 E : expected_other_referrers.insert(Referrer(new_block, 1));
344 E : EXPECT_EQ(expected_other_referrers, other->referrers());
345 :
346 : // Validate the labels.
347 E : BlockGraph::Block::LabelMap expected_labels;
348 E : expected_labels.insert(std::make_pair(0, label_1));
349 E : expected_labels.insert(std::make_pair(9, label_2));
350 E : expected_labels.insert(std::make_pair(14, label_3));
351 E : expected_labels.insert(std::make_pair(17, label_4));
352 E : expected_labels.insert(std::make_pair(36, label_5));
353 E : EXPECT_EQ(expected_labels, new_block->labels());
354 :
355 : // Validate that there is a single byte NOP at position 35, just prior to the
356 : // table.
357 E : EXPECT_EQ(0x90, new_block->data()[35]);
358 E : }
359 :
360 E : TEST_F(BlockBuilderTest, ShortLayout) {
361 : // This is the block structure we construct. If either of BB1 or BB2's
362 : // successors is manifested too long, they will both have to grow.
363 : // 0 [BB1] 62 bytes
364 : // 62 jeq BB4 (+127 bytes).
365 : // 64 [BB2] 62 bytes
366 : // 126 jmp BB1 (-128 bytes).
367 : // 128 [BB3] 63 bytes.
368 : // 191 [BB4] 1 byte.
369 E : Block* new_block = CreateLayout(62, 62, 63, 1);
370 E : ASSERT_TRUE(new_block != NULL);
371 :
372 E : EXPECT_EQ(192, new_block->size());
373 E : Block::ReferenceMap expected_refs;
374 : expected_refs.insert(
375 : std::make_pair(63,
376 : Reference(BlockGraph::PC_RELATIVE_REF,
377 E : 1, new_block, 191, 191)));
378 : expected_refs.insert(
379 : std::make_pair(127,
380 : Reference(BlockGraph::PC_RELATIVE_REF,
381 E : 1, new_block, 0, 0)));
382 E : EXPECT_EQ(expected_refs, new_block->references());
383 E : }
384 :
385 E : TEST_F(BlockBuilderTest, OutofReachBranchLayout) {
386 : // 54 + 72 + 2 = 128 - the BB1->BB4 branch is just out of reach.
387 E : Block* new_block = CreateLayout(62, 54, 72, 1);
388 E : ASSERT_TRUE(new_block != NULL);
389 :
390 : size_t expected_size = 62 +
391 : core::AssemblerImpl::kLongBranchSize +
392 : 54 +
393 : core::AssemblerImpl::kShortJumpSize +
394 : 72 +
395 E : 1;
396 E : EXPECT_EQ(expected_size, new_block->size());
397 E : Block::ReferenceMap expected_refs;
398 : expected_refs.insert(
399 : std::make_pair(62 + core::AssemblerImpl::kLongBranchOpcodeSize,
400 : Reference(BlockGraph::PC_RELATIVE_REF,
401 : 4,
402 : new_block,
403 : expected_size - 1,
404 E : expected_size - 1)));
405 : size_t succ_location = 62 +
406 : core::AssemblerImpl::kLongBranchSize +
407 : 54 +
408 E : core::AssemblerImpl::kShortJumpOpcodeSize;
409 : expected_refs.insert(
410 : std::make_pair(succ_location,
411 : Reference(BlockGraph::PC_RELATIVE_REF,
412 E : 1, new_block, 0, 0)));
413 E : EXPECT_EQ(expected_refs, new_block->references());
414 E : }
415 :
416 E : TEST_F(BlockBuilderTest, OutofReachJmpLayout) {
417 : // 0 - (62 + 2 + 63 + 2) = -129, the jump from BB2->BB1 is just out of reach.
418 E : Block* new_block = CreateLayout(62, 63, 55, 1);
419 E : ASSERT_TRUE(new_block != NULL);
420 :
421 : size_t expected_size = 62 +
422 : core::AssemblerImpl::kShortBranchSize+
423 : 63 +
424 : core::AssemblerImpl::kLongJumpSize+
425 : 55 +
426 E : 1;
427 E : EXPECT_EQ(expected_size, new_block->size());
428 E : Block::ReferenceMap expected_refs;
429 : expected_refs.insert(
430 : std::make_pair(62 + core::AssemblerImpl::kShortBranchOpcodeSize,
431 : Reference(BlockGraph::PC_RELATIVE_REF,
432 : 1,
433 : new_block,
434 : expected_size - 1,
435 E : expected_size - 1)));
436 : size_t succ_location = 62 +
437 : core::AssemblerImpl::kShortBranchSize +
438 : 63 +
439 E : core::AssemblerImpl::kLongJumpOpcodeSize;
440 : expected_refs.insert(
441 : std::make_pair(succ_location,
442 : Reference(BlockGraph::PC_RELATIVE_REF,
443 E : 4, new_block, 0, 0)));
444 E : EXPECT_EQ(expected_refs, new_block->references());
445 E : }
446 :
447 E : TEST_F(BlockBuilderTest, MergeAssemblesSourceRangesCorrectly) {
448 E : ASSERT_NO_FATAL_FAILURE(InitBlockGraph());
449 E : ASSERT_NO_FATAL_FAILURE(InitBasicBlockSubGraph());
450 :
451 : // Test that re-assembling this decomposition produces an unbroken,
452 : // identical source range as the original block had.
453 : BlockGraph::Block::SourceRanges expected_source_ranges(
454 E : assembly_func_->source_ranges());
455 :
456 E : BlockBuilder builder(&block_graph_);
457 E : ASSERT_TRUE(builder.Merge(&subgraph_));
458 :
459 E : ASSERT_EQ(1, builder.new_blocks().size());
460 :
461 E : BlockGraph::Block* new_block = builder.new_blocks()[0];
462 E : ASSERT_EQ(expected_source_ranges, new_block->source_ranges());
463 E : }
464 :
465 E : TEST_F(BlockBuilderTest, LabelsPastEndAreDropped) {
466 E : ASSERT_NO_FATAL_FAILURE(InitBasicBlockSubGraphWithLabelPastEnd());
467 :
468 E : BlockBuilder builder(&block_graph_);
469 E : ASSERT_TRUE(builder.Merge(&subgraph_));
470 :
471 E : ASSERT_EQ(1u, builder.new_blocks().size());
472 :
473 E : BlockGraph::Block* new_block = builder.new_blocks()[0];
474 E : ASSERT_EQ(1u, new_block->labels().size());
475 E : ASSERT_EQ(0, new_block->labels().begin()->first);
476 : ASSERT_EQ(BlockGraph::CODE_LABEL | BlockGraph::DEBUG_START_LABEL,
477 E : new_block->labels().begin()->second.attributes());
478 :
479 : // TODO(chrisha): When we properly handle labels of this type, ensure that
480 : // they make it through the block building process. For now we simply
481 : // ensure that it *doesn't* exist.
482 E : }
483 :
484 : } // namespace block_graph
|