1/*
2 * Copyright (C) 2013-2015 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 "FTLLocation.h"
28
29#if ENABLE(FTL_JIT)
30
31#include "B3ValueRep.h"
32#include "FTLSaveRestore.h"
33#include "RegisterSet.h"
34#include <wtf/CommaPrinter.h>
35#include <wtf/DataLog.h>
36#include <wtf/ListDump.h>
37
38namespace JSC { namespace FTL {
39
40using namespace B3;
41
42Location Location::forValueRep(const ValueRep& rep)
43{
44 switch (rep.kind()) {
45 case ValueRep::Register:
46 return forRegister(rep.reg(), 0);
47 case ValueRep::Stack:
48 return forIndirect(GPRInfo::callFrameRegister, rep.offsetFromFP());
49 case ValueRep::Constant:
50 return forConstant(rep.value());
51 default:
52 RELEASE_ASSERT_NOT_REACHED();
53 return Location();
54 }
55}
56
57void Location::dump(PrintStream& out) const
58{
59 out.print("(", kind());
60 if (hasReg())
61 out.print(", ", reg());
62 if (hasOffset())
63 out.print(", ", offset());
64 if (hasAddend())
65 out.print(", ", addend());
66 if (hasConstant())
67 out.print(", ", constant());
68 out.print(")");
69}
70
71bool Location::involvesGPR() const
72{
73 return isGPR() || kind() == Indirect;
74}
75
76bool Location::isGPR() const
77{
78 return kind() == Register && reg().isGPR();
79}
80
81GPRReg Location::gpr() const
82{
83 return reg().gpr();
84}
85
86bool Location::isFPR() const
87{
88 return kind() == Register && reg().isFPR();
89}
90
91FPRReg Location::fpr() const
92{
93 return reg().fpr();
94}
95
96void Location::restoreInto(MacroAssembler& jit, char* savedRegisters, GPRReg result, unsigned numFramesToPop) const
97{
98 if (involvesGPR() && RegisterSet::stackRegisters().get(gpr())) {
99 // Make the result GPR contain the appropriate stack register.
100 if (numFramesToPop) {
101 jit.move(MacroAssembler::framePointerRegister, result);
102
103 for (unsigned i = numFramesToPop - 1; i--;)
104 jit.loadPtr(result, result);
105
106 if (gpr() == MacroAssembler::framePointerRegister)
107 jit.loadPtr(result, result);
108 else
109 jit.addPtr(MacroAssembler::TrustedImmPtr(sizeof(void*) * 2), result);
110 } else
111 jit.move(gpr(), result);
112 }
113
114 if (isGPR()) {
115 if (RegisterSet::stackRegisters().get(gpr())) {
116 // Already restored into result.
117 } else
118 jit.load64(savedRegisters + offsetOfGPR(gpr()), result);
119
120 if (addend())
121 jit.add64(MacroAssembler::TrustedImm32(addend()), result);
122 return;
123 }
124
125 if (isFPR()) {
126 jit.load64(savedRegisters + offsetOfFPR(fpr()), result);
127 ASSERT(!addend());
128 return;
129 }
130
131 switch (kind()) {
132 case Register:
133 // B3 used some register that we don't know about!
134 dataLog("Unrecognized location: ", *this, "\n");
135 RELEASE_ASSERT_NOT_REACHED();
136 return;
137
138 case Indirect:
139 if (RegisterSet::stackRegisters().get(gpr())) {
140 // The stack register is already recovered into result.
141 jit.load64(MacroAssembler::Address(result, offset()), result);
142 return;
143 }
144
145 jit.load64(savedRegisters + offsetOfGPR(gpr()), result);
146 jit.load64(MacroAssembler::Address(result, offset()), result);
147 return;
148
149 case Constant:
150 jit.move(MacroAssembler::TrustedImm64(constant()), result);
151 return;
152
153 case Unprocessed:
154 RELEASE_ASSERT_NOT_REACHED();
155 return;
156 }
157
158 RELEASE_ASSERT_NOT_REACHED();
159}
160
161GPRReg Location::directGPR() const
162{
163 RELEASE_ASSERT(!addend());
164 return gpr();
165}
166
167} } // namespace JSC::FTL
168
169namespace WTF {
170
171using namespace JSC::FTL;
172
173void printInternal(PrintStream& out, JSC::FTL::Location::Kind kind)
174{
175 switch (kind) {
176 case Location::Unprocessed:
177 out.print("Unprocessed");
178 return;
179 case Location::Register:
180 out.print("Register");
181 return;
182 case Location::Indirect:
183 out.print("Indirect");
184 return;
185 case Location::Constant:
186 out.print("Constant");
187 return;
188 }
189 RELEASE_ASSERT_NOT_REACHED();
190}
191
192} // namespace WTF
193
194#endif // ENABLE(FTL_JIT)
195
196