1/*
2 * Copyright (C) 2013-2017 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "FTLOutput.h"
28
29#if ENABLE(FTL_JIT)
30
31#include "B3ArgumentRegValue.h"
32#include "B3AtomicValue.h"
33#include "B3BasicBlockInlines.h"
34#include "B3CCallValue.h"
35#include "B3Const32Value.h"
36#include "B3ConstPtrValue.h"
37#include "B3FenceValue.h"
38#include "B3MathExtras.h"
39#include "B3MemoryValue.h"
40#include "B3SlotBaseValue.h"
41#include "B3StackmapGenerationParams.h"
42#include "B3SwitchValue.h"
43#include "B3UpsilonValue.h"
44#include "B3ValueInlines.h"
45#include "SuperSampler.h"
46
47namespace JSC { namespace FTL {
48
49using namespace B3;
50
51Output::Output(State& state)
52 : m_proc(*state.proc)
53{
54}
55
56Output::~Output()
57{
58}
59
60void Output::initialize(AbstractHeapRepository& heaps)
61{
62 m_heaps = &heaps;
63}
64
65LBasicBlock Output::newBlock()
66{
67 LBasicBlock result = m_proc.addBlock(m_frequency);
68
69 if (!m_nextBlock)
70 m_blockOrder.append(result);
71 else
72 m_blockOrder.insertBefore(m_nextBlock, result);
73
74 return result;
75}
76
77void Output::applyBlockOrder()
78{
79 m_proc.setBlockOrder(m_blockOrder);
80}
81
82LBasicBlock Output::appendTo(LBasicBlock block, LBasicBlock nextBlock)
83{
84 appendTo(block);
85 return insertNewBlocksBefore(nextBlock);
86}
87
88void Output::appendTo(LBasicBlock block)
89{
90 m_block = block;
91}
92
93LValue Output::framePointer()
94{
95 return m_block->appendNew<B3::Value>(m_proc, B3::FramePointer, origin());
96}
97
98SlotBaseValue* Output::lockedStackSlot(size_t bytes)
99{
100 return m_block->appendNew<SlotBaseValue>(m_proc, origin(), m_proc.addStackSlot(bytes));
101}
102
103LValue Output::constBool(bool value)
104{
105 if (value)
106 return booleanTrue;
107 return booleanFalse;
108}
109
110LValue Output::constInt32(int32_t value)
111{
112 return m_block->appendNew<B3::Const32Value>(m_proc, origin(), value);
113}
114
115LValue Output::constInt64(int64_t value)
116{
117 return m_block->appendNew<B3::Const64Value>(m_proc, origin(), value);
118}
119
120LValue Output::constDouble(double value)
121{
122 return m_block->appendNew<B3::ConstDoubleValue>(m_proc, origin(), value);
123}
124
125LValue Output::phi(LType type)
126{
127 return m_block->appendNew<B3::Value>(m_proc, B3::Phi, type, origin());
128}
129
130LValue Output::opaque(LValue value)
131{
132 return m_block->appendNew<Value>(m_proc, Opaque, origin(), value);
133}
134
135LValue Output::add(LValue left, LValue right)
136{
137 if (Value* result = left->addConstant(m_proc, right)) {
138 m_block->append(result);
139 return result;
140 }
141 return m_block->appendNew<B3::Value>(m_proc, B3::Add, origin(), left, right);
142}
143
144LValue Output::sub(LValue left, LValue right)
145{
146 return m_block->appendNew<B3::Value>(m_proc, B3::Sub, origin(), left, right);
147}
148
149LValue Output::mul(LValue left, LValue right)
150{
151 return m_block->appendNew<B3::Value>(m_proc, B3::Mul, origin(), left, right);
152}
153
154LValue Output::div(LValue left, LValue right)
155{
156 return m_block->appendNew<B3::Value>(m_proc, B3::Div, origin(), left, right);
157}
158
159LValue Output::chillDiv(LValue left, LValue right)
160{
161 return m_block->appendNew<B3::Value>(m_proc, chill(B3::Div), origin(), left, right);
162}
163
164LValue Output::mod(LValue left, LValue right)
165{
166 return m_block->appendNew<B3::Value>(m_proc, B3::Mod, origin(), left, right);
167}
168
169LValue Output::chillMod(LValue left, LValue right)
170{
171 return m_block->appendNew<B3::Value>(m_proc, chill(B3::Mod), origin(), left, right);
172}
173
174LValue Output::neg(LValue value)
175{
176 return m_block->appendNew<Value>(m_proc, B3::Neg, origin(), value);
177}
178
179LValue Output::doubleAdd(LValue left, LValue right)
180{
181 return m_block->appendNew<B3::Value>(m_proc, B3::Add, origin(), left, right);
182}
183
184LValue Output::doubleSub(LValue left, LValue right)
185{
186 return m_block->appendNew<B3::Value>(m_proc, B3::Sub, origin(), left, right);
187}
188
189LValue Output::doubleMul(LValue left, LValue right)
190{
191 return m_block->appendNew<B3::Value>(m_proc, B3::Mul, origin(), left, right);
192}
193
194LValue Output::doubleDiv(LValue left, LValue right)
195{
196 return m_block->appendNew<B3::Value>(m_proc, B3::Div, origin(), left, right);
197}
198
199LValue Output::doubleMod(LValue left, LValue right)
200{
201 return m_block->appendNew<B3::Value>(m_proc, B3::Mod, origin(), left, right);
202}
203
204LValue Output::bitAnd(LValue left, LValue right)
205{
206 return m_block->appendNew<B3::Value>(m_proc, B3::BitAnd, origin(), left, right);
207}
208
209LValue Output::bitOr(LValue left, LValue right)
210{
211 return m_block->appendNew<B3::Value>(m_proc, B3::BitOr, origin(), left, right);
212}
213
214LValue Output::bitXor(LValue left, LValue right)
215{
216 return m_block->appendNew<B3::Value>(m_proc, B3::BitXor, origin(), left, right);
217}
218
219LValue Output::shl(LValue left, LValue right)
220{
221 right = castToInt32(right);
222 if (Value* result = left->shlConstant(m_proc, right)) {
223 m_block->append(result);
224 return result;
225 }
226 return m_block->appendNew<B3::Value>(m_proc, B3::Shl, origin(), left, right);
227}
228
229LValue Output::aShr(LValue left, LValue right)
230{
231 right = castToInt32(right);
232 if (Value* result = left->sShrConstant(m_proc, right)) {
233 m_block->append(result);
234 return result;
235 }
236 return m_block->appendNew<B3::Value>(m_proc, B3::SShr, origin(), left, right);
237}
238
239LValue Output::lShr(LValue left, LValue right)
240{
241 right = castToInt32(right);
242 if (Value* result = left->zShrConstant(m_proc, right)) {
243 m_block->append(result);
244 return result;
245 }
246 return m_block->appendNew<B3::Value>(m_proc, B3::ZShr, origin(), left, right);
247}
248
249LValue Output::bitNot(LValue value)
250{
251 return m_block->appendNew<B3::Value>(m_proc, B3::BitXor, origin(),
252 value,
253 m_block->appendIntConstant(m_proc, origin(), value->type(), -1));
254}
255
256LValue Output::logicalNot(LValue value)
257{
258 return m_block->appendNew<B3::Value>(m_proc, B3::Equal, origin(), value, int32Zero);
259}
260
261LValue Output::ctlz32(LValue operand)
262{
263 return m_block->appendNew<B3::Value>(m_proc, B3::Clz, origin(), operand);
264}
265
266LValue Output::doubleAbs(LValue value)
267{
268 return m_block->appendNew<B3::Value>(m_proc, B3::Abs, origin(), value);
269}
270
271LValue Output::doubleCeil(LValue operand)
272{
273 return m_block->appendNew<B3::Value>(m_proc, B3::Ceil, origin(), operand);
274}
275
276LValue Output::doubleFloor(LValue operand)
277{
278 return m_block->appendNew<B3::Value>(m_proc, B3::Floor, origin(), operand);
279}
280
281LValue Output::doubleTrunc(LValue value)
282{
283 if (MacroAssembler::supportsFloatingPointRounding()) {
284 PatchpointValue* result = patchpoint(Double);
285 result->append(value, ValueRep::SomeRegister);
286 result->setGenerator(
287 [] (CCallHelpers& jit, const StackmapGenerationParams& params) {
288 jit.roundTowardZeroDouble(params[1].fpr(), params[0].fpr());
289 });
290 result->effects = Effects::none();
291 return result;
292 }
293 double (*truncDouble)(double) = trunc;
294 return callWithoutSideEffects(Double, truncDouble, value);
295}
296
297LValue Output::doubleUnary(DFG::Arith::UnaryType type, LValue value)
298{
299 double (*unaryFunction)(double) = DFG::arithUnaryFunction(type);
300 return callWithoutSideEffects(B3::Double, unaryFunction, value);
301}
302
303LValue Output::doublePow(LValue xOperand, LValue yOperand)
304{
305 double (*powDouble)(double, double) = pow;
306 return callWithoutSideEffects(B3::Double, powDouble, xOperand, yOperand);
307}
308
309LValue Output::doublePowi(LValue x, LValue y)
310{
311 // FIXME: powDoubleInt32() should be inlined here since Output knows about block layout and
312 // should be involved in any operation that creates blocks.
313 // https://bugs.webkit.org/show_bug.cgi?id=152223
314 auto result = powDoubleInt32(m_proc, m_block, origin(), x, y);
315 m_block = result.first;
316 return result.second;
317}
318
319LValue Output::doubleSqrt(LValue value)
320{
321 return m_block->appendNew<B3::Value>(m_proc, B3::Sqrt, origin(), value);
322}
323
324LValue Output::doubleToInt(LValue value)
325{
326 PatchpointValue* result = patchpoint(Int32);
327 result->append(value, ValueRep::SomeRegister);
328 result->setGenerator(
329 [] (CCallHelpers& jit, const StackmapGenerationParams& params) {
330 jit.truncateDoubleToInt32(params[1].fpr(), params[0].gpr());
331 });
332 result->effects = Effects::none();
333 return result;
334}
335
336LValue Output::doubleToInt64(LValue value)
337{
338 PatchpointValue* result = patchpoint(Int64);
339 result->append(value, ValueRep::SomeRegister);
340 result->setGenerator(
341 [] (CCallHelpers& jit, const StackmapGenerationParams& params) {
342 jit.truncateDoubleToInt64(params[1].fpr(), params[0].gpr());
343 });
344 result->effects = Effects::none();
345 return result;
346}
347
348LValue Output::doubleToUInt(LValue value)
349{
350 PatchpointValue* result = patchpoint(Int32);
351 result->append(value, ValueRep::SomeRegister);
352 result->setGenerator(
353 [] (CCallHelpers& jit, const StackmapGenerationParams& params) {
354 jit.truncateDoubleToUint32(params[1].fpr(), params[0].gpr());
355 });
356 result->effects = Effects::none();
357 return result;
358}
359
360LValue Output::signExt32To64(LValue value)
361{
362 return m_block->appendNew<B3::Value>(m_proc, B3::SExt32, origin(), value);
363}
364
365LValue Output::signExt32ToPtr(LValue value)
366{
367 return signExt32To64(value);
368}
369
370LValue Output::zeroExt(LValue value, LType type)
371{
372 if (value->type() == type)
373 return value;
374 if (value->hasInt32())
375 return m_block->appendIntConstant(m_proc, origin(), Int64, static_cast<uint64_t>(static_cast<uint32_t>(value->asInt32())));
376 return m_block->appendNew<B3::Value>(m_proc, B3::ZExt32, origin(), value);
377}
378
379LValue Output::intToDouble(LValue value)
380{
381 return m_block->appendNew<B3::Value>(m_proc, B3::IToD, origin(), value);
382}
383
384LValue Output::unsignedToDouble(LValue value)
385{
386 return intToDouble(zeroExt(value, Int64));
387}
388
389LValue Output::castToInt32(LValue value)
390{
391 if (value->type() == Int32)
392 return value;
393 if (value->hasInt64())
394 return constInt32(static_cast<int32_t>(value->asInt64()));
395 return m_block->appendNew<B3::Value>(m_proc, B3::Trunc, origin(), value);
396}
397
398LValue Output::doubleToFloat(LValue value)
399{
400 return m_block->appendNew<B3::Value>(m_proc, B3::DoubleToFloat, origin(), value);
401}
402
403LValue Output::floatToDouble(LValue value)
404{
405 return m_block->appendNew<B3::Value>(m_proc, B3::FloatToDouble, origin(), value);
406}
407
408LValue Output::load(TypedPointer pointer, LType type)
409{
410 LValue load = m_block->appendNew<MemoryValue>(m_proc, Load, type, origin(), pointer.value());
411 m_heaps->decorateMemory(pointer.heap(), load);
412 return load;
413}
414
415LValue Output::load8SignExt32(TypedPointer pointer)
416{
417 LValue load = m_block->appendNew<MemoryValue>(m_proc, Load8S, Int32, origin(), pointer.value());
418 m_heaps->decorateMemory(pointer.heap(), load);
419 return load;
420}
421
422LValue Output::load8ZeroExt32(TypedPointer pointer)
423{
424 LValue load = m_block->appendNew<MemoryValue>(m_proc, Load8Z, Int32, origin(), pointer.value());
425 m_heaps->decorateMemory(pointer.heap(), load);
426 return load;
427}
428
429LValue Output::load16SignExt32(TypedPointer pointer)
430{
431 LValue load = m_block->appendNew<MemoryValue>(m_proc, Load16S, Int32, origin(), pointer.value());
432 m_heaps->decorateMemory(pointer.heap(), load);
433 return load;
434}
435
436LValue Output::load16ZeroExt32(TypedPointer pointer)
437{
438 LValue load = m_block->appendNew<MemoryValue>(m_proc, Load16Z, Int32, origin(), pointer.value());
439 m_heaps->decorateMemory(pointer.heap(), load);
440 return load;
441}
442
443LValue Output::store(LValue value, TypedPointer pointer)
444{
445 LValue store = m_block->appendNew<MemoryValue>(m_proc, Store, origin(), value, pointer.value());
446 m_heaps->decorateMemory(pointer.heap(), store);
447 return store;
448}
449
450FenceValue* Output::fence(const AbstractHeap* read, const AbstractHeap* write)
451{
452 FenceValue* result = m_block->appendNew<FenceValue>(m_proc, origin());
453 m_heaps->decorateFenceRead(read, result);
454 m_heaps->decorateFenceWrite(write, result);
455 return result;
456}
457
458LValue Output::store32As8(LValue value, TypedPointer pointer)
459{
460 LValue store = m_block->appendNew<MemoryValue>(m_proc, Store8, origin(), value, pointer.value());
461 m_heaps->decorateMemory(pointer.heap(), store);
462 return store;
463}
464
465LValue Output::store32As16(LValue value, TypedPointer pointer)
466{
467 LValue store = m_block->appendNew<MemoryValue>(m_proc, Store16, origin(), value, pointer.value());
468 m_heaps->decorateMemory(pointer.heap(), store);
469 return store;
470}
471
472LValue Output::baseIndex(LValue base, LValue index, Scale scale, ptrdiff_t offset)
473{
474 LValue accumulatedOffset;
475
476 switch (scale) {
477 case ScaleOne:
478 accumulatedOffset = index;
479 break;
480 case ScaleTwo:
481 accumulatedOffset = shl(index, intPtrOne);
482 break;
483 case ScaleFour:
484 accumulatedOffset = shl(index, intPtrTwo);
485 break;
486 case ScaleEight:
487 case ScalePtr:
488 accumulatedOffset = shl(index, intPtrThree);
489 break;
490 }
491
492 if (offset)
493 accumulatedOffset = add(accumulatedOffset, constIntPtr(offset));
494
495 return add(base, accumulatedOffset);
496}
497
498LValue Output::equal(LValue left, LValue right)
499{
500 TriState result = left->equalConstant(right);
501 if (result != MixedTriState)
502 return constBool(result == TrueTriState);
503 return m_block->appendNew<B3::Value>(m_proc, B3::Equal, origin(), left, right);
504}
505
506LValue Output::notEqual(LValue left, LValue right)
507{
508 TriState result = left->notEqualConstant(right);
509 if (result != MixedTriState)
510 return constBool(result == TrueTriState);
511 return m_block->appendNew<B3::Value>(m_proc, B3::NotEqual, origin(), left, right);
512}
513
514LValue Output::above(LValue left, LValue right)
515{
516 TriState result = left->aboveConstant(right);
517 if (result != MixedTriState)
518 return constBool(result == TrueTriState);
519 return m_block->appendNew<B3::Value>(m_proc, B3::Above, origin(), left, right);
520}
521
522LValue Output::aboveOrEqual(LValue left, LValue right)
523{
524 TriState result = left->aboveEqualConstant(right);
525 if (result != MixedTriState)
526 return constBool(result == TrueTriState);
527 return m_block->appendNew<B3::Value>(m_proc, B3::AboveEqual, origin(), left, right);
528}
529
530LValue Output::below(LValue left, LValue right)
531{
532 TriState result = left->belowConstant(right);
533 if (result != MixedTriState)
534 return constBool(result == TrueTriState);
535 return m_block->appendNew<B3::Value>(m_proc, B3::Below, origin(), left, right);
536}
537
538LValue Output::belowOrEqual(LValue left, LValue right)
539{
540 TriState result = left->belowEqualConstant(right);
541 if (result != MixedTriState)
542 return constBool(result == TrueTriState);
543 return m_block->appendNew<B3::Value>(m_proc, B3::BelowEqual, origin(), left, right);
544}
545
546LValue Output::greaterThan(LValue left, LValue right)
547{
548 TriState result = left->greaterThanConstant(right);
549 if (result != MixedTriState)
550 return constBool(result == TrueTriState);
551 return m_block->appendNew<B3::Value>(m_proc, B3::GreaterThan, origin(), left, right);
552}
553
554LValue Output::greaterThanOrEqual(LValue left, LValue right)
555{
556 TriState result = left->greaterEqualConstant(right);
557 if (result != MixedTriState)
558 return constBool(result == TrueTriState);
559 return m_block->appendNew<B3::Value>(m_proc, B3::GreaterEqual, origin(), left, right);
560}
561
562LValue Output::lessThan(LValue left, LValue right)
563{
564 TriState result = left->lessThanConstant(right);
565 if (result != MixedTriState)
566 return constBool(result == TrueTriState);
567 return m_block->appendNew<B3::Value>(m_proc, B3::LessThan, origin(), left, right);
568}
569
570LValue Output::lessThanOrEqual(LValue left, LValue right)
571{
572 TriState result = left->lessEqualConstant(right);
573 if (result != MixedTriState)
574 return constBool(result == TrueTriState);
575 return m_block->appendNew<B3::Value>(m_proc, B3::LessEqual, origin(), left, right);
576}
577
578LValue Output::doubleEqual(LValue left, LValue right)
579{
580 return m_block->appendNew<B3::Value>(m_proc, B3::Equal, origin(), left, right);
581}
582
583LValue Output::doubleEqualOrUnordered(LValue left, LValue right)
584{
585 return m_block->appendNew<B3::Value>(m_proc, B3::EqualOrUnordered, origin(), left, right);
586}
587
588LValue Output::doubleNotEqualOrUnordered(LValue left, LValue right)
589{
590 return m_block->appendNew<B3::Value>(m_proc, B3::NotEqual, origin(), left, right);
591}
592
593LValue Output::doubleLessThan(LValue left, LValue right)
594{
595 return m_block->appendNew<B3::Value>(m_proc, B3::LessThan, origin(), left, right);
596}
597
598LValue Output::doubleLessThanOrEqual(LValue left, LValue right)
599{
600 return m_block->appendNew<B3::Value>(m_proc, B3::LessEqual, origin(), left, right);
601}
602
603LValue Output::doubleGreaterThan(LValue left, LValue right)
604{
605 return m_block->appendNew<B3::Value>(m_proc, B3::GreaterThan, origin(), left, right);
606}
607
608LValue Output::doubleGreaterThanOrEqual(LValue left, LValue right)
609{
610 return m_block->appendNew<B3::Value>(m_proc, B3::GreaterEqual, origin(), left, right);
611}
612
613LValue Output::doubleNotEqualAndOrdered(LValue left, LValue right)
614{
615 return logicalNot(doubleEqualOrUnordered(left, right));
616}
617
618LValue Output::doubleLessThanOrUnordered(LValue left, LValue right)
619{
620 return logicalNot(doubleGreaterThanOrEqual(left, right));
621}
622
623LValue Output::doubleLessThanOrEqualOrUnordered(LValue left, LValue right)
624{
625 return logicalNot(doubleGreaterThan(left, right));
626}
627
628LValue Output::doubleGreaterThanOrUnordered(LValue left, LValue right)
629{
630 return logicalNot(doubleLessThanOrEqual(left, right));
631}
632
633LValue Output::doubleGreaterThanOrEqualOrUnordered(LValue left, LValue right)
634{
635 return logicalNot(doubleLessThan(left, right));
636}
637
638LValue Output::isZero32(LValue value)
639{
640 return m_block->appendNew<B3::Value>(m_proc, B3::Equal, origin(), value, int32Zero);
641}
642
643LValue Output::notZero32(LValue value)
644{
645 return m_block->appendNew<B3::Value>(m_proc, B3::NotEqual, origin(), value, int32Zero);
646}
647
648LValue Output::isZero64(LValue value)
649{
650 return m_block->appendNew<B3::Value>(m_proc, B3::Equal, origin(), value, int64Zero);
651}
652
653LValue Output::notZero64(LValue value)
654{
655 return m_block->appendNew<B3::Value>(m_proc, B3::NotEqual, origin(), value, int64Zero);
656}
657
658LValue Output::select(LValue value, LValue taken, LValue notTaken)
659{
660 if (value->hasInt32()) {
661 if (value->asInt32())
662 return taken;
663 else
664 return notTaken;
665 }
666 return m_block->appendNew<B3::Value>(m_proc, B3::Select, origin(), value, taken, notTaken);
667}
668
669LValue Output::atomicXchgAdd(LValue operand, TypedPointer pointer, Width width)
670{
671 LValue result = m_block->appendNew<AtomicValue>(m_proc, AtomicXchgAdd, origin(), width, operand, pointer.value(), 0, HeapRange(), HeapRange());
672 m_heaps->decorateMemory(pointer.heap(), result);
673 return result;
674}
675
676LValue Output::atomicXchgAnd(LValue operand, TypedPointer pointer, Width width)
677{
678 LValue result = m_block->appendNew<AtomicValue>(m_proc, AtomicXchgAnd, origin(), width, operand, pointer.value(), 0, HeapRange(), HeapRange());
679 m_heaps->decorateMemory(pointer.heap(), result);
680 return result;
681}
682
683LValue Output::atomicXchgOr(LValue operand, TypedPointer pointer, Width width)
684{
685 LValue result = m_block->appendNew<AtomicValue>(m_proc, AtomicXchgOr, origin(), width, operand, pointer.value(), 0, HeapRange(), HeapRange());
686 m_heaps->decorateMemory(pointer.heap(), result);
687 return result;
688}
689
690LValue Output::atomicXchgSub(LValue operand, TypedPointer pointer, Width width)
691{
692 LValue result = m_block->appendNew<AtomicValue>(m_proc, AtomicXchgSub, origin(), width, operand, pointer.value(), 0, HeapRange(), HeapRange());
693 m_heaps->decorateMemory(pointer.heap(), result);
694 return result;
695}
696
697LValue Output::atomicXchgXor(LValue operand, TypedPointer pointer, Width width)
698{
699 LValue result = m_block->appendNew<AtomicValue>(m_proc, AtomicXchgXor, origin(), width, operand, pointer.value(), 0, HeapRange(), HeapRange());
700 m_heaps->decorateMemory(pointer.heap(), result);
701 return result;
702}
703
704LValue Output::atomicXchg(LValue operand, TypedPointer pointer, Width width)
705{
706 LValue result = m_block->appendNew<AtomicValue>(m_proc, AtomicXchg, origin(), width, operand, pointer.value(), 0, HeapRange(), HeapRange());
707 m_heaps->decorateMemory(pointer.heap(), result);
708 return result;
709}
710
711LValue Output::atomicStrongCAS(LValue expected, LValue newValue, TypedPointer pointer, Width width)
712{
713 LValue result = m_block->appendNew<AtomicValue>(m_proc, AtomicStrongCAS, origin(), width, expected, newValue, pointer.value(), 0, HeapRange(), HeapRange());
714 m_heaps->decorateMemory(pointer.heap(), result);
715 return result;
716}
717
718void Output::jump(LBasicBlock destination)
719{
720 m_block->appendNewControlValue(m_proc, B3::Jump, origin(), B3::FrequentedBlock(destination));
721}
722
723void Output::branch(LValue condition, LBasicBlock taken, Weight takenWeight, LBasicBlock notTaken, Weight notTakenWeight)
724{
725 m_block->appendNewControlValue(
726 m_proc, B3::Branch, origin(), condition,
727 FrequentedBlock(taken, takenWeight.frequencyClass()),
728 FrequentedBlock(notTaken, notTakenWeight.frequencyClass()));
729}
730
731void Output::check(LValue condition, WeightedTarget taken, Weight notTakenWeight)
732{
733 LBasicBlock continuation = newBlock();
734 branch(condition, taken, WeightedTarget(continuation, notTakenWeight));
735 appendTo(continuation);
736}
737
738void Output::check(LValue condition, WeightedTarget taken)
739{
740 check(condition, taken, taken.weight().inverse());
741}
742
743void Output::ret(LValue value)
744{
745 m_block->appendNewControlValue(m_proc, B3::Return, origin(), value);
746}
747
748void Output::unreachable()
749{
750 m_block->appendNewControlValue(m_proc, B3::Oops, origin());
751}
752
753void Output::appendSuccessor(WeightedTarget target)
754{
755 m_block->appendSuccessor(target.frequentedBlock());
756}
757
758CheckValue* Output::speculate(LValue value)
759{
760 return m_block->appendNew<B3::CheckValue>(m_proc, B3::Check, origin(), value);
761}
762
763CheckValue* Output::speculateAdd(LValue left, LValue right)
764{
765 return m_block->appendNew<B3::CheckValue>(m_proc, B3::CheckAdd, origin(), left, right);
766}
767
768CheckValue* Output::speculateSub(LValue left, LValue right)
769{
770 return m_block->appendNew<B3::CheckValue>(m_proc, B3::CheckSub, origin(), left, right);
771}
772
773CheckValue* Output::speculateMul(LValue left, LValue right)
774{
775 return m_block->appendNew<B3::CheckValue>(m_proc, B3::CheckMul, origin(), left, right);
776}
777
778PatchpointValue* Output::patchpoint(LType type)
779{
780 return m_block->appendNew<B3::PatchpointValue>(m_proc, type, origin());
781}
782
783void Output::trap()
784{
785 m_block->appendNewControlValue(m_proc, B3::Oops, origin());
786}
787
788ValueFromBlock Output::anchor(LValue value)
789{
790 B3::UpsilonValue* upsilon = m_block->appendNew<B3::UpsilonValue>(m_proc, origin(), value);
791 return ValueFromBlock(upsilon, m_block);
792}
793
794LValue Output::bitCast(LValue value, LType type)
795{
796 ASSERT_UNUSED(type, type == Int64 || type == Double);
797 return m_block->appendNew<B3::Value>(m_proc, B3::BitwiseCast, origin(), value);
798}
799
800LValue Output::fround(LValue doubleValue)
801{
802 return floatToDouble(doubleToFloat(doubleValue));
803}
804
805LValue Output::load(TypedPointer pointer, LoadType type)
806{
807 switch (type) {
808 case Load8SignExt32:
809 return load8SignExt32(pointer);
810 case Load8ZeroExt32:
811 return load8ZeroExt32(pointer);
812 case Load16SignExt32:
813 return load8SignExt32(pointer);
814 case Load16ZeroExt32:
815 return load8ZeroExt32(pointer);
816 case Load32:
817 return load32(pointer);
818 case Load64:
819 return load64(pointer);
820 case LoadPtr:
821 return loadPtr(pointer);
822 case LoadFloat:
823 return loadFloat(pointer);
824 case LoadDouble:
825 return loadDouble(pointer);
826 }
827 RELEASE_ASSERT_NOT_REACHED();
828 return nullptr;
829}
830
831LValue Output::store(LValue value, TypedPointer pointer, StoreType type)
832{
833 switch (type) {
834 case Store32As8:
835 return store32As8(value, pointer);
836 case Store32As16:
837 return store32As16(value, pointer);
838 case Store32:
839 return store32(value, pointer);
840 case Store64:
841 return store64(value, pointer);
842 case StorePtr:
843 return storePtr(value, pointer);
844 case StoreFloat:
845 return storeFloat(value, pointer);
846 case StoreDouble:
847 return storeDouble(value, pointer);
848 }
849 RELEASE_ASSERT_NOT_REACHED();
850 return nullptr;
851}
852
853TypedPointer Output::absolute(const void* address)
854{
855 return TypedPointer(m_heaps->absolute[address], constIntPtr(address));
856}
857
858void Output::incrementSuperSamplerCount()
859{
860 TypedPointer counter = absolute(bitwise_cast<void*>(&g_superSamplerCount));
861 store32(add(load32(counter), int32One), counter);
862}
863
864void Output::decrementSuperSamplerCount()
865{
866 TypedPointer counter = absolute(bitwise_cast<void*>(&g_superSamplerCount));
867 store32(sub(load32(counter), int32One), counter);
868}
869
870void Output::addIncomingToPhi(LValue phi, ValueFromBlock value)
871{
872 if (value)
873 value.value()->as<B3::UpsilonValue>()->setPhi(phi);
874}
875
876void Output::entrySwitch(const Vector<LBasicBlock>& cases)
877{
878 RELEASE_ASSERT(cases.size() == m_proc.numEntrypoints());
879 m_block->appendNew<Value>(m_proc, EntrySwitch, origin());
880 for (LBasicBlock block : cases)
881 m_block->appendSuccessor(FrequentedBlock(block));
882}
883
884} } // namespace JSC::FTL
885
886#endif // ENABLE(FTL_JIT)
887
888