2 * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
31 #include "DFGCommon.h"
32 #include "FTLAbbreviations.h"
33 #include "FTLAbstractHeapRepository.h"
34 #include "FTLCommonValues.h"
35 #include "FTLIntrinsicRepository.h"
37 #include "FTLSwitchCase.h"
38 #include "FTLTypedPointer.h"
39 #include "FTLWeight.h"
40 #include "FTLWeightedTarget.h"
41 #include <wtf/StringPrintStream.h>
43 namespace JSC
{ namespace FTL
{
45 // Idiomatic LLVM IR builder specifically designed for FTL. This uses our own lowering
46 // terminology, and has some of its own notions:
48 // We say that a "reference" is what LLVM considers to be a "pointer". That is, it has
49 // an element type and can be passed directly to memory access instructions. Note that
50 // broadly speaking the users of FTL::Output should only use references for alloca'd
51 // slots for mutable local variables.
53 // We say that a "pointer" is what LLVM considers to be a pointer-width integer.
55 // We say that a "typed pointer" is a pointer that carries TBAA meta-data (i.e. an
56 // AbstractHeap). These should usually not have further computation performed on them
57 // prior to access, though there are exceptions (like offsetting into the payload of
58 // a typed pointer to a JSValue).
60 // We say that "get" and "set" are what LLVM considers to be "load" and "store". Get
61 // and set take references.
63 // We say that "load" and "store" are operations that take a typed pointer. These
64 // operations translate the pointer into a reference (or, a pointer in LLVM-speak),
65 // emit get or set on the reference (or, load and store in LLVM-speak), and apply the
66 // TBAA meta-data to the get or set.
68 enum Scale
{ ScaleOne
, ScaleTwo
, ScaleFour
, ScaleEight
, ScalePtr
};
70 class Output
: public IntrinsicRepository
{
75 void initialize(LModule
, LValue
, AbstractHeapRepository
&);
77 LBasicBlock
insertNewBlocksBefore(LBasicBlock nextBlock
)
79 LBasicBlock lastNextBlock
= m_nextBlock
;
80 m_nextBlock
= nextBlock
;
84 LBasicBlock
appendTo(LBasicBlock
, LBasicBlock nextBlock
);
86 void appendTo(LBasicBlock
);
88 LBasicBlock
newBlock(const char* name
= "");
90 LValue
param(unsigned index
) { return getParam(m_function
, index
); }
91 LValue
constBool(bool value
) { return constInt(boolean
, value
); }
92 LValue
constInt8(int8_t value
) { return constInt(int8
, value
); }
93 LValue
constInt32(int32_t value
) { return constInt(int32
, value
); }
95 LValue
constIntPtr(T
* value
) { return constInt(intPtr
, bitwise_cast
<intptr_t>(value
)); }
97 LValue
constIntPtr(T value
) { return constInt(intPtr
, static_cast<intptr_t>(value
)); }
98 LValue
constInt64(int64_t value
) { return constInt(int64
, value
); }
99 LValue
constDouble(double value
) { return constReal(doubleType
, value
); }
101 LValue
phi(LType type
) { return buildPhi(m_builder
, type
); }
102 template<typename
... Params
>
103 LValue
phi(LType type
, ValueFromBlock value
, Params
... theRest
)
105 LValue result
= phi(type
, theRest
...);
106 addIncoming(result
, value
);
109 template<typename VectorType
>
110 LValue
phi(LType type
, const VectorType
& vector
)
112 LValue result
= phi(type
);
113 for (unsigned i
= 0; i
< vector
.size(); ++i
)
114 addIncoming(result
, vector
[i
]);
118 LValue
add(LValue left
, LValue right
) { return buildAdd(m_builder
, left
, right
); }
119 LValue
sub(LValue left
, LValue right
) { return buildSub(m_builder
, left
, right
); }
120 LValue
mul(LValue left
, LValue right
) { return buildMul(m_builder
, left
, right
); }
121 LValue
div(LValue left
, LValue right
) { return buildDiv(m_builder
, left
, right
); }
122 LValue
rem(LValue left
, LValue right
) { return buildRem(m_builder
, left
, right
); }
123 LValue
neg(LValue value
) { return buildNeg(m_builder
, value
); }
125 LValue
doubleAdd(LValue left
, LValue right
) { return buildFAdd(m_builder
, left
, right
); }
126 LValue
doubleSub(LValue left
, LValue right
) { return buildFSub(m_builder
, left
, right
); }
127 LValue
doubleMul(LValue left
, LValue right
) { return buildFMul(m_builder
, left
, right
); }
128 LValue
doubleDiv(LValue left
, LValue right
) { return buildFDiv(m_builder
, left
, right
); }
129 LValue
doubleRem(LValue left
, LValue right
) { return buildFRem(m_builder
, left
, right
); }
130 LValue
doubleNeg(LValue value
) { return buildFNeg(m_builder
, value
); }
132 LValue
bitAnd(LValue left
, LValue right
) { return buildAnd(m_builder
, left
, right
); }
133 LValue
bitOr(LValue left
, LValue right
) { return buildOr(m_builder
, left
, right
); }
134 LValue
bitXor(LValue left
, LValue right
) { return buildXor(m_builder
, left
, right
); }
135 LValue
shl(LValue left
, LValue right
) { return buildShl(m_builder
, left
, right
); }
136 LValue
aShr(LValue left
, LValue right
) { return buildAShr(m_builder
, left
, right
); } // arithmetic = signed
137 LValue
lShr(LValue left
, LValue right
) { return buildLShr(m_builder
, left
, right
); } // logical = unsigned
138 LValue
bitNot(LValue value
) { return buildNot(m_builder
, value
); }
140 LValue
insertElement(LValue vector
, LValue element
, LValue index
) { return buildInsertElement(m_builder
, vector
, element
, index
); }
142 LValue
ceil64(LValue operand
)
144 return call(ceil64Intrinsic(), operand
);
146 LValue
ctlz32(LValue xOperand
, LValue yOperand
)
148 return call(ctlz32Intrinsic(), xOperand
, yOperand
);
150 LValue
addWithOverflow32(LValue left
, LValue right
)
152 return call(addWithOverflow32Intrinsic(), left
, right
);
154 LValue
subWithOverflow32(LValue left
, LValue right
)
156 return call(subWithOverflow32Intrinsic(), left
, right
);
158 LValue
mulWithOverflow32(LValue left
, LValue right
)
160 return call(mulWithOverflow32Intrinsic(), left
, right
);
162 LValue
addWithOverflow64(LValue left
, LValue right
)
164 return call(addWithOverflow64Intrinsic(), left
, right
);
166 LValue
subWithOverflow64(LValue left
, LValue right
)
168 return call(subWithOverflow64Intrinsic(), left
, right
);
170 LValue
mulWithOverflow64(LValue left
, LValue right
)
172 return call(mulWithOverflow64Intrinsic(), left
, right
);
174 LValue
doubleAbs(LValue value
)
176 return call(doubleAbsIntrinsic(), value
);
179 LValue
doubleSin(LValue value
)
181 return call(doubleSinIntrinsic(), value
);
183 LValue
doubleCos(LValue value
)
185 return call(doubleCosIntrinsic(), value
);
188 LValue
doublePow(LValue xOperand
, LValue yOperand
)
190 return call(doublePowIntrinsic(), xOperand
, yOperand
);
193 LValue
doublePowi(LValue xOperand
, LValue yOperand
)
195 return call(doublePowiIntrinsic(), xOperand
, yOperand
);
198 LValue
doubleSqrt(LValue value
)
200 return call(doubleSqrtIntrinsic(), value
);
203 LValue
doubleLog(LValue value
)
205 return call(doubleLogIntrinsic(), value
);
208 static bool hasSensibleDoubleToInt() { return isX86(); }
209 LValue
sensibleDoubleToInt(LValue
);
211 LValue
signExt(LValue value
, LType type
) { return buildSExt(m_builder
, value
, type
); }
212 LValue
zeroExt(LValue value
, LType type
) { return buildZExt(m_builder
, value
, type
); }
213 LValue
zeroExtPtr(LValue value
) { return zeroExt(value
, intPtr
); }
214 LValue
fpToInt(LValue value
, LType type
) { return buildFPToSI(m_builder
, value
, type
); }
215 LValue
fpToUInt(LValue value
, LType type
) { return buildFPToUI(m_builder
, value
, type
); }
216 LValue
fpToInt32(LValue value
) { return fpToInt(value
, int32
); }
217 LValue
fpToUInt32(LValue value
) { return fpToUInt(value
, int32
); }
218 LValue
intToFP(LValue value
, LType type
) { return buildSIToFP(m_builder
, value
, type
); }
219 LValue
intToDouble(LValue value
) { return intToFP(value
, doubleType
); }
220 LValue
unsignedToFP(LValue value
, LType type
) { return buildUIToFP(m_builder
, value
, type
); }
221 LValue
unsignedToDouble(LValue value
) { return unsignedToFP(value
, doubleType
); }
222 LValue
intCast(LValue value
, LType type
) { return buildIntCast(m_builder
, value
, type
); }
223 LValue
castToInt32(LValue value
) { return intCast(value
, int32
); }
224 LValue
fpCast(LValue value
, LType type
) { return buildFPCast(m_builder
, value
, type
); }
225 LValue
intToPtr(LValue value
, LType type
) { return buildIntToPtr(m_builder
, value
, type
); }
226 LValue
ptrToInt(LValue value
, LType type
) { return buildPtrToInt(m_builder
, value
, type
); }
227 LValue
bitCast(LValue value
, LType type
) { return buildBitCast(m_builder
, value
, type
); }
229 // Hilariously, the #define machinery in the stdlib means that this method is actually called
230 // __builtin_alloca. So far this appears benign. :-|
231 LValue
alloca(LType type
) { return buildAlloca(m_builder
, type
); }
233 // Access the value of an alloca. Also used as a low-level implementation primitive for
234 // load(). Never use this to load from "pointers" in the FTL sense, since FTL pointers
235 // are actually integers. This requires an LLVM pointer. Broadly speaking, you don't
236 // have any LLVM pointers even if you really think you do. A TypedPointer is not an
237 // LLVM pointer. See comment block at top of this file to understand the distinction
238 // between LLVM pointers, FTL pointers, and FTL references.
239 LValue
get(LValue reference
) { return buildLoad(m_builder
, reference
); }
240 // Similar to get() but for storing to the value in an alloca.
241 LValue
set(LValue value
, LValue reference
) { return buildStore(m_builder
, value
, reference
); }
243 LValue
load(TypedPointer
, LType refType
);
244 void store(LValue
, TypedPointer
, LType refType
);
246 LValue
load8(TypedPointer pointer
) { return load(pointer
, ref8
); }
247 LValue
load16(TypedPointer pointer
) { return load(pointer
, ref16
); }
248 LValue
load32(TypedPointer pointer
) { return load(pointer
, ref32
); }
249 LValue
load64(TypedPointer pointer
) { return load(pointer
, ref64
); }
250 LValue
loadPtr(TypedPointer pointer
) { return load(pointer
, refPtr
); }
251 LValue
loadFloat(TypedPointer pointer
) { return load(pointer
, refFloat
); }
252 LValue
loadDouble(TypedPointer pointer
) { return load(pointer
, refDouble
); }
253 void store8(LValue value
, TypedPointer pointer
) { store(value
, pointer
, ref8
); }
254 void store16(LValue value
, TypedPointer pointer
) { store(value
, pointer
, ref16
); }
255 void store32(LValue value
, TypedPointer pointer
) { store(value
, pointer
, ref32
); }
256 void store64(LValue value
, TypedPointer pointer
) { store(value
, pointer
, ref64
); }
257 void storePtr(LValue value
, TypedPointer pointer
) { store(value
, pointer
, refPtr
); }
258 void storeFloat(LValue value
, TypedPointer pointer
) { store(value
, pointer
, refFloat
); }
259 void storeDouble(LValue value
, TypedPointer pointer
) { store(value
, pointer
, refDouble
); }
261 LValue
addPtr(LValue value
, ptrdiff_t immediate
= 0)
265 return add(value
, constIntPtr(immediate
));
268 // Construct an address by offsetting base by the requested amount and ascribing
269 // the requested abstract heap to it.
270 TypedPointer
address(const AbstractHeap
& heap
, LValue base
, ptrdiff_t offset
= 0)
272 return TypedPointer(heap
, addPtr(base
, offset
));
274 // Construct an address by offsetting base by the amount specified by the field,
275 // and optionally an additional amount (use this with care), and then creating
276 // a TypedPointer with the given field as the heap.
277 TypedPointer
address(LValue base
, const AbstractField
& field
, ptrdiff_t offset
= 0)
279 return address(field
, base
, offset
+ field
.offset());
282 LValue
baseIndex(LValue base
, LValue index
, Scale
, ptrdiff_t offset
= 0);
284 TypedPointer
baseIndex(const AbstractHeap
& heap
, LValue base
, LValue index
, Scale scale
, ptrdiff_t offset
= 0)
286 return TypedPointer(heap
, baseIndex(base
, index
, scale
, offset
));
288 TypedPointer
baseIndex(IndexedAbstractHeap
& heap
, LValue base
, LValue index
, JSValue indexAsConstant
= JSValue(), ptrdiff_t offset
= 0)
290 return heap
.baseIndex(*this, base
, index
, indexAsConstant
, offset
);
293 TypedPointer
absolute(void* address
)
295 return TypedPointer(m_heaps
->absolute
[address
], constIntPtr(address
));
298 LValue
load8(LValue base
, const AbstractField
& field
) { return load8(address(base
, field
)); }
299 LValue
load16(LValue base
, const AbstractField
& field
) { return load16(address(base
, field
)); }
300 LValue
load32(LValue base
, const AbstractField
& field
) { return load32(address(base
, field
)); }
301 LValue
load64(LValue base
, const AbstractField
& field
) { return load64(address(base
, field
)); }
302 LValue
loadPtr(LValue base
, const AbstractField
& field
) { return loadPtr(address(base
, field
)); }
303 LValue
loadDouble(LValue base
, const AbstractField
& field
) { return loadDouble(address(base
, field
)); }
304 void store8(LValue value
, LValue base
, const AbstractField
& field
) { store8(value
, address(base
, field
)); }
305 void store32(LValue value
, LValue base
, const AbstractField
& field
) { store32(value
, address(base
, field
)); }
306 void store64(LValue value
, LValue base
, const AbstractField
& field
) { store64(value
, address(base
, field
)); }
307 void storePtr(LValue value
, LValue base
, const AbstractField
& field
) { storePtr(value
, address(base
, field
)); }
308 void storeDouble(LValue value
, LValue base
, const AbstractField
& field
) { storeDouble(value
, address(base
, field
)); }
310 void ascribeRange(LValue loadInstruction
, const ValueRange
& range
)
312 range
.decorateInstruction(m_context
, loadInstruction
, rangeKind
);
315 LValue
nonNegative32(LValue loadInstruction
)
317 ascribeRange(loadInstruction
, nonNegativeInt32
);
318 return loadInstruction
;
321 LValue
load32NonNegative(TypedPointer pointer
) { return nonNegative32(load32(pointer
)); }
322 LValue
load32NonNegative(LValue base
, const AbstractField
& field
) { return nonNegative32(load32(base
, field
)); }
324 LValue
icmp(LIntPredicate cond
, LValue left
, LValue right
) { return buildICmp(m_builder
, cond
, left
, right
); }
325 LValue
equal(LValue left
, LValue right
) { return icmp(LLVMIntEQ
, left
, right
); }
326 LValue
notEqual(LValue left
, LValue right
) { return icmp(LLVMIntNE
, left
, right
); }
327 LValue
above(LValue left
, LValue right
) { return icmp(LLVMIntUGT
, left
, right
); }
328 LValue
aboveOrEqual(LValue left
, LValue right
) { return icmp(LLVMIntUGE
, left
, right
); }
329 LValue
below(LValue left
, LValue right
) { return icmp(LLVMIntULT
, left
, right
); }
330 LValue
belowOrEqual(LValue left
, LValue right
) { return icmp(LLVMIntULE
, left
, right
); }
331 LValue
greaterThan(LValue left
, LValue right
) { return icmp(LLVMIntSGT
, left
, right
); }
332 LValue
greaterThanOrEqual(LValue left
, LValue right
) { return icmp(LLVMIntSGE
, left
, right
); }
333 LValue
lessThan(LValue left
, LValue right
) { return icmp(LLVMIntSLT
, left
, right
); }
334 LValue
lessThanOrEqual(LValue left
, LValue right
) { return icmp(LLVMIntSLE
, left
, right
); }
336 LValue
fcmp(LRealPredicate cond
, LValue left
, LValue right
) { return buildFCmp(m_builder
, cond
, left
, right
); }
337 LValue
doubleEqual(LValue left
, LValue right
) { return fcmp(LLVMRealOEQ
, left
, right
); }
338 LValue
doubleNotEqualOrUnordered(LValue left
, LValue right
) { return fcmp(LLVMRealUNE
, left
, right
); }
339 LValue
doubleLessThan(LValue left
, LValue right
) { return fcmp(LLVMRealOLT
, left
, right
); }
340 LValue
doubleLessThanOrEqual(LValue left
, LValue right
) { return fcmp(LLVMRealOLE
, left
, right
); }
341 LValue
doubleGreaterThan(LValue left
, LValue right
) { return fcmp(LLVMRealOGT
, left
, right
); }
342 LValue
doubleGreaterThanOrEqual(LValue left
, LValue right
) { return fcmp(LLVMRealOGE
, left
, right
); }
343 LValue
doubleEqualOrUnordered(LValue left
, LValue right
) { return fcmp(LLVMRealUEQ
, left
, right
); }
344 LValue
doubleNotEqual(LValue left
, LValue right
) { return fcmp(LLVMRealONE
, left
, right
); }
345 LValue
doubleLessThanOrUnordered(LValue left
, LValue right
) { return fcmp(LLVMRealULT
, left
, right
); }
346 LValue
doubleLessThanOrEqualOrUnordered(LValue left
, LValue right
) { return fcmp(LLVMRealULE
, left
, right
); }
347 LValue
doubleGreaterThanOrUnordered(LValue left
, LValue right
) { return fcmp(LLVMRealUGT
, left
, right
); }
348 LValue
doubleGreaterThanOrEqualOrUnordered(LValue left
, LValue right
) { return fcmp(LLVMRealUGE
, left
, right
); }
350 LValue
isZero8(LValue value
) { return equal(value
, int8Zero
); }
351 LValue
notZero8(LValue value
) { return notEqual(value
, int8Zero
); }
352 LValue
isZero32(LValue value
) { return equal(value
, int32Zero
); }
353 LValue
notZero32(LValue value
) { return notEqual(value
, int32Zero
); }
354 LValue
isZero64(LValue value
) { return equal(value
, int64Zero
); }
355 LValue
notZero64(LValue value
) { return notEqual(value
, int64Zero
); }
356 LValue
isNull(LValue value
) { return equal(value
, intPtrZero
); }
357 LValue
notNull(LValue value
) { return notEqual(value
, intPtrZero
); }
359 LValue
testIsZero8(LValue value
, LValue mask
) { return isZero8(bitAnd(value
, mask
)); }
360 LValue
testNonZero8(LValue value
, LValue mask
) { return notZero8(bitAnd(value
, mask
)); }
361 LValue
testIsZero32(LValue value
, LValue mask
) { return isZero32(bitAnd(value
, mask
)); }
362 LValue
testNonZero32(LValue value
, LValue mask
) { return notZero32(bitAnd(value
, mask
)); }
363 LValue
testIsZero64(LValue value
, LValue mask
) { return isZero64(bitAnd(value
, mask
)); }
364 LValue
testNonZero64(LValue value
, LValue mask
) { return notZero64(bitAnd(value
, mask
)); }
366 LValue
select(LValue value
, LValue taken
, LValue notTaken
) { return buildSelect(m_builder
, value
, taken
, notTaken
); }
367 LValue
extractValue(LValue aggVal
, unsigned index
) { return buildExtractValue(m_builder
, aggVal
, index
); }
369 LValue
fence(LAtomicOrdering ordering
= LLVMAtomicOrderingSequentiallyConsistent
, SynchronizationScope scope
= CrossThread
) { return buildFence(m_builder
, ordering
, scope
); }
370 LValue
fenceAcqRel() { return fence(LLVMAtomicOrderingAcquireRelease
); }
372 template<typename VectorType
>
373 LValue
call(LValue function
, const VectorType
& vector
) { return buildCall(m_builder
, function
, vector
); }
374 LValue
call(LValue function
) { return buildCall(m_builder
, function
); }
375 LValue
call(LValue function
, LValue arg1
) { return buildCall(m_builder
, function
, arg1
); }
376 template<typename
... Args
>
377 LValue
call(LValue function
, LValue arg1
, Args
... args
) { return buildCall(m_builder
, function
, arg1
, args
...); }
379 template<typename FunctionType
>
380 LValue
operation(FunctionType function
)
382 return intToPtr(constIntPtr(function
), pointerType(operationType(function
)));
385 void jump(LBasicBlock destination
) { buildBr(m_builder
, destination
); }
386 void branch(LValue condition
, LBasicBlock taken
, Weight takenWeight
, LBasicBlock notTaken
, Weight notTakenWeight
);
387 void branch(LValue condition
, WeightedTarget taken
, WeightedTarget notTaken
)
389 branch(condition
, taken
.target(), taken
.weight(), notTaken
.target(), notTaken
.weight());
392 // Branches to an already-created handler if true, "falls through" if false. Fall-through is
393 // simulated by creating a continuation for you.
394 void check(LValue condition
, WeightedTarget taken
, Weight notTakenWeight
);
396 // Same as check(), but uses Weight::inverse() to compute the notTakenWeight.
397 void check(LValue condition
, WeightedTarget taken
);
399 template<typename VectorType
>
400 void switchInstruction(LValue value
, const VectorType
& cases
, LBasicBlock fallThrough
, Weight fallThroughWeight
)
402 LValue inst
= buildSwitch(m_builder
, value
, cases
, fallThrough
);
405 if (!fallThroughWeight
)
407 total
+= fallThroughWeight
.value();
408 for (unsigned i
= cases
.size(); i
--;) {
409 if (!cases
[i
].weight())
411 total
+= cases
[i
].weight().value();
414 Vector
<LValue
> mdArgs
;
415 mdArgs
.append(branchWeights
);
416 mdArgs
.append(constInt32(fallThroughWeight
.scaleToTotal(total
)));
417 for (unsigned i
= 0; i
< cases
.size(); ++i
)
418 mdArgs
.append(constInt32(cases
[i
].weight().scaleToTotal(total
)));
420 setMetadata(inst
, profKind
, mdNode(m_context
, mdArgs
));
423 void ret(LValue value
) { buildRet(m_builder
, value
); }
425 void unreachable() { buildUnreachable(m_builder
); }
429 call(trapIntrinsic());
432 ValueFromBlock
anchor(LValue value
)
434 return ValueFromBlock(value
, m_block
);
438 AbstractHeapRepository
* m_heaps
;
441 LBasicBlock m_nextBlock
;
444 #define FTL_NEW_BLOCK(output, nameArguments) \
445 (LIKELY(!verboseCompilationEnabled()) \
446 ? (output).newBlock() \
447 : (output).newBlock((toCString nameArguments).data()))
449 } } // namespace JSC::FTL
451 #endif // ENABLE(FTL_JIT)
453 #endif // FTLOutput_h