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/basic_block_assembler.h"
16 :
17 : namespace block_graph {
18 :
19 : namespace {
20 :
21 : typedef core::DisplacementImpl DisplacementImpl;
22 : typedef core::OperandImpl OperandImpl;
23 : typedef core::ValueImpl ValueImpl;
24 : typedef core::ValueSize ValueSize;
25 :
26 E : ValueSize ValueSizeFromConstant(uint32 input_value) {
27 : // IA32 assembly may/will sign-extend 8-bit literals, so we attempt to encode
28 : // in 8 bits only those literals whose value will be unchanged by that
29 : // treatment.
30 E : input_value |= 0x7F;
31 :
32 E : if (input_value == 0xFFFFFFFF || input_value == 0x7F)
33 E : return core::kSize8Bit;
34 :
35 E : return core::kSize32Bit;
36 E : }
37 :
38 : ValueImpl CopyValue(const UntypedReference* ref,
39 E : const core::ValueImpl& value) {
40 : return ValueImpl(value.value(),
41 : value.size(),
42 E : value.reference() ? ref : NULL);
43 E : }
44 :
45 E : size_t ToBytes(core::ValueSize size) {
46 E : switch (size) {
47 E : case core::kSize8Bit: return 1;
48 E : case core::kSize32Bit: return 4;
49 : }
50 i : NOTREACHED();
51 i : return 0;
52 E : }
53 :
54 : // Completes a UntypedReference, converting it to a BasicBlockReference
55 : // using the provided type and size information.
56 : // @param ref_info The type and size information to use.
57 : // @param untyped_ref The untyped reference to be completed.
58 : // @returns the equivalent BasicBlockReference.
59 : BasicBlockReference CompleteUntypedReference(
60 : BlockGraph::ReferenceType type,
61 : size_t size,
62 E : const UntypedReference& untyped_ref) {
63 E : DCHECK(untyped_ref.IsValid());
64 :
65 : if (untyped_ref.referred_type() ==
66 E : BasicBlockReference::REFERRED_TYPE_BLOCK) {
67 E : DCHECK(untyped_ref.block() != NULL);
68 : return BasicBlockReference(type, size, untyped_ref.block(),
69 E : untyped_ref.offset(), untyped_ref.base());
70 : }
71 :
72 : DCHECK_EQ(BasicBlockReference::REFERRED_TYPE_BASIC_BLOCK,
73 E : untyped_ref.referred_type());
74 E : DCHECK(untyped_ref.basic_block() != NULL);
75 E : return BasicBlockReference(type, size, untyped_ref.basic_block());
76 E : }
77 :
78 : } // namespace
79 :
80 E : Value::Value() {
81 E : }
82 :
83 E : Value::Value(uint32 value) : value_(value, ValueSizeFromConstant(value)) {
84 E : }
85 :
86 E : Value::Value(uint32 value, ValueSize size) : value_(value, size) {
87 E : }
88 :
89 : Value::Value(BasicBlock* bb)
90 : : reference_(bb),
91 E : value_(0, core::kSize32Bit, &reference_) {
92 E : }
93 :
94 : Value::Value(Block* block, Offset offset)
95 : : reference_(block, offset, offset),
96 E : value_(0, core::kSize32Bit, &reference_) {
97 E : }
98 :
99 : Value::Value(Block* block, Offset offset, Offset base)
100 : : reference_(block, offset, base),
101 E : value_(0, core::kSize32Bit, &reference_) {
102 E : }
103 :
104 : Value::Value(uint32 value, ValueSize size, const UntypedReference& ref)
105 E : : reference_(ref), value_(value, size, &reference_) {
106 E : DCHECK(ref.IsValid());
107 E : }
108 :
109 : Value::Value(const Value& other)
110 : : reference_(other.reference()),
111 E : value_(CopyValue(&reference_, other.value_)) {
112 E : }
113 :
114 : Value::Value(const UntypedReference& ref, const ValueImpl& value)
115 E : : reference_(ref), value_(CopyValue(&reference_, value)) {
116 E : }
117 :
118 E : Value::~Value() {
119 : #ifndef NDEBUG
120 E : if (reference_.IsValid()) {
121 E : DCHECK(value_.reference() == &reference_);
122 E : } else {
123 E : DCHECK(value_.reference() == NULL);
124 : }
125 : #endif
126 E : }
127 :
128 E : const Value& Value::operator=(const Value& other) {
129 E : reference_ = other.reference_;
130 E : value_ = CopyValue(&reference_, other.value_);
131 E : return *this;
132 E : }
133 :
134 E : bool Value::operator==(const Value& rhs) const {
135 E : if (reference_.IsValid())
136 i : return reference_ == rhs.reference();
137 E : return value_ == rhs.value_;
138 E : }
139 :
140 E : Operand::Operand(const core::Register32& base) : operand_(base) {
141 E : }
142 :
143 : Operand::Operand(const core::Register32& base, const Displacement& displ)
144 : : reference_(displ.reference()),
145 E : operand_(base, CopyValue(&reference_, displ.value_)) {
146 E : }
147 :
148 : Operand::Operand(const Displacement& displ)
149 : : reference_(displ.reference()),
150 E : operand_(CopyValue(&reference_, displ.value_)) {
151 E : }
152 :
153 : Operand::Operand(const core::Register32& base,
154 : const core::Register32& index,
155 : core::ScaleFactor scale,
156 : const Displacement& displ)
157 : : reference_(displ.reference_),
158 E : operand_(base, index, scale, CopyValue(&reference_, displ.value_)) {
159 E : }
160 :
161 : Operand::Operand(const core::Register32& base,
162 : const core::Register32& index,
163 : core::ScaleFactor scale)
164 E : : operand_(base, index, scale) {
165 E : }
166 :
167 : Operand::Operand(const core::Register32& index,
168 : core::ScaleFactor scale,
169 : const Displacement& displ)
170 : : reference_(displ.reference_),
171 E : operand_(index, scale, CopyValue(&reference_, displ.value_)) {
172 E : }
173 :
174 : Operand::Operand(const Operand& o)
175 : : reference_(o.reference_),
176 : operand_(o.base(), o.index(), o.scale(),
177 E : CopyValue(&reference_, o.operand_.displacement())) {
178 E : }
179 :
180 E : Operand::~Operand() {
181 : #ifndef NDEBUG
182 E : if (reference_.IsValid()) {
183 E : DCHECK(operand_.displacement().reference() == &reference_);
184 E : } else {
185 E : DCHECK(operand_.displacement().reference() == NULL);
186 : }
187 : #endif
188 E : }
189 :
190 E : const Operand& Operand::operator=(const Operand& other) {
191 E : reference_ = other.reference_;
192 : operand_ =
193 : core::OperandImpl(other.base(), other.index(), other.scale(),
194 E : CopyValue(&reference_, other.operand_.displacement()));
195 E : return *this;
196 E : }
197 :
198 : BasicBlockAssembler::BasicBlockSerializer::BasicBlockSerializer(
199 : const Instructions::iterator& where, Instructions* list)
200 E : : where_(where), list_(list), num_ref_infos_(0) {
201 E : DCHECK(list != NULL);
202 E : }
203 :
204 : void BasicBlockAssembler::BasicBlockSerializer::AppendInstruction(
205 : uint32 location, const uint8* bytes, size_t num_bytes,
206 E : const size_t *ref_locations, const void* const* refs, size_t num_refs) {
207 : // The number of reference infos we've been provided must match the number of
208 : // references we have been given.
209 E : DCHECK_EQ(num_ref_infos_, num_refs);
210 :
211 E : Instruction instruction;
212 E : CHECK(Instruction::FromBuffer(bytes, num_bytes, &instruction));
213 E : instruction.set_source_range(source_range_);
214 :
215 E : Instructions::iterator it = list_->insert(where_, instruction);
216 :
217 E : for (size_t i = 0; i < num_refs; ++i) {
218 : const UntypedReference* tref =
219 E : reinterpret_cast<const UntypedReference*>(refs[i]);
220 E : DCHECK(tref != NULL);
221 :
222 : BasicBlockReference bbref = CompleteUntypedReference(
223 E : ref_infos_[i].type, ref_infos_[i].size, *tref);
224 E : DCHECK(bbref.IsValid());
225 E : it->SetReference(ref_locations[i], bbref);
226 E : }
227 :
228 : // Clear the reference info for the next instruction.
229 E : num_ref_infos_ = 0;
230 E : }
231 :
232 : void BasicBlockAssembler::BasicBlockSerializer::PushReferenceInfo(
233 E : BlockGraph::ReferenceType type, core::ValueSize size) {
234 E : DCHECK_GT(2u, num_ref_infos_);
235 E : ref_infos_[num_ref_infos_].type = type;
236 E : ref_infos_[num_ref_infos_].size = ToBytes(size);
237 E : ++num_ref_infos_;
238 E : }
239 :
240 : BasicBlockAssembler::BasicBlockAssembler(const Instructions::iterator& where,
241 : Instructions* list)
242 E : : serializer_(where, list), asm_(0, &serializer_) {
243 E : }
244 :
245 : BasicBlockAssembler::BasicBlockAssembler(uint32 location,
246 : const Instructions::iterator& where,
247 : Instructions* list)
248 E : : serializer_(where, list), asm_(location, &serializer_) {
249 E : }
250 :
251 E : void BasicBlockAssembler::nop(size_t size) {
252 E : asm_.nop(size);
253 E : }
254 :
255 E : void BasicBlockAssembler::call(const Immediate& dst) {
256 : // In the context of BasicBlockAssembler it only makes sense for calls with
257 : // immediate parameters to be backed by a 32-bit reference.
258 E : PushMandatoryReferenceInfo(BlockGraph::PC_RELATIVE_REF, dst);
259 E : CheckReferenceSize(core::kSize32Bit, dst);
260 E : asm_.call(dst.value_);
261 E : }
262 :
263 E : void BasicBlockAssembler::call(const Operand& dst) {
264 : // If a call is backed by a reference it must be 32-bit.
265 E : PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, dst);
266 E : CheckReferenceSize(core::kSize32Bit, dst);
267 E : asm_.call(dst.operand_);
268 E : }
269 :
270 E : void BasicBlockAssembler::jmp(const Immediate& dst) {
271 : // In the context of BasicBlockAssembler it only makes sense for jumps with
272 : // immediate parameters to be backed by a reference.
273 E : PushMandatoryReferenceInfo(BlockGraph::PC_RELATIVE_REF, dst);
274 E : asm_.jmp(dst.value_);
275 E : }
276 :
277 E : void BasicBlockAssembler::jmp(const Operand& dst) {
278 E : PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, dst);
279 E : asm_.jmp(dst.operand_);
280 E : }
281 :
282 E : void BasicBlockAssembler::j(ConditionCode code, const Immediate& dst) {
283 : // In the context of BasicBlockAssembler it only makes sense for jumps with
284 : // immediate parameters to be backed by a reference.
285 E : PushMandatoryReferenceInfo(BlockGraph::PC_RELATIVE_REF, dst);
286 E : asm_.j(code, dst.value_);
287 E : }
288 :
289 E : void BasicBlockAssembler::set(ConditionCode code, const Register32& dst) {
290 E : asm_.set(code, dst);
291 E : }
292 :
293 E : void BasicBlockAssembler::pushfd() {
294 E : asm_.pushfd();
295 E : }
296 :
297 E : void BasicBlockAssembler::popfd() {
298 E : asm_.popfd();
299 E : }
300 :
301 E : void BasicBlockAssembler::lahf() {
302 E : asm_.lahf();
303 E : }
304 :
305 E : void BasicBlockAssembler::sahf() {
306 E : asm_.sahf();
307 E : }
308 :
309 E : void BasicBlockAssembler::test(const Register8& dst, const Register8& src) {
310 E : asm_.test(dst, src);
311 E : }
312 :
313 E : void BasicBlockAssembler::test(const Register8& dst, const Immediate& src) {
314 E : PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
315 E : asm_.test(dst, src.value_);
316 E : }
317 :
318 E : void BasicBlockAssembler::test(const Register32& dst, const Register32& src) {
319 E : asm_.test(dst, src);
320 E : }
321 :
322 : void BasicBlockAssembler::test(const Register32& dst, const Operand& src) {
323 : PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
324 : asm_.test(dst, src.operand_);
325 : }
326 :
327 : void BasicBlockAssembler::test(const Operand& dst, const Register32& src) {
328 : PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, dst);
329 : asm_.test(dst.operand_, src);
330 : }
331 :
332 E : void BasicBlockAssembler::test(const Register32& dst, const Immediate& src) {
333 E : PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
334 E : asm_.test(dst, src.value_);
335 E : }
336 :
337 E : void BasicBlockAssembler::test(const Operand& dst, const Immediate& src) {
338 E : PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, dst);
339 E : PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
340 E : asm_.test(dst.operand_, src.value_);
341 E : }
342 :
343 E : void BasicBlockAssembler::cmp(const Register8& dst, const Register8& src) {
344 E : asm_.cmp(dst, src);
345 E : }
346 :
347 E : void BasicBlockAssembler::cmp(const Register8& dst, const Immediate& src) {
348 E : PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
349 E : asm_.cmp(dst, src.value_);
350 E : }
351 :
352 E : void BasicBlockAssembler::cmp(const Register32& dst, const Register32& src) {
353 E : asm_.cmp(dst, src);
354 E : }
355 :
356 : void BasicBlockAssembler::cmp(const Register32& dst, const Operand& src) {
357 : PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
358 : asm_.cmp(dst, src.operand_);
359 : }
360 :
361 : void BasicBlockAssembler::cmp(const Operand& dst, const Register32& src) {
362 : PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, dst);
363 : asm_.cmp(dst.operand_, src);
364 : }
365 :
366 E : void BasicBlockAssembler::cmp(const Register32& dst, const Immediate& src) {
367 E : PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
368 E : asm_.cmp(dst, src.value_);
369 E : }
370 :
371 E : void BasicBlockAssembler::cmp(const Operand& dst, const Immediate& src) {
372 E : PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, dst);
373 E : PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
374 E : asm_.cmp(dst.operand_, src.value_);
375 E : }
376 :
377 E : void BasicBlockAssembler::add(const Register8& dst, const Register8& src) {
378 E : asm_.add(dst, src);
379 E : }
380 :
381 E : void BasicBlockAssembler::add(const Register8& dst, const Immediate& src) {
382 E : PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
383 E : asm_.add(dst, src.value_);
384 E : }
385 :
386 E : void BasicBlockAssembler::add(const Register32& dst, const Register32& src) {
387 E : asm_.add(dst, src);
388 E : }
389 :
390 : void BasicBlockAssembler::add(const Register32& dst, const Operand& src) {
391 : PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
392 : asm_.add(dst, src.operand_);
393 : }
394 :
395 : void BasicBlockAssembler::add(const Operand& dst, const Register32& src) {
396 : PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, dst);
397 : asm_.add(dst.operand_, src);
398 : }
399 :
400 E : void BasicBlockAssembler::add(const Register32& dst, const Immediate& src) {
401 E : PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
402 E : asm_.add(dst, src.value_);
403 E : }
404 :
405 E : void BasicBlockAssembler::add(const Operand& dst, const Immediate& src) {
406 E : PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, dst);
407 E : PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
408 E : asm_.add(dst.operand_, src.value_);
409 E : }
410 :
411 E : void BasicBlockAssembler::sub(const Register8& dst, const Register8& src) {
412 E : asm_.sub(dst, src);
413 E : }
414 :
415 E : void BasicBlockAssembler::sub(const Register8& dst, const Immediate& src) {
416 E : PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
417 E : asm_.sub(dst, src.value_);
418 E : }
419 :
420 E : void BasicBlockAssembler::sub(const Register32& dst, const Register32& src) {
421 E : asm_.sub(dst, src);
422 E : }
423 :
424 : void BasicBlockAssembler::sub(const Register32& dst, const Operand& src) {
425 : PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
426 : asm_.sub(dst, src.operand_);
427 : }
428 :
429 : void BasicBlockAssembler::sub(const Operand& dst, const Register32& src) {
430 : PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, dst);
431 : asm_.sub(dst.operand_, src);
432 : }
433 :
434 E : void BasicBlockAssembler::sub(const Register32& dst, const Immediate& src) {
435 E : PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
436 E : asm_.sub(dst, src.value_);
437 E : }
438 :
439 E : void BasicBlockAssembler::sub(const Operand& dst, const Immediate& src) {
440 E : PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, dst);
441 E : PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
442 E : asm_.sub(dst.operand_, src.value_);
443 E : }
444 :
445 E : void BasicBlockAssembler::shl(const Register32& dst, const Immediate& src) {
446 E : PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
447 E : asm_.shl(dst, src.value_);
448 E : }
449 :
450 E : void BasicBlockAssembler::shr(const Register32& dst, const Immediate& src) {
451 E : PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
452 E : asm_.shr(dst, src.value_);
453 E : }
454 :
455 E : void BasicBlockAssembler::mov_b(const Operand& dst, const Immediate& src) {
456 E : PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, dst);
457 E : PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
458 E : CheckReferenceSize(core::kSize32Bit, dst);
459 E : CheckReferenceSize(core::kSize32Bit, src);
460 E : asm_.mov_b(dst.operand_, src.value_);
461 E : }
462 :
463 E : void BasicBlockAssembler::movzx_b(const Register32& dst, const Operand& src) {
464 E : PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
465 E : CheckReferenceSize(core::kSize32Bit, src);
466 E : asm_.movzx_b(dst, src.operand_);
467 E : }
468 :
469 E : void BasicBlockAssembler::mov(const Register32& dst, const Register32& src) {
470 E : asm_.mov(dst, src);
471 E : }
472 :
473 E : void BasicBlockAssembler::mov(const Register32& dst, const Operand& src) {
474 E : PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
475 E : CheckReferenceSize(core::kSize32Bit, src);
476 E : asm_.mov(dst, src.operand_);
477 E : }
478 :
479 E : void BasicBlockAssembler::mov(const Operand& dst, const Register32& src) {
480 E : PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, dst);
481 E : CheckReferenceSize(core::kSize32Bit, dst);
482 E : asm_.mov(dst.operand_, src);
483 E : }
484 :
485 E : void BasicBlockAssembler::mov(const Register32& dst, const Immediate& src) {
486 E : PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
487 E : CheckReferenceSize(core::kSize32Bit, src);
488 E : asm_.mov(dst, src.value_);
489 E : }
490 :
491 E : void BasicBlockAssembler::mov(const Operand& dst, const Immediate& src) {
492 E : PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, dst);
493 E : PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
494 E : CheckReferenceSize(core::kSize32Bit, dst);
495 E : CheckReferenceSize(core::kSize32Bit, src);
496 E : asm_.mov(dst.operand_, src.value_);
497 E : }
498 :
499 E : void BasicBlockAssembler::mov_fs(const Register32& dst, const Operand& src) {
500 E : PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
501 E : CheckReferenceSize(core::kSize32Bit, src);
502 E : asm_.mov_fs(dst, src.operand_);
503 E : }
504 :
505 E : void BasicBlockAssembler::mov_fs(const Operand& dst, const Register32& src) {
506 E : PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, dst);
507 E : CheckReferenceSize(core::kSize32Bit, dst);
508 E : asm_.mov_fs(dst.operand_, src);
509 E : }
510 :
511 E : void BasicBlockAssembler::lea(const Register32& dst, const Operand& src) {
512 E : PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
513 E : CheckReferenceSize(core::kSize32Bit, src);
514 E : asm_.lea(dst, src.operand_);
515 E : }
516 :
517 E : void BasicBlockAssembler::push(const Register32& src) {
518 E : asm_.push(src);
519 E : }
520 :
521 E : void BasicBlockAssembler::push(const Immediate& src) {
522 E : PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
523 E : CheckReferenceSize(core::kSize32Bit, src);
524 E : asm_.push(src.value_);
525 E : }
526 :
527 E : void BasicBlockAssembler::push(const Operand& src) {
528 E : PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, src);
529 E : CheckReferenceSize(core::kSize32Bit, src);
530 E : asm_.push(src.operand_);
531 E : }
532 :
533 E : void BasicBlockAssembler::pop(const Register32& dst) {
534 E : asm_.pop(dst);
535 E : }
536 :
537 E : void BasicBlockAssembler::pop(const Operand& dst) {
538 E : PushOptionalReferenceInfo(BlockGraph::ABSOLUTE_REF, dst);
539 E : CheckReferenceSize(core::kSize32Bit, dst);
540 E : asm_.pop(dst.operand_);
541 E : }
542 :
543 E : void BasicBlockAssembler::ret() {
544 E : asm_.ret();
545 E : }
546 :
547 E : void BasicBlockAssembler::ret(uint16 n) {
548 E : asm_.ret(n);
549 E : }
550 :
551 E : void BasicBlockAssembler::xchg(const Register32& dst, const Register32& src) {
552 E : asm_.xchg(dst, src);
553 E : }
554 :
555 E : void BasicBlockAssembler::xchg(const Register16& dst, const Register16& src) {
556 E : asm_.xchg(dst, src);
557 E : }
558 :
559 E : void BasicBlockAssembler::xchg(const Register8& dst, const Register8& src) {
560 E : asm_.xchg(dst, src);
561 E : }
562 :
563 : void BasicBlockAssembler::PushMandatoryReferenceInfo(
564 E : ReferenceType type, const Immediate& imm) {
565 E : DCHECK(imm.value_.reference() != NULL);
566 E : serializer_.PushReferenceInfo(type, imm.value_.size());
567 E : }
568 :
569 : void BasicBlockAssembler::PushOptionalReferenceInfo(
570 E : ReferenceType type, const Immediate& imm) {
571 E : if (imm.value_.reference() == NULL)
572 E : return;
573 E : serializer_.PushReferenceInfo(type, imm.value_.size());
574 E : }
575 :
576 : void BasicBlockAssembler::PushOptionalReferenceInfo(
577 E : ReferenceType type, const Operand& op) {
578 E : if (op.operand_.displacement().reference() == NULL)
579 E : return;
580 E : serializer_.PushReferenceInfo(type, op.operand_.displacement().size());
581 E : }
582 :
583 : void BasicBlockAssembler::CheckReferenceSize(
584 E : core::ValueSize size, const Immediate& imm) const {
585 E : DCHECK(imm.value_.reference() == NULL || imm.value_.size() == size);
586 E : }
587 :
588 : void BasicBlockAssembler::CheckReferenceSize(
589 E : core::ValueSize size, const Operand& op) const {
590 : DCHECK(op.operand_.displacement().reference() == NULL ||
591 E : op.operand_.displacement().size() == size);
592 E : }
593 :
594 : } // namespace block_graph
|