WebAssembly JS API: implement Global
[WebKit-https.git] / Source / JavaScriptCore / wasm / WasmFormat.h
1 /*
2  * Copyright (C) 2015 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 "B3Compilation.h"
31 #include "B3Type.h"
32 #include "CodeLocation.h"
33 #include "Identifier.h"
34 #include "MacroAssemblerCodeRef.h"
35 #include "RegisterAtOffsetList.h"
36 #include "WasmMemoryInformation.h"
37 #include "WasmOps.h"
38 #include "WasmPageCount.h"
39 #include <memory>
40 #include <wtf/FastMalloc.h>
41 #include <wtf/Optional.h>
42 #include <wtf/Vector.h>
43
44 namespace JSC {
45
46 class JSFunction;
47
48 namespace Wasm {
49
50 inline bool isValueType(Type type)
51 {
52     switch (type) {
53     case I32:
54     case I64:
55     case F32:
56     case F64:
57         return true;
58     default:
59         break;
60     }
61     return false;
62 }
63     
64 struct External {
65     enum Kind : uint8_t {
66         // FIXME auto-generate this. https://bugs.webkit.org/show_bug.cgi?id=165231
67         Function = 0,
68         Table = 1,
69         Memory = 2,
70         Global = 3,
71     };
72     template<typename Int>
73     static bool isValid(Int val)
74     {
75         switch (val) {
76         case Function:
77         case Table:
78         case Memory:
79         case Global:
80             return true;
81         default:
82             return false;
83         }
84     }
85     
86     static_assert(Function == 0, "Wasm needs Function to have the value 0");
87     static_assert(Table    == 1, "Wasm needs Table to have the value 1");
88     static_assert(Memory   == 2, "Wasm needs Memory to have the value 2");
89     static_assert(Global   == 3, "Wasm needs Global to have the value 3");
90 };
91
92 struct Signature {
93     Type returnType;
94     Vector<Type> arguments;
95 };
96
97 struct Import {
98     Identifier module;
99     Identifier field;
100     External::Kind kind;
101     unsigned kindIndex; // Index in the vector of the corresponding kind.
102 };
103
104 struct Export {
105     Identifier field;
106     External::Kind kind;
107     unsigned kindIndex; // Index in the vector of the corresponding kind.
108 };
109
110 struct Global {
111     enum Mutability : uint8_t {
112         // FIXME auto-generate this. https://bugs.webkit.org/show_bug.cgi?id=165231
113         Mutable = 1,
114         Immutable = 0
115     };
116
117     enum InitializationType {
118         IsImport,
119         FromGlobalImport,
120         FromExpression
121     };
122
123     Mutability mutability;
124     Type type;
125     InitializationType initializationType { IsImport };
126     uint64_t initialBitsOrImportNumber { 0 };
127 };
128
129 struct FunctionLocationInBinary {
130     size_t start;
131     size_t end;
132 };
133
134 struct Segment {
135     uint32_t offset;
136     uint32_t sizeInBytes;
137     // Bytes are allocated at the end.
138     static Segment* make(uint32_t offset, uint32_t sizeInBytes)
139     {
140         auto allocated = tryFastCalloc(sizeof(Segment) + sizeInBytes, 1);
141         Segment* segment;
142         if (!allocated.getValue(segment))
143             return nullptr;
144         segment->offset = offset;
145         segment->sizeInBytes = sizeInBytes;
146         return segment;
147     }
148     static void destroy(Segment *segment)
149     {
150         fastFree(segment);
151     }
152     uint8_t& byte(uint32_t pos)
153     {
154         ASSERT(pos < sizeInBytes);
155         return *reinterpret_cast<uint8_t*>(reinterpret_cast<char*>(this) + sizeof(offset) + sizeof(sizeInBytes) + pos);
156     }
157     typedef std::unique_ptr<Segment, decltype(&Segment::destroy)> Ptr;
158     static Ptr makePtr(Segment* segment)
159     {
160         return Ptr(segment, &Segment::destroy);
161     }
162 };
163
164 struct Element {
165     uint32_t offset;
166     Vector<uint32_t> functionIndices;
167 };
168
169 class TableInformation {
170 public:
171     TableInformation()
172     {
173         ASSERT(!*this);
174     }
175
176     TableInformation(uint32_t initial, std::optional<uint32_t> maximum, bool isImport)
177         : m_initial(initial)
178         , m_maximum(maximum)
179         , m_isImport(isImport)
180         , m_isValid(true)
181     {
182         ASSERT(*this);
183     }
184
185     explicit operator bool() const { return m_isValid; }
186     bool isImport() const { return m_isImport; }
187     uint32_t initial() const { return m_initial; }
188     std::optional<uint32_t> maximum() const { return m_maximum; }
189
190 private:
191     uint32_t m_initial;
192     std::optional<uint32_t> m_maximum;
193     bool m_isImport { false };
194     bool m_isValid { false };
195 };
196
197 struct ModuleInformation {
198     Vector<Signature> signatures;
199     Vector<Import> imports;
200     Vector<Signature*> importFunctions;
201     Vector<Signature*> internalFunctionSignatures;
202     MemoryInformation memory;
203     Vector<Export> exports;
204     std::optional<uint32_t> startFunctionIndexSpace;
205     Vector<Segment::Ptr> data;
206     Vector<Element> elements;
207     TableInformation tableInformation;
208     Vector<Global> globals;
209     unsigned firstInternalGlobal { 0 };
210
211     ~ModuleInformation();
212 };
213
214 struct UnlinkedWasmToWasmCall {
215     CodeLocationCall callLocation;
216     size_t functionIndex;
217 };
218
219 struct Entrypoint {
220     std::unique_ptr<B3::Compilation> compilation;
221     RegisterAtOffsetList calleeSaveRegisters;
222 };
223
224 struct WasmInternalFunction {
225     CodeLocationDataLabelPtr wasmCalleeMoveLocation;
226     CodeLocationDataLabelPtr jsToWasmCalleeMoveLocation;
227
228     Entrypoint wasmEntrypoint;
229     Entrypoint jsToWasmEntrypoint;
230 };
231
232 typedef MacroAssemblerCodeRef WasmToJSStub;
233
234 // WebAssembly direct calls and call_indirect use indices into "function index space". This space starts with all imports, and then all internal functions.
235 // CallableFunction and FunctionIndexSpace are only meant as fast lookup tables for these opcodes, and do not own code.
236 struct CallableFunction {
237     CallableFunction() = default;
238
239     CallableFunction(Signature* signature, void* code = nullptr)
240         : signature(signature)
241         , code(code)
242     {
243     }
244
245     // FIXME pack this inside a (uniqued) integer (for correctness the parser should unique Signatures),
246     // and then pack that integer into the code pointer. https://bugs.webkit.org/show_bug.cgi?id=165511
247     Signature* signature { nullptr }; 
248     void* code { nullptr };
249 };
250 typedef Vector<CallableFunction> FunctionIndexSpace;
251
252
253 struct ImmutableFunctionIndexSpace {
254     MallocPtr<CallableFunction> buffer;
255     size_t size;
256 };
257
258 } } // namespace JSC::Wasm
259
260 #endif // ENABLE(WEBASSEMBLY)