]>
Commit | Line | Data |
---|---|---|
81345200 A |
1 | /* |
2 | * Copyright (C) 2013, 2014 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 | #ifndef FTLOutput_h | |
27 | #define FTLOutput_h | |
28 | ||
29 | #if ENABLE(FTL_JIT) | |
30 | ||
31 | #include "DFGCommon.h" | |
32 | #include "FTLAbbreviations.h" | |
33 | #include "FTLAbstractHeapRepository.h" | |
34 | #include "FTLCommonValues.h" | |
35 | #include "FTLIntrinsicRepository.h" | |
36 | #include "FTLState.h" | |
37 | #include "FTLSwitchCase.h" | |
38 | #include "FTLTypedPointer.h" | |
39 | #include "FTLWeight.h" | |
40 | #include "FTLWeightedTarget.h" | |
41 | #include <wtf/StringPrintStream.h> | |
42 | ||
43 | namespace JSC { namespace FTL { | |
44 | ||
45 | // Idiomatic LLVM IR builder specifically designed for FTL. This uses our own lowering | |
46 | // terminology, and has some of its own notions: | |
47 | // | |
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. | |
52 | // | |
53 | // We say that a "pointer" is what LLVM considers to be a pointer-width integer. | |
54 | // | |
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). | |
59 | // | |
60 | // We say that "get" and "set" are what LLVM considers to be "load" and "store". Get | |
61 | // and set take references. | |
62 | // | |
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. | |
67 | ||
68 | enum Scale { ScaleOne, ScaleTwo, ScaleFour, ScaleEight, ScalePtr }; | |
69 | ||
70 | class Output : public IntrinsicRepository { | |
71 | public: | |
72 | Output(LContext); | |
73 | ~Output(); | |
74 | ||
75 | void initialize(LModule, LValue, AbstractHeapRepository&); | |
76 | ||
77 | LBasicBlock insertNewBlocksBefore(LBasicBlock nextBlock) | |
78 | { | |
79 | LBasicBlock lastNextBlock = m_nextBlock; | |
80 | m_nextBlock = nextBlock; | |
81 | return lastNextBlock; | |
82 | } | |
83 | ||
84 | LBasicBlock appendTo(LBasicBlock, LBasicBlock nextBlock); | |
85 | ||
86 | void appendTo(LBasicBlock); | |
87 | ||
88 | LBasicBlock newBlock(const char* name = ""); | |
89 | ||
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); } | |
94 | template<typename T> | |
95 | LValue constIntPtr(T* value) { return constInt(intPtr, bitwise_cast<intptr_t>(value)); } | |
96 | template<typename T> | |
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); } | |
100 | ||
101 | LValue phi(LType type) { return buildPhi(m_builder, type); } | |
102 | template<typename... Params> | |
103 | LValue phi(LType type, ValueFromBlock value, Params... theRest) | |
104 | { | |
105 | LValue result = phi(type, theRest...); | |
106 | addIncoming(result, value); | |
107 | return result; | |
108 | } | |
109 | template<typename VectorType> | |
110 | LValue phi(LType type, const VectorType& vector) | |
111 | { | |
112 | LValue result = phi(type); | |
113 | for (unsigned i = 0; i < vector.size(); ++i) | |
114 | addIncoming(result, vector[i]); | |
115 | return result; | |
116 | } | |
117 | ||
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); } | |
124 | ||
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); } | |
131 | ||
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); } | |
137 | LValue lShr(LValue left, LValue right) { return buildLShr(m_builder, left, right); } | |
138 | LValue bitNot(LValue value) { return buildNot(m_builder, value); } | |
139 | ||
140 | LValue insertElement(LValue vector, LValue element, LValue index) { return buildInsertElement(m_builder, vector, element, index); } | |
141 | ||
142 | LValue addWithOverflow32(LValue left, LValue right) | |
143 | { | |
144 | return call(addWithOverflow32Intrinsic(), left, right); | |
145 | } | |
146 | LValue subWithOverflow32(LValue left, LValue right) | |
147 | { | |
148 | return call(subWithOverflow32Intrinsic(), left, right); | |
149 | } | |
150 | LValue mulWithOverflow32(LValue left, LValue right) | |
151 | { | |
152 | return call(mulWithOverflow32Intrinsic(), left, right); | |
153 | } | |
154 | LValue addWithOverflow64(LValue left, LValue right) | |
155 | { | |
156 | return call(addWithOverflow64Intrinsic(), left, right); | |
157 | } | |
158 | LValue subWithOverflow64(LValue left, LValue right) | |
159 | { | |
160 | return call(subWithOverflow64Intrinsic(), left, right); | |
161 | } | |
162 | LValue mulWithOverflow64(LValue left, LValue right) | |
163 | { | |
164 | return call(mulWithOverflow64Intrinsic(), left, right); | |
165 | } | |
166 | LValue doubleAbs(LValue value) | |
167 | { | |
168 | return call(doubleAbsIntrinsic(), value); | |
169 | } | |
170 | ||
171 | LValue doubleSin(LValue value) | |
172 | { | |
173 | return call(doubleSinIntrinsic(), value); | |
174 | } | |
175 | LValue doubleCos(LValue value) | |
176 | { | |
177 | return call(doubleCosIntrinsic(), value); | |
178 | } | |
179 | ||
180 | LValue doubleSqrt(LValue value) | |
181 | { | |
182 | return call(doubleSqrtIntrinsic(), value); | |
183 | } | |
184 | ||
185 | static bool hasSensibleDoubleToInt() { return isX86(); } | |
186 | LValue sensibleDoubleToInt(LValue); | |
187 | ||
188 | LValue signExt(LValue value, LType type) { return buildSExt(m_builder, value, type); } | |
189 | LValue zeroExt(LValue value, LType type) { return buildZExt(m_builder, value, type); } | |
190 | LValue fpToInt(LValue value, LType type) { return buildFPToSI(m_builder, value, type); } | |
191 | LValue fpToUInt(LValue value, LType type) { return buildFPToUI(m_builder, value, type); } | |
192 | LValue fpToInt32(LValue value) { return fpToInt(value, int32); } | |
193 | LValue fpToUInt32(LValue value) { return fpToUInt(value, int32); } | |
194 | LValue intToFP(LValue value, LType type) { return buildSIToFP(m_builder, value, type); } | |
195 | LValue intToDouble(LValue value) { return intToFP(value, doubleType); } | |
196 | LValue unsignedToFP(LValue value, LType type) { return buildUIToFP(m_builder, value, type); } | |
197 | LValue unsignedToDouble(LValue value) { return unsignedToFP(value, doubleType); } | |
198 | LValue intCast(LValue value, LType type) { return buildIntCast(m_builder, value, type); } | |
199 | LValue castToInt32(LValue value) { return intCast(value, int32); } | |
200 | LValue fpCast(LValue value, LType type) { return buildFPCast(m_builder, value, type); } | |
201 | LValue intToPtr(LValue value, LType type) { return buildIntToPtr(m_builder, value, type); } | |
202 | LValue ptrToInt(LValue value, LType type) { return buildPtrToInt(m_builder, value, type); } | |
203 | LValue bitCast(LValue value, LType type) { return buildBitCast(m_builder, value, type); } | |
204 | ||
205 | LValue alloca(LType type) { return buildAlloca(m_builder, type); } | |
206 | ||
207 | // Access the value of an alloca. Also used as a low-level implementation primitive for | |
208 | // load(). Never use this to load from "pointers" in the FTL sense, since FTL pointers | |
209 | // are actually integers. This requires an LLVM pointer. Broadly speaking, you don't | |
210 | // have any LLVM pointers even if you really think you do. A TypedPointer is not an | |
211 | // LLVM pointer. See comment block at top of this file to understand the distinction | |
212 | // between LLVM pointers, FTL pointers, and FTL references. | |
213 | LValue get(LValue reference) { return buildLoad(m_builder, reference); } | |
214 | // Similar to get() but for storing to the value in an alloca. | |
215 | LValue set(LValue value, LValue reference) { return buildStore(m_builder, value, reference); } | |
216 | ||
217 | LValue load(TypedPointer, LType refType); | |
218 | void store(LValue, TypedPointer, LType refType); | |
219 | ||
220 | LValue load8(TypedPointer pointer) { return load(pointer, ref8); } | |
221 | LValue load16(TypedPointer pointer) { return load(pointer, ref16); } | |
222 | LValue load32(TypedPointer pointer) { return load(pointer, ref32); } | |
223 | LValue load64(TypedPointer pointer) { return load(pointer, ref64); } | |
224 | LValue loadPtr(TypedPointer pointer) { return load(pointer, refPtr); } | |
225 | LValue loadFloat(TypedPointer pointer) { return load(pointer, refFloat); } | |
226 | LValue loadDouble(TypedPointer pointer) { return load(pointer, refDouble); } | |
227 | void store8(LValue value, TypedPointer pointer) { store(value, pointer, ref8); } | |
228 | void store16(LValue value, TypedPointer pointer) { store(value, pointer, ref16); } | |
229 | void store32(LValue value, TypedPointer pointer) { store(value, pointer, ref32); } | |
230 | void store64(LValue value, TypedPointer pointer) { store(value, pointer, ref64); } | |
231 | void storePtr(LValue value, TypedPointer pointer) { store(value, pointer, refPtr); } | |
232 | void storeFloat(LValue value, TypedPointer pointer) { store(value, pointer, refFloat); } | |
233 | void storeDouble(LValue value, TypedPointer pointer) { store(value, pointer, refDouble); } | |
234 | ||
235 | LValue addPtr(LValue value, ptrdiff_t immediate = 0) | |
236 | { | |
237 | if (!immediate) | |
238 | return value; | |
239 | return add(value, constIntPtr(immediate)); | |
240 | } | |
241 | ||
242 | // Construct an address by offsetting base by the requested amount and ascribing | |
243 | // the requested abstract heap to it. | |
244 | TypedPointer address(const AbstractHeap& heap, LValue base, ptrdiff_t offset = 0) | |
245 | { | |
246 | return TypedPointer(heap, addPtr(base, offset)); | |
247 | } | |
248 | // Construct an address by offsetting base by the amount specified by the field, | |
249 | // and optionally an additional amount (use this with care), and then creating | |
250 | // a TypedPointer with the given field as the heap. | |
251 | TypedPointer address(LValue base, const AbstractField& field, ptrdiff_t offset = 0) | |
252 | { | |
253 | return address(field, base, offset + field.offset()); | |
254 | } | |
255 | ||
256 | LValue baseIndex(LValue base, LValue index, Scale, ptrdiff_t offset = 0); | |
257 | ||
258 | TypedPointer baseIndex(const AbstractHeap& heap, LValue base, LValue index, Scale scale, ptrdiff_t offset = 0) | |
259 | { | |
260 | return TypedPointer(heap, baseIndex(base, index, scale, offset)); | |
261 | } | |
262 | TypedPointer baseIndex(IndexedAbstractHeap& heap, LValue base, LValue index, JSValue indexAsConstant = JSValue(), ptrdiff_t offset = 0) | |
263 | { | |
264 | return heap.baseIndex(*this, base, index, indexAsConstant, offset); | |
265 | } | |
266 | ||
267 | TypedPointer absolute(void* address) | |
268 | { | |
269 | return TypedPointer(m_heaps->absolute[address], constIntPtr(address)); | |
270 | } | |
271 | ||
272 | LValue load8(LValue base, const AbstractField& field) { return load8(address(base, field)); } | |
273 | LValue load16(LValue base, const AbstractField& field) { return load16(address(base, field)); } | |
274 | LValue load32(LValue base, const AbstractField& field) { return load32(address(base, field)); } | |
275 | LValue load64(LValue base, const AbstractField& field) { return load64(address(base, field)); } | |
276 | LValue loadPtr(LValue base, const AbstractField& field) { return loadPtr(address(base, field)); } | |
277 | LValue loadDouble(LValue base, const AbstractField& field) { return loadDouble(address(base, field)); } | |
278 | void store8(LValue value, LValue base, const AbstractField& field) { store8(value, address(base, field)); } | |
279 | void store32(LValue value, LValue base, const AbstractField& field) { store32(value, address(base, field)); } | |
280 | void store64(LValue value, LValue base, const AbstractField& field) { store64(value, address(base, field)); } | |
281 | void storePtr(LValue value, LValue base, const AbstractField& field) { storePtr(value, address(base, field)); } | |
282 | void storeDouble(LValue value, LValue base, const AbstractField& field) { storeDouble(value, address(base, field)); } | |
283 | ||
284 | void ascribeRange(LValue loadInstruction, const ValueRange& range) | |
285 | { | |
286 | range.decorateInstruction(m_context, loadInstruction, rangeKind); | |
287 | } | |
288 | ||
289 | LValue nonNegative32(LValue loadInstruction) | |
290 | { | |
291 | ascribeRange(loadInstruction, nonNegativeInt32); | |
292 | return loadInstruction; | |
293 | } | |
294 | ||
295 | LValue load32NonNegative(TypedPointer pointer) { return nonNegative32(load32(pointer)); } | |
296 | LValue load32NonNegative(LValue base, const AbstractField& field) { return nonNegative32(load32(base, field)); } | |
297 | ||
298 | LValue icmp(LIntPredicate cond, LValue left, LValue right) { return buildICmp(m_builder, cond, left, right); } | |
299 | LValue equal(LValue left, LValue right) { return icmp(LLVMIntEQ, left, right); } | |
300 | LValue notEqual(LValue left, LValue right) { return icmp(LLVMIntNE, left, right); } | |
301 | LValue above(LValue left, LValue right) { return icmp(LLVMIntUGT, left, right); } | |
302 | LValue aboveOrEqual(LValue left, LValue right) { return icmp(LLVMIntUGE, left, right); } | |
303 | LValue below(LValue left, LValue right) { return icmp(LLVMIntULT, left, right); } | |
304 | LValue belowOrEqual(LValue left, LValue right) { return icmp(LLVMIntULE, left, right); } | |
305 | LValue greaterThan(LValue left, LValue right) { return icmp(LLVMIntSGT, left, right); } | |
306 | LValue greaterThanOrEqual(LValue left, LValue right) { return icmp(LLVMIntSGE, left, right); } | |
307 | LValue lessThan(LValue left, LValue right) { return icmp(LLVMIntSLT, left, right); } | |
308 | LValue lessThanOrEqual(LValue left, LValue right) { return icmp(LLVMIntSLE, left, right); } | |
309 | ||
310 | LValue fcmp(LRealPredicate cond, LValue left, LValue right) { return buildFCmp(m_builder, cond, left, right); } | |
311 | LValue doubleEqual(LValue left, LValue right) { return fcmp(LLVMRealOEQ, left, right); } | |
312 | LValue doubleNotEqualOrUnordered(LValue left, LValue right) { return fcmp(LLVMRealUNE, left, right); } | |
313 | LValue doubleLessThan(LValue left, LValue right) { return fcmp(LLVMRealOLT, left, right); } | |
314 | LValue doubleLessThanOrEqual(LValue left, LValue right) { return fcmp(LLVMRealOLE, left, right); } | |
315 | LValue doubleGreaterThan(LValue left, LValue right) { return fcmp(LLVMRealOGT, left, right); } | |
316 | LValue doubleGreaterThanOrEqual(LValue left, LValue right) { return fcmp(LLVMRealOGE, left, right); } | |
317 | LValue doubleEqualOrUnordered(LValue left, LValue right) { return fcmp(LLVMRealUEQ, left, right); } | |
318 | LValue doubleNotEqual(LValue left, LValue right) { return fcmp(LLVMRealONE, left, right); } | |
319 | LValue doubleLessThanOrUnordered(LValue left, LValue right) { return fcmp(LLVMRealULT, left, right); } | |
320 | LValue doubleLessThanOrEqualOrUnordered(LValue left, LValue right) { return fcmp(LLVMRealULE, left, right); } | |
321 | LValue doubleGreaterThanOrUnordered(LValue left, LValue right) { return fcmp(LLVMRealUGT, left, right); } | |
322 | LValue doubleGreaterThanOrEqualOrUnordered(LValue left, LValue right) { return fcmp(LLVMRealUGE, left, right); } | |
323 | ||
324 | LValue isZero8(LValue value) { return equal(value, int8Zero); } | |
325 | LValue notZero8(LValue value) { return notEqual(value, int8Zero); } | |
326 | LValue isZero32(LValue value) { return equal(value, int32Zero); } | |
327 | LValue notZero32(LValue value) { return notEqual(value, int32Zero); } | |
328 | LValue isZero64(LValue value) { return equal(value, int64Zero); } | |
329 | LValue notZero64(LValue value) { return notEqual(value, int64Zero); } | |
330 | LValue isNull(LValue value) { return equal(value, intPtrZero); } | |
331 | LValue notNull(LValue value) { return notEqual(value, intPtrZero); } | |
332 | ||
333 | LValue testIsZero8(LValue value, LValue mask) { return isZero8(bitAnd(value, mask)); } | |
334 | LValue testNonZero8(LValue value, LValue mask) { return notZero8(bitAnd(value, mask)); } | |
335 | LValue testIsZero32(LValue value, LValue mask) { return isZero32(bitAnd(value, mask)); } | |
336 | LValue testNonZero32(LValue value, LValue mask) { return notZero32(bitAnd(value, mask)); } | |
337 | LValue testIsZero64(LValue value, LValue mask) { return isZero64(bitAnd(value, mask)); } | |
338 | LValue testNonZero64(LValue value, LValue mask) { return notZero64(bitAnd(value, mask)); } | |
339 | ||
340 | LValue select(LValue value, LValue taken, LValue notTaken) { return buildSelect(m_builder, value, taken, notTaken); } | |
341 | LValue extractValue(LValue aggVal, unsigned index) { return buildExtractValue(m_builder, aggVal, index); } | |
342 | ||
343 | LValue fence(LAtomicOrdering ordering = LLVMAtomicOrderingSequentiallyConsistent, SynchronizationScope scope = CrossThread) { return buildFence(m_builder, ordering, scope); } | |
344 | LValue fenceAcqRel() { return fence(LLVMAtomicOrderingAcquireRelease); } | |
345 | ||
346 | template<typename VectorType> | |
347 | LValue call(LValue function, const VectorType& vector) { return buildCall(m_builder, function, vector); } | |
348 | LValue call(LValue function) { return buildCall(m_builder, function); } | |
349 | LValue call(LValue function, LValue arg1) { return buildCall(m_builder, function, arg1); } | |
350 | LValue call(LValue function, LValue arg1, LValue arg2) { return buildCall(m_builder, function, arg1, arg2); } | |
351 | LValue call(LValue function, LValue arg1, LValue arg2, LValue arg3) { return buildCall(m_builder, function, arg1, arg2, arg3); } | |
352 | LValue call(LValue function, LValue arg1, LValue arg2, LValue arg3, LValue arg4) { return buildCall(m_builder, function, arg1, arg2, arg3, arg4); } | |
353 | LValue call(LValue function, LValue arg1, LValue arg2, LValue arg3, LValue arg4, LValue arg5) { return buildCall(m_builder, function, arg1, arg2, arg3, arg4, arg5); } | |
354 | LValue call(LValue function, LValue arg1, LValue arg2, LValue arg3, LValue arg4, LValue arg5, LValue arg6) { return buildCall(m_builder, function, arg1, arg2, arg3, arg4, arg5, arg6); } | |
355 | LValue call(LValue function, LValue arg1, LValue arg2, LValue arg3, LValue arg4, LValue arg5, LValue arg6, LValue arg7) { return buildCall(m_builder, function, arg1, arg2, arg3, arg4, arg5, arg6, arg7); } | |
356 | LValue call(LValue function, LValue arg1, LValue arg2, LValue arg3, LValue arg4, LValue arg5, LValue arg6, LValue arg7, LValue arg8) { return buildCall(m_builder, function, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); } | |
357 | ||
358 | template<typename FunctionType> | |
359 | LValue operation(FunctionType function) | |
360 | { | |
361 | return intToPtr(constIntPtr(function), pointerType(operationType(function))); | |
362 | } | |
363 | ||
364 | void jump(LBasicBlock destination) { buildBr(m_builder, destination); } | |
365 | void branch(LValue condition, LBasicBlock taken, Weight takenWeight, LBasicBlock notTaken, Weight notTakenWeight); | |
366 | void branch(LValue condition, WeightedTarget taken, WeightedTarget notTaken) | |
367 | { | |
368 | branch(condition, taken.target(), taken.weight(), notTaken.target(), notTaken.weight()); | |
369 | } | |
370 | ||
371 | template<typename VectorType> | |
372 | void switchInstruction(LValue value, const VectorType& cases, LBasicBlock fallThrough, Weight fallThroughWeight) | |
373 | { | |
374 | LValue inst = buildSwitch(m_builder, value, cases, fallThrough); | |
375 | ||
376 | double total = 0; | |
377 | if (!fallThroughWeight) | |
378 | return; | |
379 | total += fallThroughWeight.value(); | |
380 | for (unsigned i = cases.size(); i--;) { | |
381 | if (!cases[i].weight()) | |
382 | return; | |
383 | total += cases[i].weight().value(); | |
384 | } | |
385 | ||
386 | Vector<LValue> mdArgs; | |
387 | mdArgs.append(branchWeights); | |
388 | mdArgs.append(constInt32(fallThroughWeight.scaleToTotal(total))); | |
389 | for (unsigned i = 0; i < cases.size(); ++i) | |
390 | mdArgs.append(constInt32(cases[i].weight().scaleToTotal(total))); | |
391 | ||
392 | setMetadata(inst, profKind, mdNode(m_context, mdArgs)); | |
393 | } | |
394 | ||
395 | void ret(LValue value) { buildRet(m_builder, value); } | |
396 | ||
397 | void unreachable() { buildUnreachable(m_builder); } | |
398 | ||
399 | void trap() | |
400 | { | |
401 | call(trapIntrinsic()); | |
402 | } | |
403 | ||
404 | void crashNonTerminal(); | |
405 | ||
406 | void crash() | |
407 | { | |
408 | crashNonTerminal(); | |
409 | unreachable(); | |
410 | } | |
411 | ||
412 | ValueFromBlock anchor(LValue value) | |
413 | { | |
414 | return ValueFromBlock(value, m_block); | |
415 | } | |
416 | ||
417 | LValue m_function; | |
418 | AbstractHeapRepository* m_heaps; | |
419 | LBuilder m_builder; | |
420 | LBasicBlock m_block; | |
421 | LBasicBlock m_nextBlock; | |
422 | }; | |
423 | ||
424 | #define FTL_NEW_BLOCK(output, nameArguments) \ | |
425 | (LIKELY(!verboseCompilationEnabled()) \ | |
426 | ? (output).newBlock() \ | |
427 | : (output).newBlock((toCString nameArguments).data())) | |
428 | ||
429 | } } // namespace JSC::FTL | |
430 | ||
431 | #endif // ENABLE(FTL_JIT) | |
432 | ||
433 | #endif // FTLOutput_h | |
434 |