WebAssembly: improve compilation error messages
[WebKit-https.git] / Source / JavaScriptCore / wasm / generateWasmValidateInlinesHeader.py
1 #!/usr/bin/env python
2
3 # Copyright (C) 2016 Apple Inc. All rights reserved.
4 #
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions
7 # are met:
8 #
9 # 1.  Redistributions of source code must retain the above copyright
10 #     notice, this list of conditions and the following disclaimer.
11 # 2.  Redistributions in binary form must reproduce the above copyright
12 #     notice, this list of conditions and the following disclaimer in the
13 #     documentation and/or other materials provided with the distribution.
14 #
15 # THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
16 # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 # DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
19 # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
26 # This tool has a couple of helpful macros to process Wasm files from the wasm.json.
27
28 from generateWasm import *
29 import optparse
30 import sys
31
32 parser = optparse.OptionParser(usage="usage: %prog <wasm.json> <WasmOps.h>")
33 (options, args) = parser.parse_args(sys.argv[0:])
34 if len(args) != 3:
35     parser.error(parser.usage)
36
37 wasm = Wasm(args[0], args[1])
38 opcodes = wasm.opcodes
39 wasmValidateInlinesHFile = open(args[2], "w")
40
41
42 def cppType(name):
43     result = {
44         "bool": "I32",
45         "addr": "I32",
46         "i32": "I32",
47         "i64": "I64",
48         "f32": "F32",
49         "f64": "F64",
50     }.get(name, None)
51     if result == None:
52         raise ValueError("Unknown type name: " + name)
53     return result
54
55
56 def toCpp(name):
57     return wasm.toCpp(name)
58
59
60 def unaryMacro(name):
61     op = opcodes[name]
62     return """
63 template<> auto Validate::addOp<OpType::""" + toCpp(name) + """>(ExpressionType value, ExpressionType& result) -> Result
64 {
65     if (UNLIKELY(value != """ + cppType(op["parameter"][0]) + """))
66         return UnexpectedType<Result::ErrorType>("validation failed: """ + name + """ value type mismatch");
67
68     result = """ + cppType(op["return"][0]) + """;
69     return { };
70 }
71 """
72
73
74 def binaryMacro(name):
75     op = opcodes[name]
76     return """
77 template<> auto Validate::addOp<OpType::""" + toCpp(name) + """>(ExpressionType left, ExpressionType right, ExpressionType& result) -> Result
78 {
79     if (UNLIKELY(left != """ + cppType(op["parameter"][0]) + """))
80         return UnexpectedType<Result::ErrorType>("validation failed: """ + name + """ left value type mismatch");
81
82     if (UNLIKELY(right != """ + cppType(op["parameter"][1]) + """))
83         return UnexpectedType<Result::ErrorType>("validation failed: """ + name + """ right value type mismatch");
84
85     result = """ + cppType(op["return"][0]) + """;
86     return { };
87 }
88 """
89
90 def loadMacro(name):
91     op = opcodes[name]
92     return """
93     case LoadOpType::""" + toCpp(name) + """: {
94         if (UNLIKELY(pointer != """ + cppType(op["parameter"][0]) + """))
95             return UnexpectedType<Result::ErrorType>("validation failed: """ + name + """ pointer type mismatch");
96
97         result = """ + cppType(op["return"][0]) + """;
98         return { };
99     }"""
100
101
102 def storeMacro(name):
103     op = opcodes[name]
104     return """
105     case StoreOpType::""" + toCpp(name) + """: {
106         if (UNLIKELY(pointer != """ + cppType(op["parameter"][0]) + """))
107             return UnexpectedType<Result::ErrorType>("validation failed: """ + name + """ pointer type mismatch");
108
109         if (UNLIKELY(value != """ + cppType(op["parameter"][1]) + """))
110             return UnexpectedType<Result::ErrorType>("validation failed: """ + name + """ value type mismatch");
111
112         return { };
113     }"""
114
115
116 unarySpecializations = "".join([op for op in wasm.opcodeIterator(isUnary, unaryMacro)])
117 binarySpecializations = "".join([op for op in wasm.opcodeIterator(isBinary, binaryMacro)])
118 loadCases = "".join([op for op in wasm.opcodeIterator(lambda op: op["category"] == "memory" and len(op["return"]) == 1, loadMacro)])
119 storeCases = "".join([op for op in wasm.opcodeIterator(lambda op: op["category"] == "memory" and len(op["return"]) == 0, storeMacro)])
120
121 contents = wasm.header + """
122 // This file is intended to be inlined by WasmValidate.cpp only! It should not be included elsewhere.
123
124 #pragma once
125
126 #if ENABLE(WEBASSEMBLY)
127
128 namespace JSC { namespace Wasm {
129
130 """ + unarySpecializations + binarySpecializations + """
131
132 auto Validate::load(LoadOpType op, ExpressionType pointer, ExpressionType& result, uint32_t) -> Result
133 {
134     if (UNLIKELY(!hasMemory()))
135         return UnexpectedType<Result::ErrorType>("validation failed: load instruction without memory");
136
137     switch (op) {
138 """ + loadCases + """
139     }
140 }
141
142 auto Validate::store(StoreOpType op, ExpressionType pointer, ExpressionType value, uint32_t) -> Result
143 {
144     if (UNLIKELY(!hasMemory()))
145         return UnexpectedType<Result::ErrorType>("validation failed: store instruction without memory");
146
147     switch (op) {
148 """ + storeCases + """
149     }
150 }
151
152 } } // namespace JSC::Wasm
153
154 #endif // ENABLE(WEBASSEMBLY)
155
156 """
157
158 wasmValidateInlinesHFile.write(contents)
159 wasmValidateInlinesHFile.close()