1/*
2 * Copyright (C) 2015-2018 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 "B3ValueRep.h"
28
29#if ENABLE(B3_JIT)
30
31#include "AssemblyHelpers.h"
32#include "JSCInlines.h"
33
34namespace JSC { namespace B3 {
35
36void ValueRep::addUsedRegistersTo(RegisterSet& set) const
37{
38 switch (m_kind) {
39 case WarmAny:
40 case ColdAny:
41 case LateColdAny:
42 case SomeRegister:
43 case SomeRegisterWithClobber:
44 case SomeEarlyRegister:
45 case Constant:
46 return;
47 case LateRegister:
48 case Register:
49 set.set(reg());
50 return;
51 case Stack:
52 case StackArgument:
53 set.set(MacroAssembler::stackPointerRegister);
54 set.set(GPRInfo::callFrameRegister);
55 return;
56 }
57 RELEASE_ASSERT_NOT_REACHED();
58}
59
60RegisterSet ValueRep::usedRegisters() const
61{
62 RegisterSet result;
63 addUsedRegistersTo(result);
64 return result;
65}
66
67void ValueRep::dump(PrintStream& out) const
68{
69 out.print(m_kind);
70 switch (m_kind) {
71 case WarmAny:
72 case ColdAny:
73 case LateColdAny:
74 case SomeRegister:
75 case SomeRegisterWithClobber:
76 case SomeEarlyRegister:
77 return;
78 case LateRegister:
79 case Register:
80 out.print("(", reg(), ")");
81 return;
82 case Stack:
83 out.print("(", offsetFromFP(), ")");
84 return;
85 case StackArgument:
86 out.print("(", offsetFromSP(), ")");
87 return;
88 case Constant:
89 out.print("(", value(), ")");
90 return;
91 }
92 RELEASE_ASSERT_NOT_REACHED();
93}
94
95void ValueRep::emitRestore(AssemblyHelpers& jit, Reg reg) const
96{
97 if (reg.isGPR()) {
98 switch (kind()) {
99 case LateRegister:
100 case Register:
101 if (isGPR())
102 jit.move(gpr(), reg.gpr());
103 else
104 jit.moveDoubleTo64(fpr(), reg.gpr());
105 break;
106 case Stack:
107 jit.load64(AssemblyHelpers::Address(GPRInfo::callFrameRegister, offsetFromFP()), reg.gpr());
108 break;
109 case Constant:
110 jit.move(AssemblyHelpers::TrustedImm64(value()), reg.gpr());
111 break;
112 default:
113 RELEASE_ASSERT_NOT_REACHED();
114 break;
115 }
116 return;
117 }
118
119 switch (kind()) {
120 case LateRegister:
121 case Register:
122 if (isGPR())
123 jit.move64ToDouble(gpr(), reg.fpr());
124 else
125 jit.moveDouble(fpr(), reg.fpr());
126 break;
127 case Stack:
128 jit.loadDouble(AssemblyHelpers::Address(GPRInfo::callFrameRegister, offsetFromFP()), reg.fpr());
129 break;
130 case Constant:
131 jit.move(AssemblyHelpers::TrustedImm64(value()), jit.scratchRegister());
132 jit.move64ToDouble(jit.scratchRegister(), reg.fpr());
133 break;
134 default:
135 RELEASE_ASSERT_NOT_REACHED();
136 break;
137 }
138}
139
140ValueRecovery ValueRep::recoveryForJSValue() const
141{
142 switch (kind()) {
143 case LateRegister:
144 case Register:
145 return ValueRecovery::inGPR(gpr(), DataFormatJS);
146 case Stack:
147 RELEASE_ASSERT(!(offsetFromFP() % sizeof(EncodedJSValue)));
148 return ValueRecovery::displacedInJSStack(
149 VirtualRegister(offsetFromFP() / sizeof(EncodedJSValue)),
150 DataFormatJS);
151 case Constant:
152 return ValueRecovery::constant(JSValue::decode(value()));
153 default:
154 RELEASE_ASSERT_NOT_REACHED();
155 return { };
156 }
157}
158
159} } // namespace JSC::B3
160
161namespace WTF {
162
163using namespace JSC::B3;
164
165void printInternal(PrintStream& out, ValueRep::Kind kind)
166{
167 switch (kind) {
168 case ValueRep::WarmAny:
169 out.print("WarmAny");
170 return;
171 case ValueRep::ColdAny:
172 out.print("ColdAny");
173 return;
174 case ValueRep::LateColdAny:
175 out.print("LateColdAny");
176 return;
177 case ValueRep::SomeRegister:
178 out.print("SomeRegister");
179 return;
180 case ValueRep::SomeRegisterWithClobber:
181 out.print("SomeRegisterWithClobber");
182 return;
183 case ValueRep::SomeEarlyRegister:
184 out.print("SomeEarlyRegister");
185 return;
186 case ValueRep::Register:
187 out.print("Register");
188 return;
189 case ValueRep::LateRegister:
190 out.print("LateRegister");
191 return;
192 case ValueRep::Stack:
193 out.print("Stack");
194 return;
195 case ValueRep::StackArgument:
196 out.print("StackArgument");
197 return;
198 case ValueRep::Constant:
199 out.print("Constant");
200 return;
201 }
202 RELEASE_ASSERT_NOT_REACHED();
203}
204
205} // namespace WTF
206
207#endif // ENABLE(B3_JIT)
208