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 : #include "syzygy/block_graph/transform.h"
16 :
17 : #include "syzygy/block_graph/basic_block_decomposer.h"
18 : #include "syzygy/block_graph/block_builder.h"
19 : #include "syzygy/block_graph/block_util.h"
20 :
21 : namespace block_graph {
22 :
23 : bool ApplyBlockGraphTransform(BlockGraphTransformInterface* transform,
24 : const TransformPolicyInterface* policy,
25 : BlockGraph* block_graph,
26 E : BlockGraph::Block* header_block) {
27 E : DCHECK(transform != NULL);
28 E : DCHECK(transform->name() != NULL);
29 E : DCHECK(policy != NULL);
30 E : DCHECK_GT(strlen(transform->name()), 0u);
31 E : DCHECK(block_graph != NULL);
32 E : DCHECK(header_block != NULL);
33 :
34 : // Get the ID of the header block. As a sanity check we want to ensure
35 : // that it still exists after the transform.
36 E : BlockGraph::BlockId header_block_id = header_block->id();
37 :
38 E : if (!transform->TransformBlockGraph(policy, block_graph, header_block)) {
39 E : LOG(ERROR) << "Transform \"" << transform->name() << "\" failed.";
40 E : return false;
41 : }
42 :
43 : // Ensure that the header block still exists. If it was changed, it needs
44 : // to have been changed in place.
45 E : BlockGraph::Block* block = block_graph->GetBlockById(header_block_id);
46 E : if (block == NULL) {
47 E : LOG(ERROR) << "Header block not found after \"" << transform->name()
48 : << "\" transform.";
49 E : return false;
50 : }
51 E : DCHECK_EQ(header_block, block);
52 :
53 E : return true;
54 E : }
55 :
56 : bool ApplyBlockGraphTransforms(
57 : const std::vector<BlockGraphTransformInterface*>& transforms,
58 : const TransformPolicyInterface* policy,
59 : BlockGraph* block_graph,
60 E : BlockGraph::Block* header_block) {
61 E : DCHECK_NE(reinterpret_cast<TransformPolicyInterface*>(NULL), policy);
62 E : DCHECK_NE(reinterpret_cast<BlockGraph*>(NULL), block_graph);
63 E : DCHECK_NE(reinterpret_cast<BlockGraph::Block*>(NULL), header_block);
64 :
65 : // Apply the transforms sequentially.
66 E : for (size_t i = 0; i < transforms.size(); ++i) {
67 : if (!ApplyBlockGraphTransform(transforms[i],
68 : policy,
69 : block_graph,
70 E : header_block)) {
71 E : return false;
72 : }
73 E : }
74 :
75 E : return true;
76 E : }
77 :
78 : bool ApplyBasicBlockSubGraphTransform(
79 : BasicBlockSubGraphTransformInterface* transform,
80 : const TransformPolicyInterface* policy,
81 : BlockGraph* block_graph,
82 : BlockGraph::Block* block,
83 E : BlockVector* new_blocks) {
84 E : DCHECK(transform != NULL);
85 E : DCHECK(policy != NULL);
86 E : DCHECK(block_graph != NULL);
87 E : DCHECK(block != NULL);
88 E : DCHECK_EQ(BlockGraph::CODE_BLOCK, block->type());
89 E : DCHECK(policy->BlockIsSafeToBasicBlockDecompose(block));
90 :
91 : // Decompose block to basic blocks.
92 E : BasicBlockSubGraph subgraph;
93 E : BasicBlockDecomposer bb_decomposer(block, &subgraph);
94 E : if (!bb_decomposer.Decompose())
95 i : return false;
96 :
97 : // Call the transform.
98 E : if (!transform->TransformBasicBlockSubGraph(policy, block_graph, &subgraph))
99 E : return false;
100 :
101 : // Update the block-graph post transform.
102 E : BlockBuilder builder(block_graph);
103 E : if (!builder.Merge(&subgraph))
104 i : return false;
105 :
106 E : if (new_blocks != NULL) {
107 : new_blocks->assign(builder.new_blocks().begin(),
108 E : builder.new_blocks().end());
109 : }
110 :
111 E : return true;
112 E : }
113 :
114 : bool ApplyBasicBlockSubGraphTransforms(
115 : const std::vector<BasicBlockSubGraphTransformInterface*>& transforms,
116 : const TransformPolicyInterface* policy,
117 : BlockGraph* block_graph,
118 : BlockGraph::Block* block,
119 E : BlockVector* new_blocks) {
120 E : DCHECK(policy != NULL);
121 E : DCHECK(block_graph != NULL);
122 E : DCHECK(block != NULL);
123 E : DCHECK_EQ(BlockGraph::CODE_BLOCK, block->type());
124 E : DCHECK(policy->BlockIsSafeToBasicBlockDecompose(block));
125 :
126 : // Decompose block to basic blocks.
127 E : BasicBlockSubGraph subgraph;
128 E : BasicBlockDecomposer bb_decomposer(block, &subgraph);
129 E : if (!bb_decomposer.Decompose())
130 i : return false;
131 :
132 : // Call the transforms.
133 : std::vector<BasicBlockSubGraphTransformInterface*>::const_iterator it =
134 E : transforms.begin();
135 E : for (; it != transforms.end(); ++it) {
136 E : BasicBlockSubGraphTransformInterface* transform = *it;
137 E : DCHECK(transform != NULL);
138 E : if (!transform->TransformBasicBlockSubGraph(policy, block_graph, &subgraph))
139 i : return false;
140 E : }
141 :
142 : // Update the block-graph post transform.
143 E : BlockBuilder builder(block_graph);
144 E : if (!builder.Merge(&subgraph))
145 i : return false;
146 :
147 E : if (new_blocks != NULL) {
148 : new_blocks->assign(builder.new_blocks().begin(),
149 E : builder.new_blocks().end());
150 : }
151 :
152 E : return true;
153 E : }
154 :
155 : } // namespace block_graph
|