1/*
2 * Copyright (C) 2015-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 "AirArg.h"
28
29#if ENABLE(B3_JIT)
30
31#include "AirSpecial.h"
32#include "AirStackSlot.h"
33#include "B3Value.h"
34#include "FPRInfo.h"
35#include "GPRInfo.h"
36
37#if ASSERT_DISABLED
38IGNORE_RETURN_TYPE_WARNINGS_BEGIN
39#endif
40
41namespace JSC { namespace B3 { namespace Air {
42
43bool Arg::isStackMemory() const
44{
45 switch (kind()) {
46 case Addr:
47 return base() == Air::Tmp(GPRInfo::callFrameRegister)
48 || base() == Air::Tmp(MacroAssembler::stackPointerRegister);
49 case ExtendedOffsetAddr:
50 case Stack:
51 case CallArg:
52 return true;
53 default:
54 return false;
55 }
56}
57
58bool Arg::isRepresentableAs(Width width, Signedness signedness) const
59{
60 return isRepresentableAs(width, signedness, value());
61}
62
63bool Arg::usesTmp(Air::Tmp tmp) const
64{
65 bool uses = false;
66 const_cast<Arg*>(this)->forEachTmpFast(
67 [&] (Air::Tmp otherTmp) {
68 if (otherTmp == tmp)
69 uses = true;
70 });
71 return uses;
72}
73
74bool Arg::canRepresent(Type type) const
75{
76 return isBank(bankForType(type));
77}
78
79bool Arg::canRepresent(Value* value) const
80{
81 return canRepresent(value->type());
82}
83
84bool Arg::isCompatibleBank(const Arg& other) const
85{
86 if (hasBank())
87 return other.isBank(bank());
88 if (other.hasBank())
89 return isBank(other.bank());
90 return true;
91}
92
93unsigned Arg::jsHash() const
94{
95 unsigned result = static_cast<unsigned>(m_kind);
96
97 switch (m_kind) {
98 case Invalid:
99 case Special:
100 break;
101 case Tmp:
102 result += m_base.internalValue();
103 break;
104 case Imm:
105 case BitImm:
106 case CallArg:
107 case RelCond:
108 case ResCond:
109 case DoubleCond:
110 case StatusCond:
111 case WidthArg:
112 result += static_cast<unsigned>(m_offset);
113 break;
114 case BigImm:
115 case BitImm64:
116 result += static_cast<unsigned>(m_offset);
117 result += static_cast<unsigned>(m_offset >> 32);
118 break;
119 case SimpleAddr:
120 result += m_base.internalValue();
121 break;
122 case Addr:
123 case ExtendedOffsetAddr:
124 result += m_offset;
125 result += m_base.internalValue();
126 break;
127 case Index:
128 result += static_cast<unsigned>(m_offset);
129 result += m_scale;
130 result += m_base.internalValue();
131 result += m_index.internalValue();
132 break;
133 case Stack:
134 result += static_cast<unsigned>(m_scale);
135 result += stackSlot()->index();
136 break;
137 }
138
139 return result;
140}
141
142void Arg::dump(PrintStream& out) const
143{
144 switch (m_kind) {
145 case Invalid:
146 out.print("<invalid>");
147 return;
148 case Tmp:
149 out.print(tmp());
150 return;
151 case Imm:
152 out.print("$", m_offset);
153 return;
154 case BigImm:
155 out.printf("$0x%llx", static_cast<long long unsigned>(m_offset));
156 return;
157 case BitImm:
158 out.print("$", m_offset);
159 return;
160 case BitImm64:
161 out.printf("$0x%llx", static_cast<long long unsigned>(m_offset));
162 return;
163 case SimpleAddr:
164 out.print("(", base(), ")");
165 return;
166 case Addr:
167 case ExtendedOffsetAddr:
168 if (offset())
169 out.print(offset());
170 out.print("(", base(), ")");
171 return;
172 case Index:
173 if (offset())
174 out.print(offset());
175 out.print("(", base(), ",", index());
176 if (scale() != 1)
177 out.print(",", scale());
178 out.print(")");
179 return;
180 case Stack:
181 if (offset())
182 out.print(offset());
183 out.print("(", pointerDump(stackSlot()), ")");
184 return;
185 case CallArg:
186 if (offset())
187 out.print(offset());
188 out.print("(callArg)");
189 return;
190 case RelCond:
191 out.print(asRelationalCondition());
192 return;
193 case ResCond:
194 out.print(asResultCondition());
195 return;
196 case DoubleCond:
197 out.print(asDoubleCondition());
198 return;
199 case StatusCond:
200 out.print(asStatusCondition());
201 return;
202 case Special:
203 out.print(pointerDump(special()));
204 return;
205 case WidthArg:
206 out.print(width());
207 return;
208 }
209
210 RELEASE_ASSERT_NOT_REACHED();
211}
212
213} } } // namespace JSC::B3::Air
214
215namespace WTF {
216
217using namespace JSC::B3::Air;
218
219void printInternal(PrintStream& out, Arg::Kind kind)
220{
221 switch (kind) {
222 case Arg::Invalid:
223 out.print("Invalid");
224 return;
225 case Arg::Tmp:
226 out.print("Tmp");
227 return;
228 case Arg::Imm:
229 out.print("Imm");
230 return;
231 case Arg::BigImm:
232 out.print("BigImm");
233 return;
234 case Arg::BitImm:
235 out.print("BitImm");
236 return;
237 case Arg::BitImm64:
238 out.print("BitImm64");
239 return;
240 case Arg::SimpleAddr:
241 out.print("SimpleAddr");
242 return;
243 case Arg::Addr:
244 out.print("Addr");
245 return;
246 case Arg::ExtendedOffsetAddr:
247 out.print("ExtendedOffsetAddr");
248 return;
249 case Arg::Stack:
250 out.print("Stack");
251 return;
252 case Arg::CallArg:
253 out.print("CallArg");
254 return;
255 case Arg::Index:
256 out.print("Index");
257 return;
258 case Arg::RelCond:
259 out.print("RelCond");
260 return;
261 case Arg::ResCond:
262 out.print("ResCond");
263 return;
264 case Arg::DoubleCond:
265 out.print("DoubleCond");
266 return;
267 case Arg::StatusCond:
268 out.print("StatusCond");
269 return;
270 case Arg::Special:
271 out.print("Special");
272 return;
273 case Arg::WidthArg:
274 out.print("WidthArg");
275 return;
276 }
277
278 RELEASE_ASSERT_NOT_REACHED();
279}
280
281void printInternal(PrintStream& out, Arg::Temperature temperature)
282{
283 switch (temperature) {
284 case Arg::Cold:
285 out.print("Cold");
286 return;
287 case Arg::Warm:
288 out.print("Warm");
289 return;
290 }
291
292 RELEASE_ASSERT_NOT_REACHED();
293}
294
295void printInternal(PrintStream& out, Arg::Phase phase)
296{
297 switch (phase) {
298 case Arg::Early:
299 out.print("Early");
300 return;
301 case Arg::Late:
302 out.print("Late");
303 return;
304 }
305
306 RELEASE_ASSERT_NOT_REACHED();
307}
308
309void printInternal(PrintStream& out, Arg::Timing timing)
310{
311 switch (timing) {
312 case Arg::OnlyEarly:
313 out.print("OnlyEarly");
314 return;
315 case Arg::OnlyLate:
316 out.print("OnlyLate");
317 return;
318 case Arg::EarlyAndLate:
319 out.print("EarlyAndLate");
320 return;
321 }
322
323 RELEASE_ASSERT_NOT_REACHED();
324}
325
326void printInternal(PrintStream& out, Arg::Role role)
327{
328 switch (role) {
329 case Arg::Use:
330 out.print("Use");
331 return;
332 case Arg::Def:
333 out.print("Def");
334 return;
335 case Arg::UseDef:
336 out.print("UseDef");
337 return;
338 case Arg::ZDef:
339 out.print("ZDef");
340 return;
341 case Arg::UseZDef:
342 out.print("UseZDef");
343 return;
344 case Arg::UseAddr:
345 out.print("UseAddr");
346 return;
347 case Arg::ColdUse:
348 out.print("ColdUse");
349 return;
350 case Arg::LateUse:
351 out.print("LateUse");
352 return;
353 case Arg::LateColdUse:
354 out.print("LateColdUse");
355 return;
356 case Arg::EarlyDef:
357 out.print("EarlyDef");
358 return;
359 case Arg::EarlyZDef:
360 out.print("EarlyZDef");
361 return;
362 case Arg::Scratch:
363 out.print("Scratch");
364 return;
365 }
366
367 RELEASE_ASSERT_NOT_REACHED();
368}
369
370void printInternal(PrintStream& out, Arg::Signedness signedness)
371{
372 switch (signedness) {
373 case Arg::Signed:
374 out.print("Signed");
375 return;
376 case Arg::Unsigned:
377 out.print("Unsigned");
378 return;
379 }
380
381 RELEASE_ASSERT_NOT_REACHED();
382}
383
384} // namespace WTF
385
386#if ASSERT_DISABLED
387IGNORE_RETURN_TYPE_WARNINGS_END
388#endif
389
390#endif // ENABLE(B3_JIT)
391