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