WebAssembly: implement data section
[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 "WasmMemoryInformation.h"
36 #include "WasmOps.h"
37 #include "WasmPageCount.h"
38 #include <memory>
39 #include <wtf/FastMalloc.h>
40 #include <wtf/Optional.h>
41 #include <wtf/Vector.h>
42
43 namespace JSC {
44
45 class JSFunction;
46
47 namespace Wasm {
48
49 inline bool isValueType(Type type)
50 {
51     switch (type) {
52     case I32:
53     case I64:
54     case F32:
55     case F64:
56         return true;
57     default:
58         break;
59     }
60     return false;
61 }
62     
63 struct External {
64     enum Kind : uint8_t {
65         // FIXME auto-generate this. https://bugs.webkit.org/show_bug.cgi?id=165231
66         Function = 0,
67         Table = 1,
68         Memory = 2,
69         Global = 3,
70     };
71     template<typename Int>
72     static bool isValid(Int val)
73     {
74         switch (val) {
75         case Function:
76         case Table:
77         case Memory:
78         case Global:
79             return true;
80         default:
81             return false;
82         }
83     }
84     
85     static_assert(Function == 0, "Wasm needs Function to have the value 0");
86     static_assert(Table    == 1, "Wasm needs Table to have the value 1");
87     static_assert(Memory   == 2, "Wasm needs Memory to have the value 2");
88     static_assert(Global   == 3, "Wasm needs Global to have the value 3");
89 };
90
91 struct Signature {
92     Type returnType;
93     Vector<Type> arguments;
94 };
95     
96 struct Import {
97     Identifier module;
98     Identifier field;
99     External::Kind kind;
100     unsigned kindIndex; // Index in the vector of the corresponding kind.
101 };
102
103 struct Export {
104     Identifier field;
105     External::Kind kind;
106     union {
107         uint32_t functionIndex;
108         // FIXME implement Table https://bugs.webkit.org/show_bug.cgi?id=164135
109         // FIXME implement Memory https://bugs.webkit.org/show_bug.cgi?id=165671
110         // FIXME implement Global https://bugs.webkit.org/show_bug.cgi?id=164133
111     };
112 };
113
114 struct FunctionLocationInBinary {
115     size_t start;
116     size_t end;
117 };
118
119 struct Segment {
120     uint32_t offset;
121     uint32_t sizeInBytes;
122     // Bytes are allocated at the end.
123     static Segment* make(uint32_t offset, uint32_t sizeInBytes)
124     {
125         auto allocated = tryFastCalloc(sizeof(Segment) + sizeInBytes, 1);
126         Segment* segment;
127         if (!allocated.getValue(segment))
128             return nullptr;
129         segment->offset = offset;
130         segment->sizeInBytes = sizeInBytes;
131         return segment;
132     }
133     static void destroy(Segment *segment)
134     {
135         fastFree(segment);
136     }
137     uint8_t& byte(uint32_t pos)
138     {
139         ASSERT(pos < sizeInBytes);
140         return *reinterpret_cast<uint8_t*>(reinterpret_cast<char*>(this) + sizeof(offset) + sizeof(sizeInBytes) + pos);
141     }
142     typedef std::unique_ptr<Segment, decltype(&Segment::destroy)> Ptr;
143     static Ptr makePtr(Segment* segment)
144     {
145         return Ptr(segment, &Segment::destroy);
146     }
147 };
148
149 struct ModuleInformation {
150     Vector<Signature> signatures;
151     Vector<Import> imports;
152     Vector<Signature*> importFunctions;
153     // FIXME implement import Table https://bugs.webkit.org/show_bug.cgi?id=164135
154     // FIXME implement import Global https://bugs.webkit.org/show_bug.cgi?id=164133
155     Vector<Signature*> internalFunctionSignatures;
156     MemoryInformation memory;
157     Vector<Export> exports;
158     std::optional<uint32_t> startFunctionIndexSpace;
159     Vector<Segment::Ptr> data;
160
161     ~ModuleInformation();
162 };
163
164 struct UnlinkedWasmToWasmCall {
165     CodeLocationCall callLocation;
166     size_t functionIndex;
167 };
168
169 struct WasmInternalFunction {
170     CodeLocationDataLabelPtr calleeMoveLocation;
171     std::unique_ptr<B3::Compilation> code;
172     std::unique_ptr<B3::Compilation> jsToWasmEntryPoint;
173 };
174
175 typedef MacroAssemblerCodeRef WasmToJSStub;
176
177 // WebAssembly direct calls and call_indirect use indices into "function index space". This space starts with all imports, and then all internal functions.
178 // CallableFunction and FunctionIndexSpace are only meant as fast lookup tables for these opcodes, and do not own code.
179 struct CallableFunction {
180     CallableFunction(Signature* signature)
181         : signature(signature)
182         , code(nullptr)
183     {
184     }
185     Signature* signature; // FIXME pack this inside a (uniqued) integer (for correctness the parser should unique Signatures), and then pack that integer into the code pointer. https://bugs.webkit.org/show_bug.cgi?id=165511
186     void* code;
187 };
188 typedef Vector<CallableFunction> FunctionIndexSpace;
189
190 } } // namespace JSC::Wasm
191
192 #endif // ENABLE(WEBASSEMBLY)