1/*
2 * Copyright (C) 2016-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
32namespace JSC { namespace B3 { namespace Air {
33
34template<typename T> struct ArgThingHelper;
35
36template<> struct ArgThingHelper<Tmp> {
37 static bool is(const Arg& arg)
38 {
39 return arg.isTmp();
40 }
41
42 static Tmp as(const Arg& arg)
43 {
44 if (is(arg))
45 return arg.tmp();
46 return Tmp();
47 }
48
49 template<typename Functor>
50 static void forEachFast(Arg& arg, const Functor& functor)
51 {
52 arg.forEachTmpFast(functor);
53 }
54
55 template<typename Functor>
56 static void forEach(Arg& arg, Arg::Role role, Bank bank, Width width, const Functor& functor)
57 {
58 arg.forEachTmp(role, bank, width, functor);
59 }
60};
61
62template<> struct ArgThingHelper<Arg> {
63 static bool is(const Arg&)
64 {
65 return true;
66 }
67
68 static Arg as(const Arg& arg)
69 {
70 return arg;
71 }
72
73 template<typename Functor>
74 static void forEachFast(Arg& arg, const Functor& functor)
75 {
76 functor(arg);
77 }
78
79 template<typename Functor>
80 static void forEach(Arg& arg, Arg::Role role, Bank bank, Width width, const Functor& functor)
81 {
82 functor(arg, role, bank, width);
83 }
84};
85
86template<> struct ArgThingHelper<StackSlot*> {
87 static bool is(const Arg& arg)
88 {
89 return arg.isStack();
90 }
91
92 static StackSlot* as(const Arg& arg)
93 {
94 return arg.stackSlot();
95 }
96
97 template<typename Functor>
98 static void forEachFast(Arg& arg, const Functor& functor)
99 {
100 if (!arg.isStack())
101 return;
102
103 StackSlot* stackSlot = arg.stackSlot();
104 functor(stackSlot);
105 arg = Arg::stack(stackSlot, arg.offset());
106 }
107
108 template<typename Functor>
109 static void forEach(Arg& arg, Arg::Role role, Bank bank, Width width, const Functor& functor)
110 {
111 if (!arg.isStack())
112 return;
113
114 StackSlot* stackSlot = arg.stackSlot();
115
116 // FIXME: This is way too optimistic about the meaning of "Def". It gets lucky for
117 // now because our only use of "Anonymous" stack slots happens to want the optimistic
118 // semantics. We could fix this by just changing the comments that describe the
119 // semantics of "Anonymous".
120 // https://bugs.webkit.org/show_bug.cgi?id=151128
121
122 functor(stackSlot, role, bank, width);
123 arg = Arg::stack(stackSlot, arg.offset());
124 }
125};
126
127template<> struct ArgThingHelper<Reg> {
128 static bool is(const Arg& arg)
129 {
130 return arg.isReg();
131 }
132
133 static Reg as(const Arg& arg)
134 {
135 return arg.reg();
136 }
137
138 template<typename Functor>
139 static void forEachFast(Arg& arg, const Functor& functor)
140 {
141 arg.forEachTmpFast(
142 [&] (Tmp& tmp) {
143 if (!tmp.isReg())
144 return;
145
146 Reg reg = tmp.reg();
147 functor(reg);
148 tmp = Tmp(reg);
149 });
150 }
151
152 template<typename Functor>
153 static void forEach(Arg& arg, Arg::Role argRole, Bank argBank, Width argWidth, const Functor& functor)
154 {
155 arg.forEachTmp(
156 argRole, argBank, argWidth,
157 [&] (Tmp& tmp, Arg::Role role, Bank bank, Width width) {
158 if (!tmp.isReg())
159 return;
160
161 Reg reg = tmp.reg();
162 functor(reg, role, bank, width);
163 tmp = Tmp(reg);
164 });
165 }
166};
167
168template<typename Thing>
169bool Arg::is() const
170{
171 return ArgThingHelper<Thing>::is(*this);
172}
173
174template<typename Thing>
175Thing Arg::as() const
176{
177 return ArgThingHelper<Thing>::as(*this);
178}
179
180template<typename Thing, typename Functor>
181void Arg::forEachFast(const Functor& functor)
182{
183 ArgThingHelper<Thing>::forEachFast(*this, functor);
184}
185
186template<typename Thing, typename Functor>
187void Arg::forEach(Role role, Bank bank, Width width, const Functor& functor)
188{
189 ArgThingHelper<Thing>::forEach(*this, role, bank, width, functor);
190}
191
192} } } // namespace JSC::B3::Air
193
194#endif // ENABLE(B3_JIT)
195