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#pragma once
27
28#if ENABLE(B3_JIT)
29
30#include "AirArg.h"
31#include "AirCode.h"
32#include "AirTmp.h"
33
34namespace JSC { namespace B3 { namespace Air {
35
36inline Tmp::Tmp(const Arg& arg)
37{
38 *this = arg.tmp();
39}
40
41// When a Hash structure is too slow or when Sets contains most values, you can
42// use direct array addressing with Tmps.
43template<Bank bank>
44struct AbsoluteTmpMapper;
45
46template<>
47struct AbsoluteTmpMapper<GP> {
48 static unsigned absoluteIndex(const Tmp& tmp)
49 {
50 ASSERT(tmp.isGP());
51 ASSERT(static_cast<int>(tmp.internalValue()) > 0);
52 return tmp.internalValue();
53 }
54
55 static unsigned absoluteIndex(unsigned tmpIndex)
56 {
57 return absoluteIndex(Tmp::gpTmpForIndex(tmpIndex));
58 }
59
60 static unsigned lastMachineRegisterIndex()
61 {
62 return absoluteIndex(Tmp(MacroAssembler::lastRegister()));
63 }
64
65 static Tmp tmpFromAbsoluteIndex(unsigned tmpIndex)
66 {
67 return Tmp::tmpForInternalValue(tmpIndex);
68 }
69};
70
71template<>
72struct AbsoluteTmpMapper<FP> {
73 static unsigned absoluteIndex(const Tmp& tmp)
74 {
75 ASSERT(tmp.isFP());
76 ASSERT(static_cast<int>(tmp.internalValue()) < 0);
77 return -tmp.internalValue();
78 }
79
80 static unsigned absoluteIndex(unsigned tmpIndex)
81 {
82 return absoluteIndex(Tmp::fpTmpForIndex(tmpIndex));
83 }
84
85 static unsigned lastMachineRegisterIndex()
86 {
87 return absoluteIndex(Tmp(MacroAssembler::lastFPRegister()));
88 }
89
90 static Tmp tmpFromAbsoluteIndex(unsigned tmpIndex)
91 {
92 return Tmp::tmpForInternalValue(-tmpIndex);
93 }
94};
95
96template<Bank theBank>
97class Tmp::Indexed : public Tmp {
98public:
99 static const char* const dumpPrefix;
100
101 Indexed(Tmp tmp)
102 : Tmp(tmp)
103 {
104 }
105
106 unsigned index() const
107 {
108 return tmpIndex(theBank);
109 }
110};
111
112template<Bank theBank>
113class Tmp::AbsolutelyIndexed : public Tmp {
114public:
115 static const char* const dumpPrefix;
116
117 AbsolutelyIndexed(Tmp tmp)
118 : Tmp(tmp)
119 {
120 }
121
122 unsigned index() const
123 {
124 return AbsoluteTmpMapper<theBank>::absoluteIndex(*this);
125 }
126};
127
128class Tmp::LinearlyIndexed : public Tmp {
129public:
130 static const char* const dumpPrefix;
131
132 LinearlyIndexed(Tmp tmp, Code& code)
133 : Tmp(tmp)
134 , m_code(&code)
135 {
136 }
137
138 ALWAYS_INLINE unsigned index() const
139 {
140 if (isGP())
141 return AbsoluteTmpMapper<GP>::absoluteIndex(*this);
142 return absoluteIndexEnd(*m_code, GP) + AbsoluteTmpMapper<FP>::absoluteIndex(*this);
143 }
144
145private:
146 Code* m_code;
147};
148
149template<Bank theBank>
150inline Tmp::Indexed<theBank> Tmp::indexed() const
151{
152 return Indexed<theBank>(*this);
153}
154
155template<Bank theBank>
156inline Tmp::AbsolutelyIndexed<theBank> Tmp::absolutelyIndexed() const
157{
158 return AbsolutelyIndexed<theBank>(*this);
159}
160
161inline Tmp::LinearlyIndexed Tmp::linearlyIndexed(Code& code) const
162{
163 return LinearlyIndexed(*this, code);
164}
165
166ALWAYS_INLINE unsigned Tmp::indexEnd(Code& code, Bank bank)
167{
168 return code.numTmps(bank);
169}
170
171ALWAYS_INLINE unsigned Tmp::absoluteIndexEnd(Code& code, Bank bank)
172{
173 if (bank == GP)
174 return AbsoluteTmpMapper<GP>::absoluteIndex(code.numTmps(GP));
175 return AbsoluteTmpMapper<FP>::absoluteIndex(code.numTmps(FP));
176}
177
178ALWAYS_INLINE unsigned Tmp::linearIndexEnd(Code& code)
179{
180 return absoluteIndexEnd(code, GP) + absoluteIndexEnd(code, FP);
181}
182
183ALWAYS_INLINE Tmp Tmp::tmpForAbsoluteIndex(Bank bank, unsigned index)
184{
185 if (bank == GP)
186 return AbsoluteTmpMapper<GP>::tmpFromAbsoluteIndex(index);
187 ASSERT(bank == FP);
188 return AbsoluteTmpMapper<FP>::tmpFromAbsoluteIndex(index);
189}
190
191ALWAYS_INLINE Tmp Tmp::tmpForLinearIndex(Code& code, unsigned index)
192{
193 unsigned gpEnd = absoluteIndexEnd(code, GP);
194 if (index < gpEnd)
195 return tmpForAbsoluteIndex(GP, index);
196 return tmpForAbsoluteIndex(FP, index - gpEnd);
197}
198
199} } } // namespace JSC::B3::Air
200
201#endif // ENABLE(B3_JIT)
202