Add alignment to basic blocks.
A further CL will plumb this into the block builder.
BUG=
Review URL: https://codereview.appspot.com/6822076
git-svn-id: http://sawbuck.googlecode.com/svn/trunk/syzygy@1218 15e8cca8-e42c-11de-a347-f34a4f72eb7d
diff --git a/block_graph/basic_block.cc b/block_graph/basic_block.cc
index 1b2c7d6..d9319c0 100644
--- a/block_graph/basic_block.cc
+++ b/block_graph/basic_block.cc
@@ -624,6 +624,7 @@
BasicBlock::BasicBlock(const base::StringPiece& name,
BasicBlock::BasicBlockType type)
: name_(name.begin(), name.end()),
+ alignment_(1),
type_(type),
offset_(kNoOffset) {
}
diff --git a/block_graph/basic_block.h b/block_graph/basic_block.h
index 417239b..8ca6e40 100644
--- a/block_graph/basic_block.h
+++ b/block_graph/basic_block.h
@@ -22,6 +22,7 @@
#include "base/string_piece.h"
#include "syzygy/block_graph/block_graph.h"
+#include "syzygy/common/align.h"
#include "syzygy/core/assembler.h"
#include "syzygy/core/disassembler_util.h"
@@ -545,6 +546,13 @@
BasicBlockType type() const { return type_; }
const std::string& name() const { return name_; }
+ size_t alignment() const { return alignment_; }
+ void set_alignment(size_t alignment) {
+ DCHECK_LE(1u, alignment_);
+ DCHECK(common::IsPowerOfTwo(alignment));
+ alignment_ = alignment;
+ }
+
Offset offset() const { return offset_; }
void set_offset(Offset offset) { offset_ = offset; }
@@ -570,6 +578,9 @@
// The name of this basic block.
std::string name_;
+ // The alignment of this basic block.
+ size_t alignment_;
+
// The offset of this basic block in the oritinal block. Set to the offset
// of the first byte the basic block originated from during decomposition.
// Useful as a stable, unique identifier for basic blocks in a decomposition.
diff --git a/block_graph/basic_block_assembly_func.asm b/block_graph/basic_block_assembly_func.asm
index ff097b4..6baa614 100644
--- a/block_graph/basic_block_assembly_func.asm
+++ b/block_graph/basic_block_assembly_func.asm
@@ -1,4 +1,4 @@
-; Copyright 2012 Google Inc.
+; Copyright 2012 Google Inc. All Rights Reserved.
;
; Licensed under the Apache License, Version 2.0 (the "License");
; you may not use this file except in compliance with the License.
@@ -82,6 +82,10 @@
interrupt_label LABEL PROC
int 3
+ ; We add some padding so that jump_table ends up being 4-byte aligned.
+ int 3
+ int 3
+
jump_table \
dd case_0
dd case_1
diff --git a/block_graph/basic_block_decomposer.cc b/block_graph/basic_block_decomposer.cc
index 2dc5e5f..e64ac52 100644
--- a/block_graph/basic_block_decomposer.cc
+++ b/block_graph/basic_block_decomposer.cc
@@ -56,6 +56,8 @@
typedef BBAddressSpace::RangeMapConstIter RangeMapConstIter;
typedef BBAddressSpace::RangeMapIter RangeMapIter;
+const size_t kPointerSize = BlockGraph::Reference::kMaximumSize;
+
// We use a (somewhat) arbitrary value as the disassembly address for a block
// so we can tell the difference between a reference to the beginning of the
// block (offset=0) and a null address.
@@ -172,11 +174,21 @@
desc.attributes = block_->attributes();
desc.section = block_->section();
+ // Add the basic blocks to the block descriptor.
Offset offset = 0;
RangeMapConstIter it = original_address_space_.begin();
for (; it != original_address_space_.end(); ++it) {
DCHECK_EQ(it->first.start(), offset);
desc.basic_block_order.push_back(it->second);
+
+ // Any data basic blocks (jump and case tables) with 0 mod 4 alignment
+ // are marked so that the alignment is preserved by the block builder.
+ if (desc.alignment >= kPointerSize &&
+ it->second->type() == BasicBlock::BASIC_DATA_BLOCK &&
+ (offset % kPointerSize) == 0) {
+ it->second->set_alignment(kPointerSize);
+ }
+
offset += it->first.size();
}
diff --git a/block_graph/basic_block_decomposer_unittest.cc b/block_graph/basic_block_decomposer_unittest.cc
index 5bb81cf..afb363e 100644
--- a/block_graph/basic_block_decomposer_unittest.cc
+++ b/block_graph/basic_block_decomposer_unittest.cc
@@ -143,6 +143,7 @@
std::advance(inst_iter, 1);
ASSERT_EQ(1u, inst_iter->references().size());
ASSERT_EQ(bbs_[8], inst_iter->references().begin()->second.basic_block());
+ ASSERT_EQ(1u, bbs_[0]->alignment());
// Basic-block 1 - unreachable-label.
// TODO(rogerm): This is classified as padding for now, it will become code
@@ -154,6 +155,7 @@
// ASSERT_EQ(1u, bbs_[1]->successors().size());;
// ASSERT_EQ(bbs_[2],
// bbs_[1]->successors().front().reference().basic_block());
+ ASSERT_EQ(1u, bbs_[1]->alignment());
// Basic-block 2 - case_0.
ASSERT_TRUE(BasicBlockSubGraph::IsReachable(rm, bbs_[2]));
@@ -163,6 +165,7 @@
ASSERT_EQ(2u, bb2->instructions().size());
ASSERT_EQ(1u, bb2->successors().size());;
ASSERT_EQ(bbs_[3], bb2->successors().front().reference().basic_block());
+ ASSERT_EQ(1u, bbs_[2]->alignment());
// Basic-block 3 - sub eax to jnz.
ASSERT_TRUE(BasicBlockSubGraph::IsReachable(rm, bbs_[3]));
@@ -173,6 +176,7 @@
ASSERT_EQ(2u, bb3->successors().size());;
ASSERT_EQ(bb3, bb3->successors().front().reference().basic_block());
ASSERT_EQ(bbs_[4], bb3->successors().back().reference().basic_block());
+ ASSERT_EQ(1u, bbs_[3]->alignment());
// Basic-block 4 - ret.
ASSERT_TRUE(BasicBlockSubGraph::IsReachable(rm, bbs_[4]));
@@ -181,6 +185,7 @@
ASSERT_TRUE(bb4 != NULL);
ASSERT_EQ(1u, bb4->instructions().size());
ASSERT_EQ(0u, bb4->successors().size());;
+ ASSERT_EQ(1u, bbs_[4]->alignment());
// Basic-block 5 - case_1.
ASSERT_TRUE(BasicBlockSubGraph::IsReachable(rm, bbs_[5]));
@@ -193,6 +198,7 @@
bb5->instructions().front().references().begin()->second.block());
ASSERT_EQ(1u, bb5->successors().size());
ASSERT_EQ(bbs_[6], bb5->successors().front().reference().basic_block());
+ ASSERT_EQ(1u, bbs_[5]->alignment());
// Basic-block 6 - case_default.
ASSERT_TRUE(BasicBlockSubGraph::IsReachable(rm, bbs_[6]));
@@ -204,14 +210,16 @@
func2_,
bb6->instructions().back().references().begin()->second.block());
ASSERT_EQ(0u, bb6->successors().size());
+ ASSERT_EQ(1u, bbs_[6]->alignment());
// Basic-block 7 - interrupt_label.
ASSERT_FALSE(BasicBlockSubGraph::IsReachable(rm, bbs_[7]));
ASSERT_EQ(BasicBlock::BASIC_CODE_BLOCK, bbs_[7]->type());
BasicCodeBlock* bb7 = BasicCodeBlock::Cast(bbs_[7]);
ASSERT_TRUE(bb7 != NULL);
- ASSERT_EQ(1u, bb7->instructions().size());
+ ASSERT_EQ(3u, bb7->instructions().size());
ASSERT_EQ(0u, bb7->successors().size());
+ ASSERT_EQ(1u, bbs_[7]->alignment());
// Basic-block 8 - jump_table.
ASSERT_TRUE(BasicBlockSubGraph::IsReachable(rm, bbs_[8]));
@@ -220,6 +228,7 @@
ASSERT_TRUE(bb8 != NULL);
ASSERT_EQ(3 * Reference::kMaximumSize, bb8->size());
ASSERT_EQ(3u, bb8->references().size());
+ ASSERT_EQ(4u, bbs_[8]->alignment());
// Basic-block 9 - case_table.
ASSERT_TRUE(BasicBlockSubGraph::IsReachable(rm, bbs_[9]));
@@ -228,6 +237,7 @@
ASSERT_TRUE(bb9 != NULL);
ASSERT_EQ(256, bb9->size());
ASSERT_EQ(0u, bb9->references().size());
+ ASSERT_EQ(4u, bbs_[9]->alignment());
// Validate all source ranges.
core::RelativeAddress next_addr(start_addr_);
diff --git a/block_graph/basic_block_test_util.cc b/block_graph/basic_block_test_util.cc
index c5e012d..12d3eab 100644
--- a/block_graph/basic_block_test_util.cc
+++ b/block_graph/basic_block_test_util.cc
@@ -106,6 +106,10 @@
source_ranges().Push(Block::DataRange(0, kAssemblyFuncSize),
Block::SourceRange(start_addr_, kAssemblyFuncSize));
+ // This block contains aligned case and jump tables, so the decomposer would
+ // give it pointer alignment.
+ assembly_func_->set_alignment(4);
+
// Add the data labels.
ASSERT_TRUE(assembly_func_->SetLabel(
kCaseTableOffset, "case_table", kCaseTableAttributes));
diff --git a/reorder/basic_block_optimizer_unittest.cc b/reorder/basic_block_optimizer_unittest.cc
index 96c94fb..b305c86 100644
--- a/reorder/basic_block_optimizer_unittest.cc
+++ b/reorder/basic_block_optimizer_unittest.cc
@@ -244,8 +244,8 @@
TEST_F(BasicBlockOrdererTest, AddWarmDataReferences) {
// Get basic block pointers to the switch, jump table, and case table.
const BasicCodeBlock* code_bb = BasicCodeBlock::Cast(FindBasicBlockAt(0));
- const BasicDataBlock* jump_table = BasicDataBlock::Cast(FindBasicBlockAt(50));
- const BasicDataBlock* case_table = BasicDataBlock::Cast(FindBasicBlockAt(62));
+ const BasicDataBlock* jump_table = BasicDataBlock::Cast(FindBasicBlockAt(52));
+ const BasicDataBlock* case_table = BasicDataBlock::Cast(FindBasicBlockAt(64));
ASSERT_TRUE(code_bb != NULL);
ASSERT_TRUE(jump_table != NULL);
ASSERT_TRUE(case_table != NULL);
@@ -269,8 +269,8 @@
Order::OffsetVector warm;
Order::OffsetVector cold;
ASSERT_TRUE(orderer_->GetBasicBlockOrderings(&warm, &cold));
- // Note that the bb's at 50 and 62 are the jump and case tables, respectively.
- EXPECT_THAT(warm, testing::ElementsAre(0, 24, 31, 36, 50, 62));
+ // Note that the bb's at 52 and 64 are the jump and case tables, respectively.
+ EXPECT_THAT(warm, testing::ElementsAre(0, 24, 31, 36, 52, 64));
EXPECT_THAT(cold, testing::ElementsAre(23, 37, 42, 49));
}
@@ -298,8 +298,8 @@
Order::OffsetVector warm;
Order::OffsetVector cold;
ASSERT_TRUE(orderer_->GetBasicBlockOrderings(&warm, &cold));
- // Note that the bb's at 50 and 62 are the jump and case tables, respectively.
- EXPECT_THAT(warm, testing::ElementsAre(0, 24, 31, 37, 36, 50, 62));
+ // Note that the bb's at 52 and 64 are the jump and case tables, respectively.
+ EXPECT_THAT(warm, testing::ElementsAre(0, 24, 31, 37, 36, 52, 64));
EXPECT_THAT(cold, testing::ElementsAre(23, 42, 49));
}
diff --git a/reorder/transforms/basic_block_layout_transform_unittest.cc b/reorder/transforms/basic_block_layout_transform_unittest.cc
index 3da44bf..2bf96f8 100644
--- a/reorder/transforms/basic_block_layout_transform_unittest.cc
+++ b/reorder/transforms/basic_block_layout_transform_unittest.cc
@@ -77,8 +77,8 @@
ASSERT_TRUE(Insert(37, 2, 0));
ASSERT_TRUE(Insert(42, 2, 1));
ASSERT_TRUE(Insert(49, 2, 2));
- ASSERT_TRUE(Insert(50, 2, 3));
- ASSERT_TRUE(Insert(62, 2, 4));
+ ASSERT_TRUE(Insert(52, 2, 3));
+ ASSERT_TRUE(Insert(64, 2, 4));
BasicBlockSubGraphLayoutTransform tx(bb_map_);
EXPECT_FALSE(tx.TransformBasicBlockSubGraph(&block_graph_, &subgraph_));
}
@@ -94,8 +94,8 @@
ASSERT_TRUE(Insert(37, 0, 5));
ASSERT_TRUE(Insert(42, 0, 6));
ASSERT_TRUE(Insert(49, 0, 7));
- ASSERT_TRUE(Insert(50, 0, 8));
- ASSERT_TRUE(Insert(62, 0, 10));
+ ASSERT_TRUE(Insert(52, 0, 8));
+ ASSERT_TRUE(Insert(64, 0, 10));
BasicBlockSubGraphLayoutTransform tx(bb_map_);
EXPECT_FALSE(tx.TransformBasicBlockSubGraph(&block_graph_, &subgraph_));
}
@@ -109,8 +109,8 @@
ASSERT_TRUE(Insert(37, 0, 5));
ASSERT_TRUE(Insert(42, 0, 6));
ASSERT_TRUE(Insert(49, 0, 7));
- ASSERT_TRUE(Insert(50, 0, 8));
- ASSERT_TRUE(Insert(62, 0, 9));
+ ASSERT_TRUE(Insert(52, 0, 8));
+ ASSERT_TRUE(Insert(64, 0, 9));
BasicBlockSubGraphLayoutTransform tx(bb_map_);
EXPECT_TRUE(tx.TransformBasicBlockSubGraph(&block_graph_, &subgraph_));
@@ -128,8 +128,8 @@
ASSERT_TRUE(Insert(49, 0, 6));
// Data blocks.
- ASSERT_TRUE(Insert(50, 1, 0));
- ASSERT_TRUE(Insert(62, 1, 1));
+ ASSERT_TRUE(Insert(52, 1, 0));
+ ASSERT_TRUE(Insert(64, 1, 1));
// We explicitly do not specify the BB at offset 23, which consists of
// padding that can be deleted.
@@ -258,8 +258,8 @@
assembly_func_code_bbs.push_back(49);
Order::OffsetVector assembly_func_data_bbs;
- assembly_func_data_bbs.push_back(50);
- assembly_func_data_bbs.push_back(62);
+ assembly_func_data_bbs.push_back(52);
+ assembly_func_data_bbs.push_back(64);
order.sections[0].id = text_section_->id();
order.sections[0].name = text_section_->name();