Update WASM towards 0xc
[WebKit-https.git] / Source / JavaScriptCore / wasm / WASMModuleParser.cpp
1 /*
2  * Copyright (C) 2016 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 #include "config.h"
27 #include "WASMModuleParser.h"
28
29 #if ENABLE(WEBASSEMBLY)
30
31 #include "WASMFormat.h"
32 #include "WASMOps.h"
33 #include "WASMSections.h"
34
35 namespace JSC { namespace WASM {
36
37 static const bool verbose = false;
38
39 bool ModuleParser::parse()
40 {
41     if (m_sourceLength < 8)
42         return false;
43     if (!consumeCharacter(0))
44         return false;
45     if (!consumeString("asm"))
46         return false;
47
48     // Skip the version number for now since we don't do anything with it.
49     uint32_t versionNumber;
50     if (!parseUInt32(versionNumber))
51         return false;
52
53     if (versionNumber != magicNumber)
54         return false;
55
56
57     if (verbose)
58         dataLogLn("Passed processing header.");
59
60     Sections::Section previousSection = Sections::Unknown;
61     while (m_offset < m_sourceLength) {
62         if (verbose)
63             dataLogLn("Starting to parse next section at offset: ", m_offset);
64
65         Sections::Section section = Sections::Unknown;
66         uint8_t sectionByte;
67         if (!parseUInt7(sectionByte))
68             return false;
69
70         if (sectionByte) {
71             if (sectionByte >= Sections::Unknown)
72                 section = Sections::Unknown;
73             else
74                 section = static_cast<Sections::Section>(sectionByte);
75         } else {
76             uint32_t sectionNameLength;
77             if (!parseVarUInt32(sectionNameLength))
78                 return false;
79
80             // Make sure we can read up to the section's size.
81             if (m_offset + sectionNameLength + maxLEBByteLength >= m_sourceLength)
82                 return false;
83
84             // We don't support any custom sections yet.
85
86             m_offset += sectionNameLength;
87         }
88
89         if (!Sections::validateOrder(previousSection, section))
90             return false;
91
92         uint32_t sectionLength;
93         if (!parseVarUInt32(sectionLength))
94             return false;
95
96         unsigned end = m_offset + sectionLength;
97
98         switch (section) {
99         case Sections::FunctionTypes: {
100             if (verbose)
101                 dataLogLn("Parsing types.");
102             if (!parseFunctionTypes())
103                 return false;
104             break;
105         }
106
107         case Sections::Signatures: {
108             if (verbose)
109                 dataLogLn("Parsing function signatures.");
110             if (!parseFunctionSignatures())
111                 return false;
112             break;
113         }
114
115         case Sections::Definitions: {
116             if (verbose)
117                 dataLogLn("Parsing function definitions.");
118             if (!parseFunctionDefinitions())
119                 return false;
120             break;
121         }
122
123         case Sections::Unknown:
124         // FIXME: Delete this when we support all the sections.
125         default: {
126             if (verbose)
127                 dataLogLn("Unknown section, skipping.");
128             m_offset += sectionLength;
129             break;
130         }
131         }
132
133         if (verbose)
134             dataLogLn("Finished parsing section.");
135
136         if (end != m_offset)
137             return false;
138
139         previousSection = section;
140     }
141
142     // TODO
143     return true;
144 }
145
146 bool ModuleParser::parseFunctionTypes()
147 {
148     uint32_t count;
149     if (!parseVarUInt32(count))
150         return false;
151
152     if (verbose)
153         dataLogLn("count: ", count);
154
155     m_signatures.resize(count);
156
157     for (uint32_t i = 0; i < count; ++i) {
158         uint8_t type;
159         if (!parseUInt7(type))
160             return false;
161         if (type != 0x40) // Function type constant.
162             return false;
163
164         if (verbose)
165             dataLogLn("Got function type.");
166
167         uint32_t argumentCount;
168         if (!parseVarUInt32(argumentCount))
169             return false;
170
171         if (verbose)
172             dataLogLn("argumentCount: ", argumentCount);
173
174         Vector<Type> argumentTypes;
175         argumentTypes.resize(argumentCount);
176
177         for (unsigned i = 0; i < argumentCount; ++i) {
178             if (!parseUInt7(type) || !isValueType(static_cast<Type>(type)))
179                 return false;
180             argumentTypes[i] = static_cast<Type>(type);
181         }
182
183         if (!parseVarUInt1(type))
184             return false;
185         Type returnType;
186
187         if (verbose)
188             dataLogLn(type);
189
190         if (type) {
191             Type value;
192             if (!parseValueType(value))
193                 return false;
194             returnType = static_cast<Type>(value);
195         } else
196             returnType = Type::Void;
197
198         m_signatures[i] = { returnType, WTFMove(argumentTypes) };
199     }
200     return true;
201 }
202
203 bool ModuleParser::parseFunctionSignatures()
204 {
205     uint32_t count;
206     if (!parseVarUInt32(count))
207         return false;
208
209     m_functions.resize(count);
210
211     for (uint32_t i = 0; i < count; ++i) {
212         uint32_t typeNumber;
213         if (!parseVarUInt32(typeNumber))
214             return false;
215
216         if (typeNumber >= m_signatures.size())
217             return false;
218
219         m_functions[i].signature = &m_signatures[typeNumber];
220     }
221
222     return true;
223 }
224
225 bool ModuleParser::parseFunctionDefinitions()
226 {
227     uint32_t count;
228     if (!parseVarUInt32(count))
229         return false;
230
231     if (count != m_functions.size())
232         return false;
233
234     for (uint32_t i = 0; i < count; ++i) {
235         uint32_t functionSize;
236         if (!parseVarUInt32(functionSize))
237             return false;
238
239         FunctionInformation& info = m_functions[i];
240         info.start = m_offset;
241         info.end = m_offset + functionSize;
242         m_offset = info.end;
243     }
244
245     return true;
246 }
247
248 } } // namespace JSC::WASM
249
250 #endif // ENABLE(WEBASSEMBLY)