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 : // If the failure is due to unsupported instructions then simply mark the
96 : // block as undecomposable so it won't be processed again.
97 i : if (bb_decomposer.contains_unsupported_instructions()) {
98 i : VLOG(1) << "Block contains unsupported instruction(s): "
99 : << BlockInfo(block);
100 i : block->set_attribute(BlockGraph::UNSUPPORTED_INSTRUCTIONS);
101 i : return true;
102 : }
103 :
104 i : return false;
105 : }
106 :
107 : // Call the transform.
108 E : if (!transform->TransformBasicBlockSubGraph(policy, block_graph, &subgraph))
109 E : return false;
110 :
111 : // Update the block-graph post transform.
112 E : BlockBuilder builder(block_graph);
113 E : if (!builder.Merge(&subgraph))
114 i : return false;
115 :
116 E : if (new_blocks != NULL) {
117 : new_blocks->assign(builder.new_blocks().begin(),
118 E : builder.new_blocks().end());
119 : }
120 :
121 E : return true;
122 E : }
123 :
124 : bool ApplyBasicBlockSubGraphTransforms(
125 : const std::vector<BasicBlockSubGraphTransformInterface*>& transforms,
126 : const TransformPolicyInterface* policy,
127 : BlockGraph* block_graph,
128 : BlockGraph::Block* block,
129 E : BlockVector* new_blocks) {
130 E : DCHECK(policy != NULL);
131 E : DCHECK(block_graph != NULL);
132 E : DCHECK(block != NULL);
133 E : DCHECK_EQ(BlockGraph::CODE_BLOCK, block->type());
134 E : DCHECK(policy->BlockIsSafeToBasicBlockDecompose(block));
135 :
136 : // Decompose block to basic blocks.
137 E : BasicBlockSubGraph subgraph;
138 E : BasicBlockDecomposer bb_decomposer(block, &subgraph);
139 E : if (!bb_decomposer.Decompose())
140 i : return false;
141 :
142 : // Call the transforms.
143 : std::vector<BasicBlockSubGraphTransformInterface*>::const_iterator it =
144 E : transforms.begin();
145 E : for (; it != transforms.end(); ++it) {
146 E : BasicBlockSubGraphTransformInterface* transform = *it;
147 E : DCHECK(transform != NULL);
148 E : if (!transform->TransformBasicBlockSubGraph(policy, block_graph, &subgraph))
149 i : return false;
150 E : }
151 :
152 : // Update the block-graph post transform.
153 E : BlockBuilder builder(block_graph);
154 E : if (!builder.Merge(&subgraph))
155 i : return false;
156 :
157 E : if (new_blocks != NULL) {
158 : new_blocks->assign(builder.new_blocks().begin(),
159 E : builder.new_blocks().end());
160 : }
161 :
162 E : return true;
163 E : }
164 :
165 : } // namespace block_graph
|