1/*
2 * Copyright (C) 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. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY 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 ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#pragma once
27
28#include "Opcode.h"
29#include "OpcodeSize.h"
30
31namespace JSC {
32
33struct JSOpcodeTraits {
34 using OpcodeID = ::JSC::OpcodeID;
35 static constexpr OpcodeID numberOfBytecodesWithMetadata = static_cast<OpcodeID>(NUMBER_OF_BYTECODE_WITH_METADATA);
36 static constexpr OpcodeID wide16 = op_wide16;
37 static constexpr OpcodeID wide32 = op_wide32;
38 static constexpr const unsigned* opcodeLengths = ::JSC::opcodeLengths;
39 static constexpr const char* const* opcodeNames = ::JSC::opcodeNames;
40};
41
42struct WasmOpcodeTraits {
43 using OpcodeID = WasmOpcodeID;
44 static constexpr OpcodeID numberOfBytecodesWithMetadata = static_cast<OpcodeID>(NUMBER_OF_WASM_WITH_METADATA);
45 static constexpr OpcodeID wide16 = wasm_wide16;
46 static constexpr OpcodeID wide32 = wasm_wide32;
47 static constexpr const unsigned* opcodeLengths = wasmOpcodeLengths;
48 static constexpr const char* const* opcodeNames = wasmOpcodeNames;
49};
50
51
52template<typename Opcode>
53struct BaseInstruction {
54
55 struct Metadata { };
56
57protected:
58 BaseInstruction()
59 { }
60
61private:
62 template<OpcodeSize Width>
63 class Impl {
64 public:
65 template<typename Traits = JSOpcodeTraits>
66 typename Traits::OpcodeID opcodeID() const { return static_cast<typename Traits::OpcodeID>(m_opcode); }
67
68 private:
69 typename TypeBySize<Width>::unsignedType m_opcode;
70 };
71
72public:
73 template<typename Traits = JSOpcodeTraits>
74 typename Traits::OpcodeID opcodeID() const
75 {
76 if (isWide32<Traits>())
77 return wide32<Traits>()->template opcodeID<Traits>();
78 if (isWide16<Traits>())
79 return wide16<Traits>()->template opcodeID<Traits>();
80 return narrow()->template opcodeID<Traits>();
81 }
82
83 template<typename Traits = JSOpcodeTraits>
84 const char* name() const
85 {
86 return Traits::opcodeNames[opcodeID()];
87 }
88
89 template<typename Traits = JSOpcodeTraits>
90 bool isWide16() const
91 {
92 return narrow()->template opcodeID<Traits>() == Traits::wide16;
93 }
94
95 template<typename Traits = JSOpcodeTraits>
96 bool isWide32() const
97 {
98 return narrow()->template opcodeID<Traits>() == Traits::wide32;
99 }
100
101 template<typename Traits = JSOpcodeTraits>
102 bool hasMetadata() const
103 {
104 return opcodeID<Traits>() < Traits::numberOfBytecodesWithMetadata;
105 }
106
107 template<typename Traits = JSOpcodeTraits>
108 int sizeShiftAmount() const
109 {
110 if (isWide32<Traits>())
111 return 2;
112 if (isWide16<Traits>())
113 return 1;
114 return 0;
115 }
116
117 template<typename Traits = JSOpcodeTraits>
118 size_t size() const
119 {
120 auto sizeShiftAmount = this->sizeShiftAmount<Traits>();
121 auto padding = sizeShiftAmount ? 1 : 0;
122 auto size = 1 << sizeShiftAmount;
123 return Traits::opcodeLengths[opcodeID<Traits>()] * size + padding;
124 }
125
126 template<class T, typename Traits = JSOpcodeTraits>
127 bool is() const
128 {
129 return opcodeID<Traits>() == T::opcodeID;
130 }
131
132 template<class T, typename Traits = JSOpcodeTraits>
133 T as() const
134 {
135 ASSERT((is<T, Traits>()));
136 return T::decode(reinterpret_cast<const uint8_t*>(this));
137 }
138
139 template<class T, typename Traits = JSOpcodeTraits>
140 T* cast()
141 {
142 ASSERT((is<T, Traits>()));
143 return bitwise_cast<T*>(this);
144 }
145
146 template<class T, typename Traits = JSOpcodeTraits>
147 const T* cast() const
148 {
149 ASSERT((is<T, Traits>()));
150 return reinterpret_cast<const T*>(this);
151 }
152
153 const Impl<OpcodeSize::Narrow>* narrow() const
154 {
155 return reinterpret_cast<const Impl<OpcodeSize::Narrow>*>(this);
156 }
157
158 template<typename Traits = JSOpcodeTraits>
159 const Impl<OpcodeSize::Wide16>* wide16() const
160 {
161
162 ASSERT(isWide16<Traits>());
163 return reinterpret_cast<const Impl<OpcodeSize::Wide16>*>(bitwise_cast<uintptr_t>(this) + 1);
164 }
165
166 template<typename Traits = JSOpcodeTraits>
167 const Impl<OpcodeSize::Wide32>* wide32() const
168 {
169
170 ASSERT(isWide32<Traits>());
171 return reinterpret_cast<const Impl<OpcodeSize::Wide32>*>(bitwise_cast<uintptr_t>(this) + 1);
172 }
173};
174
175struct Instruction : public BaseInstruction<OpcodeID> {
176};
177
178struct WasmInstance : public BaseInstruction<WasmOpcodeID> {
179};
180
181} // namespace JSC
182