WebAssembly: Wasm::IndexOrName has a raw pointer to Name
[WebKit-https.git] / Source / JavaScriptCore / wasm / WasmFormat.h
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(WEBASSEMBLY)
29
30 #include "B3Type.h"
31 #include "CodeLocation.h"
32 #include "Identifier.h"
33 #include "MacroAssemblerCodeRef.h"
34 #include "RegisterAtOffsetList.h"
35 #include "WasmMemoryInformation.h"
36 #include "WasmName.h"
37 #include "WasmNameSection.h"
38 #include "WasmOps.h"
39 #include "WasmPageCount.h"
40 #include "WasmSignature.h"
41 #include <limits>
42 #include <memory>
43 #include <wtf/Optional.h>
44 #include <wtf/Vector.h>
45
46 namespace JSC {
47
48 namespace B3 {
49 class Compilation;
50 }
51
52 namespace Wasm {
53
54 struct CompilationContext;
55 struct ModuleInformation;
56
57 inline bool isValueType(Type type)
58 {
59     switch (type) {
60     case I32:
61     case I64:
62     case F32:
63     case F64:
64         return true;
65     default:
66         break;
67     }
68     return false;
69 }
70     
71 enum class ExternalKind : uint8_t {
72     // FIXME auto-generate this. https://bugs.webkit.org/show_bug.cgi?id=165231
73     Function = 0,
74     Table = 1,
75     Memory = 2,
76     Global = 3,
77 };
78
79 template<typename Int>
80 inline bool isValidExternalKind(Int val)
81 {
82     switch (val) {
83     case static_cast<Int>(ExternalKind::Function):
84     case static_cast<Int>(ExternalKind::Table):
85     case static_cast<Int>(ExternalKind::Memory):
86     case static_cast<Int>(ExternalKind::Global):
87         return true;
88     }
89     return false;
90 }
91
92 static_assert(static_cast<int>(ExternalKind::Function) == 0, "Wasm needs Function to have the value 0");
93 static_assert(static_cast<int>(ExternalKind::Table)    == 1, "Wasm needs Table to have the value 1");
94 static_assert(static_cast<int>(ExternalKind::Memory)   == 2, "Wasm needs Memory to have the value 2");
95 static_assert(static_cast<int>(ExternalKind::Global)   == 3, "Wasm needs Global to have the value 3");
96
97 inline const char* makeString(ExternalKind kind)
98 {
99     switch (kind) {
100     case ExternalKind::Function: return "function";
101     case ExternalKind::Table: return "table";
102     case ExternalKind::Memory: return "memory";
103     case ExternalKind::Global: return "global";
104     }
105     RELEASE_ASSERT_NOT_REACHED();
106     return "?";
107 }
108
109 struct Import {
110     const Name module;
111     const Name field;
112     ExternalKind kind;
113     unsigned kindIndex; // Index in the vector of the corresponding kind.
114 };
115
116 struct Export {
117     const Name field;
118     ExternalKind kind;
119     unsigned kindIndex; // Index in the vector of the corresponding kind.
120 };
121
122 String makeString(const Name& characters);
123
124 struct Global {
125     enum Mutability : uint8_t {
126         // FIXME auto-generate this. https://bugs.webkit.org/show_bug.cgi?id=165231
127         Mutable = 1,
128         Immutable = 0
129     };
130
131     enum InitializationType {
132         IsImport,
133         FromGlobalImport,
134         FromExpression
135     };
136
137     Mutability mutability;
138     Type type;
139     InitializationType initializationType { IsImport };
140     uint64_t initialBitsOrImportNumber { 0 };
141 };
142
143 struct FunctionLocationInBinary {
144     size_t start;
145     size_t end;
146 };
147
148 class I32InitExpr {
149     enum Type : uint8_t {
150         Global,
151         Const
152     };
153
154     I32InitExpr(Type type, uint32_t bits)
155         : m_bits(bits)
156         , m_type(type)
157     { }
158
159 public:
160     I32InitExpr() = delete;
161
162     static I32InitExpr globalImport(uint32_t globalImportNumber) { return I32InitExpr(Global, globalImportNumber); }
163     static I32InitExpr constValue(uint32_t constValue) { return I32InitExpr(Const, constValue); }
164
165     bool isConst() const { return m_type == Const; }
166     bool isGlobalImport() const { return m_type == Global; }
167     uint32_t constValue() const
168     {
169         RELEASE_ASSERT(isConst());
170         return m_bits;
171     }
172     uint32_t globalImportIndex() const
173     {
174         RELEASE_ASSERT(isGlobalImport());
175         return m_bits;
176     }
177
178 private:
179     uint32_t m_bits;
180     Type m_type;
181 };
182
183 struct Segment {
184     uint32_t sizeInBytes;
185     I32InitExpr offset;
186     // Bytes are allocated at the end.
187     uint8_t& byte(uint32_t pos)
188     {
189         ASSERT(pos < sizeInBytes);
190         return *reinterpret_cast<uint8_t*>(reinterpret_cast<char*>(this) + sizeof(Segment) + pos);
191     }
192     static Segment* create(I32InitExpr, uint32_t);
193     static void destroy(Segment*);
194     typedef std::unique_ptr<Segment, decltype(&Segment::destroy)> Ptr;
195     static Ptr adoptPtr(Segment*);
196 };
197
198 struct Element {
199     Element(I32InitExpr offset)
200         : offset(offset)
201     { }
202
203     I32InitExpr offset;
204     Vector<uint32_t> functionIndices;
205 };
206
207 class TableInformation {
208 public:
209     TableInformation()
210     {
211         ASSERT(!*this);
212     }
213
214     TableInformation(uint32_t initial, std::optional<uint32_t> maximum, bool isImport)
215         : m_initial(initial)
216         , m_maximum(maximum)
217         , m_isImport(isImport)
218         , m_isValid(true)
219     {
220         ASSERT(*this);
221     }
222
223     explicit operator bool() const { return m_isValid; }
224     bool isImport() const { return m_isImport; }
225     uint32_t initial() const { return m_initial; }
226     std::optional<uint32_t> maximum() const { return m_maximum; }
227
228 private:
229     uint32_t m_initial;
230     std::optional<uint32_t> m_maximum;
231     bool m_isImport { false };
232     bool m_isValid { false };
233 };
234     
235 struct CustomSection {
236     Name name;
237     Vector<uint8_t> payload;
238 };
239
240 enum class NameType : uint8_t {
241     Module = 0,
242     Function = 1,
243     Local = 2,
244 };
245     
246 template<typename Int>
247 inline bool isValidNameType(Int val)
248 {
249     switch (val) {
250     case static_cast<Int>(NameType::Module):
251     case static_cast<Int>(NameType::Function):
252     case static_cast<Int>(NameType::Local):
253         return true;
254     }
255     return false;
256 }
257
258 struct UnlinkedWasmToWasmCall {
259     CodeLocationNearCall callLocation;
260     size_t functionIndexSpace;
261 };
262
263 struct Entrypoint {
264     std::unique_ptr<B3::Compilation> compilation;
265     RegisterAtOffsetList calleeSaveRegisters;
266 };
267
268 struct InternalFunction {
269     CodeLocationDataLabelPtr calleeMoveLocation;
270     Entrypoint entrypoint;
271 };
272
273 using WasmEntrypointLoadLocation = void**;
274
275 // WebAssembly direct calls and call_indirect use indices into "function index space". This space starts
276 // with all imports, and then all internal functions. CallableFunction and FunctionIndexSpace are only
277 // meant as fast lookup tables for these opcodes and do not own code.
278 struct CallableFunction {
279 #if !COMPILER_SUPPORTS(NSDMI_FOR_AGGREGATES)
280     CallableFunction() = default;
281     CallableFunction(SignatureIndex signatureIndex, WasmEntrypointLoadLocation code = nullptr)
282         : signatureIndex { signatureIndex }
283         , code { code }
284     {
285     }
286 #endif
287
288     static ptrdiff_t offsetOfWasmEntrypointLoadLocation() { return OBJECT_OFFSETOF(CallableFunction, code); }
289
290     // FIXME: Pack signature index and code pointer into one 64-bit value. See <https://bugs.webkit.org/show_bug.cgi?id=165511>.
291     SignatureIndex signatureIndex { Signature::invalidIndex };
292     WasmEntrypointLoadLocation code { nullptr };
293 };
294 using FunctionIndexSpace = Vector<CallableFunction>;
295
296 } } // namespace JSC::Wasm
297
298 #endif // ENABLE(WEBASSEMBLY)