2 * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
28 #if ENABLE(WEBASSEMBLY)
30 #include "B3Compilation.h"
32 #include "CodeLocation.h"
33 #include "Identifier.h"
34 #include "MacroAssemblerCodeRef.h"
35 #include "RegisterAtOffsetList.h"
36 #include "WasmMemoryInformation.h"
38 #include "WasmPageCount.h"
39 #include "WasmSignature.h"
42 #include <wtf/Optional.h>
43 #include <wtf/Vector.h>
51 inline bool isValueType(Type type)
65 enum class ExternalKind : uint8_t {
66 // FIXME auto-generate this. https://bugs.webkit.org/show_bug.cgi?id=165231
73 template<typename Int>
74 static bool isValidExternalKind(Int val)
77 case static_cast<Int>(ExternalKind::Function):
78 case static_cast<Int>(ExternalKind::Table):
79 case static_cast<Int>(ExternalKind::Memory):
80 case static_cast<Int>(ExternalKind::Global):
87 static_assert(static_cast<int>(ExternalKind::Function) == 0, "Wasm needs Function to have the value 0");
88 static_assert(static_cast<int>(ExternalKind::Table) == 1, "Wasm needs Table to have the value 1");
89 static_assert(static_cast<int>(ExternalKind::Memory) == 2, "Wasm needs Memory to have the value 2");
90 static_assert(static_cast<int>(ExternalKind::Global) == 3, "Wasm needs Global to have the value 3");
92 static inline const char* makeString(ExternalKind kind)
95 case ExternalKind::Function: return "Function";
96 case ExternalKind::Table: return "Table";
97 case ExternalKind::Memory: return "Memory";
98 case ExternalKind::Global: return "Global";
100 RELEASE_ASSERT_NOT_REACHED();
108 unsigned kindIndex; // Index in the vector of the corresponding kind.
114 unsigned kindIndex; // Index in the vector of the corresponding kind.
118 enum Mutability : uint8_t {
119 // FIXME auto-generate this. https://bugs.webkit.org/show_bug.cgi?id=165231
124 enum InitializationType {
130 Mutability mutability;
132 InitializationType initializationType { IsImport };
133 uint64_t initialBitsOrImportNumber { 0 };
136 struct FunctionLocationInBinary {
142 enum Type : uint8_t {
147 I32InitExpr(Type type, uint32_t bits)
153 I32InitExpr() = delete;
155 static I32InitExpr globalImport(uint32_t globalImportNumber) { return I32InitExpr(Global, globalImportNumber); }
156 static I32InitExpr constValue(uint32_t constValue) { return I32InitExpr(Const, constValue); }
158 bool isConst() const { return m_type == Const; }
159 bool isGlobalImport() const { return m_type == Global; }
160 uint32_t constValue() const
162 RELEASE_ASSERT(isConst());
165 uint32_t globalImportIndex() const
167 RELEASE_ASSERT(isGlobalImport());
177 uint32_t sizeInBytes;
179 // Bytes are allocated at the end.
180 uint8_t& byte(uint32_t pos)
182 ASSERT(pos < sizeInBytes);
183 return *reinterpret_cast<uint8_t*>(reinterpret_cast<char*>(this) + sizeof(Segment) + pos);
185 static Segment* create(I32InitExpr, uint32_t);
186 static void destroy(Segment*);
187 typedef std::unique_ptr<Segment, decltype(&Segment::destroy)> Ptr;
188 static Ptr adoptPtr(Segment*);
192 Element(I32InitExpr offset)
197 Vector<uint32_t> functionIndices;
200 class TableInformation {
207 TableInformation(uint32_t initial, std::optional<uint32_t> maximum, bool isImport)
210 , m_isImport(isImport)
216 explicit operator bool() const { return m_isValid; }
217 bool isImport() const { return m_isImport; }
218 uint32_t initial() const { return m_initial; }
219 std::optional<uint32_t> maximum() const { return m_maximum; }
223 std::optional<uint32_t> m_maximum;
224 bool m_isImport { false };
225 bool m_isValid { false };
228 struct CustomSection {
230 Vector<uint8_t> payload;
233 struct ModuleInformation {
234 Vector<Import> imports;
235 Vector<SignatureIndex> importFunctionSignatureIndices;
236 Vector<SignatureIndex> internalFunctionSignatureIndices;
238 MemoryInformation memory;
240 Vector<Export> exports;
241 std::optional<uint32_t> startFunctionIndexSpace;
242 Vector<Segment::Ptr> data;
243 Vector<Element> elements;
244 TableInformation tableInformation;
245 Vector<Global> globals;
246 unsigned firstInternalGlobal { 0 };
247 Vector<CustomSection> customSections;
249 size_t functionIndexSpaceSize() const { return importFunctionSignatureIndices.size() + internalFunctionSignatureIndices.size(); }
250 bool isImportedFunctionFromFunctionIndexSpace(size_t functionIndex) const
252 ASSERT(functionIndex < functionIndexSpaceSize());
253 return functionIndex < importFunctionSignatureIndices.size();
255 SignatureIndex signatureIndexFromFunctionIndexSpace(size_t functionIndex) const
257 return isImportedFunctionFromFunctionIndexSpace(functionIndex)
258 ? importFunctionSignatureIndices[functionIndex]
259 : internalFunctionSignatureIndices[functionIndex - importFunctionSignatureIndices.size()];
262 uint32_t importFunctionCount() const { return importFunctionSignatureIndices.size(); }
264 ~ModuleInformation();
267 struct UnlinkedWasmToWasmCall {
268 CodeLocationCall callLocation;
269 size_t functionIndex;
270 enum class Target : uint8_t {
277 std::unique_ptr<B3::Compilation> compilation;
278 RegisterAtOffsetList calleeSaveRegisters;
281 struct WasmInternalFunction {
282 CodeLocationDataLabelPtr wasmCalleeMoveLocation;
283 CodeLocationDataLabelPtr jsToWasmCalleeMoveLocation;
285 Entrypoint wasmEntrypoint;
286 Entrypoint jsToWasmEntrypoint;
289 struct WasmExitStubs {
290 MacroAssemblerCodeRef wasmToJs;
291 MacroAssemblerCodeRef wasmToWasm;
294 // WebAssembly direct calls and call_indirect use indices into "function index space". This space starts with all imports, and then all internal functions.
295 // CallableFunction and FunctionIndexSpace are only meant as fast lookup tables for these opcodes, and do not own code.
296 struct CallableFunction {
297 CallableFunction() = default;
299 CallableFunction(SignatureIndex signatureIndex, void* code = nullptr)
300 : signatureIndex(signatureIndex)
305 // FIXME pack the SignatureIndex and the code pointer into one 64-bit value. https://bugs.webkit.org/show_bug.cgi?id=165511
306 SignatureIndex signatureIndex { Signature::invalidIndex };
307 void* code { nullptr };
309 typedef Vector<CallableFunction> FunctionIndexSpace;
311 } } // namespace JSC::Wasm
313 #endif // ENABLE(WEBASSEMBLY)