1 : // Copyright 2012 Google Inc.
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 : // Provides an assembler that assembles to basic block instruction lists.
16 :
17 : #ifndef SYZYGY_BLOCK_GRAPH_BASIC_BLOCK_ASSEMBLER_H_
18 : #define SYZYGY_BLOCK_GRAPH_BASIC_BLOCK_ASSEMBLER_H_
19 :
20 : #include "syzygy/block_graph/basic_block.h"
21 : #include "syzygy/core/assembler.h"
22 :
23 : namespace block_graph {
24 :
25 : class BasicBlockAssembler;
26 : class Operand;
27 :
28 : class Value {
29 : public:
30 : Value();
31 : // Constructs an 8- or 32-bit value, depending on the minimum number of bits
32 : // required to represent the Value. If the value can be encoded using 8-bits
33 : // to have the same representation under sign extension, then an 8-bit Value
34 : // will be created; otherwise, a 32-bit absolute Value will be created.
35 : explicit Value(uint32 value);
36 : // Constructs an absolute value having a specific bit width.
37 : Value(uint32 value, core::ValueSize size);
38 : // Constructs a 32 bit absolute value referring to the basic block @p bb.
39 : explicit Value(BasicBlock* bb);
40 : // Constructs a 32 bit absolute value referring to @p block at @p offset.
41 : Value(BlockGraph::Block* block, BlockGraph::Offset offset);
42 : // Copy construction.
43 : Value(const Value& other);
44 :
45 : // Destructor.
46 : ~Value();
47 :
48 : // Assignment operator.
49 : const Value& operator=(const Value& other);
50 :
51 : // @name Accessors.
52 : // @{
53 E : uint32 value() const { return value_.value(); }
54 E : core::ValueSize size() const { return value_.size(); }
55 E : const BasicBlockReference &reference() const { return reference_; }
56 : // @}
57 :
58 : private:
59 : // Private constructor for Operand.
60 : Value(const BasicBlockReference& ref, const core::ValueImpl& value);
61 :
62 : friend class BasicBlockAssembler;
63 : friend class Operand;
64 :
65 : BasicBlockReference reference_;
66 : core::ValueImpl value_;
67 : };
68 :
69 : // Displacements and immediates behave near-identically, but are semantically
70 : // slightly different.
71 : typedef Value Immediate;
72 : typedef Value Displacement;
73 :
74 : // An operand implies indirection to memory through one of the myriad
75 : // modes supported by IA32.
76 : class Operand {
77 : public:
78 : // A register-indirect mode.
79 : explicit Operand(core::Register base);
80 :
81 : // A register-indirect with displacement mode.
82 : Operand(core::Register base, const Displacement& displ);
83 :
84 : // A displacement-only mode.
85 : explicit Operand(const Displacement& displ);
86 :
87 : // The full [base + index * scale + displ32] mode.
88 : // @note esp cannot be used as an index register.
89 : Operand(core::Register base,
90 : core::Register index,
91 : core::ScaleFactor scale,
92 : const Displacement& displ);
93 :
94 : // The full [base + index * scale] mode.
95 : // @note esp cannot be used as an index register.
96 : Operand(core::Register base,
97 : core::Register index,
98 : core::ScaleFactor scale);
99 :
100 : // The [index * scale + displ32] mode.
101 : // @note esp cannot be used as an index register.
102 : Operand(core::Register index,
103 : core::ScaleFactor scale,
104 : const Displacement& displ);
105 :
106 : // Copy constructor.
107 : Operand(const Operand& o);
108 :
109 : // Destructor.
110 : ~Operand();
111 :
112 : // Assignment operator.
113 : const Operand& operator=(const Operand& other);
114 :
115 : // @name Accessors.
116 : // @{
117 E : core::RegisterCode base() const { return operand_.base(); }
118 E : core::RegisterCode index() const { return operand_.index(); }
119 E : core::ScaleFactor scale() const { return operand_.scale(); }
120 E : Displacement displacement() const {
121 E : return Displacement(reference_, operand_.displacement());
122 E : }
123 : // @}
124 :
125 : private:
126 : friend class BasicBlockAssembler;
127 :
128 : BasicBlockReference reference_;
129 : core::OperandImpl operand_;
130 : };
131 :
132 : class BasicBlockAssembler {
133 : public:
134 : typedef BasicBlock::Instructions Instructions;
135 : typedef core::Register Register;
136 :
137 : // Constructs a basic block assembler that inserts new instructions
138 : // into @p *list at @p where.
139 : BasicBlockAssembler(const Instructions::iterator& where,
140 : Instructions *list);
141 :
142 : // @name Call instructions.
143 : // @{
144 : void call(const Immediate& dst);
145 : void call(const Operand& dst);
146 : // @}
147 :
148 : // @name Jmp instructions.
149 : // @{
150 : void jmp(const Immediate& dst);
151 : void jmp(const Operand& dst);
152 : // @}
153 :
154 : // @name Byte mov varieties.
155 : // @{
156 : void mov_b(const Operand& dst, const Immediate& src);
157 : // @}
158 :
159 : // @name Double-word mov varieties.
160 : // @{
161 : void mov(Register dst, Register src);
162 : void mov(Register dst, const Operand& src);
163 : void mov(const Operand& dst, Register src);
164 : void mov(Register dst, const Immediate& src);
165 : void mov(const Operand& dst, const Immediate& src);
166 : // @}
167 :
168 : // @name load effective address.
169 : void lea(Register dst, const Operand& src);
170 :
171 : // @name stack manipulation.
172 : // @{
173 : void push(Register src);
174 : void push(const Immediate& src);
175 : void push(const Operand& src);
176 :
177 : void pop(Register src);
178 : void pop(const Operand& src);
179 : // @}
180 :
181 : private:
182 : class BasicBlockSerializer
183 : : public core::AssemblerImpl::InstructionSerializer {
184 : public:
185 : BasicBlockSerializer(const Instructions::iterator& where,
186 : Instructions* list);
187 :
188 : virtual void AppendInstruction(uint32 location,
189 : const uint8* bytes,
190 : size_t num_bytes,
191 : const size_t *ref_locations,
192 : const void* const* refs,
193 : size_t num_refs) OVERRIDE;
194 :
195 : private:
196 : Instructions::iterator where_;
197 : Instructions* list_;
198 : };
199 :
200 : BasicBlockSerializer serializer_;
201 : core::AssemblerImpl asm_;
202 : };
203 :
204 : } // namespace block_graph
205 :
206 : #endif // SYZYGY_BLOCK_GRAPH_BASIC_BLOCK_ASSEMBLER_H_
|