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