Files: d42f5bf9d7ad822c5a87be84d90bd79af0f4b715 / typeCheckWrapper.js
4371 bytesRaw
1 | const {LANGUAGE_TYPES_STRG} = require('primea-annotations') |
2 | |
3 | module.exports = function (params) { |
4 | const module = [{ |
5 | 'name': 'preramble', |
6 | 'magic': [ |
7 | 0, |
8 | 97, |
9 | 115, |
10 | 109 |
11 | ], |
12 | 'version': [ |
13 | 1, |
14 | 0, |
15 | 0, |
16 | 0 |
17 | ] |
18 | }, { |
19 | 'name': 'type', |
20 | 'entries': [{ |
21 | 'form': 'func', |
22 | 'params': [ |
23 | ] |
24 | }, { |
25 | 'form': 'func', |
26 | 'params': [ |
27 | // imported check |
28 | ] |
29 | }, { |
30 | 'form': 'func', |
31 | 'params': [ |
32 | // exported check |
33 | ] |
34 | }, { |
35 | 'form': 'func', |
36 | 'params': [ |
37 | // invoke |
38 | ] |
39 | }] |
40 | }, { |
41 | 'name': 'import', |
42 | 'entries': [{ |
43 | 'moduleStr': 'env', |
44 | 'fieldStr': 'checkTypes', |
45 | 'kind': 'function', |
46 | 'type': 0 |
47 | }] |
48 | }, { |
49 | 'name': 'function', |
50 | 'entries': [ |
51 | 1, |
52 | 2 |
53 | ] |
54 | }, { |
55 | 'name': 'table', |
56 | 'entries': [{ |
57 | 'elementType': 'anyFunc', |
58 | 'limits': { |
59 | 'flags': 1, |
60 | 'intial': 1, |
61 | 'maximum': 1 |
62 | } |
63 | }] |
64 | }, { |
65 | 'name': 'global', |
66 | 'entries': [] |
67 | }, { |
68 | 'name': 'export', |
69 | 'entries': [{ |
70 | 'field_str': 'table', |
71 | 'kind': 'table', |
72 | 'index': 0 |
73 | }, { |
74 | 'field_str': 'invoke', |
75 | 'kind': 'function', |
76 | 'index': 2 |
77 | }, { |
78 | 'field_str': 'check', |
79 | 'kind': 'function', |
80 | 'index': 1 |
81 | }] |
82 | }, { |
83 | 'name': 'code', |
84 | 'entries': [{ |
85 | 'locals': [], |
86 | 'code': [] |
87 | }, { |
88 | 'locals': [], |
89 | 'code': [] |
90 | }] |
91 | }] |
92 | |
93 | const definedTypes = new Set(['anyref', 'module', 'func', 'data', 'elem', 'link', 'id']) |
94 | const setGlobals = [] |
95 | const importType = module[1].entries[0].params |
96 | const checkType = module[1].entries[1].params |
97 | const invokerType = module[1].entries[2].params |
98 | const invokeType = module[1].entries[3].params |
99 | let checkCode = module[7].entries[0].code |
100 | let invokeCode = module[7].entries[1].code |
101 | |
102 | let invokeIndex = 0 |
103 | params.forEach((param, index) => { |
104 | let baseType = param |
105 | const typeCode = LANGUAGE_TYPES_STRG[param] |
106 | // import type |
107 | if (definedTypes.has(param)) { |
108 | baseType = 'i32' |
109 | } else { |
110 | baseType = param |
111 | } |
112 | |
113 | // check import |
114 | importType.push('i32') |
115 | importType.push('i32') |
116 | checkCode.push(i32_const(typeCode)) |
117 | if (baseType === 'i64') { |
118 | importType.push('i32') |
119 | |
120 | // splits an i64 into 2 i32 |
121 | const spliti64 = [ |
122 | get_local(index), |
123 | i64_const(32), |
124 | shr_u(), |
125 | wrap_i64(), |
126 | get_local(index), |
127 | wrap_i64()] |
128 | |
129 | checkCode = checkCode.concat(spliti64) |
130 | |
131 | const i32wrapCode = [ |
132 | get_local(invokeIndex), { |
133 | 'return_type': 'i64', |
134 | 'name': 'extend_u/i32' |
135 | }, { |
136 | 'return_type': 'i64', |
137 | 'name': 'const', |
138 | 'immediates': '32' |
139 | }, { |
140 | 'return_type': 'i64', |
141 | 'name': 'shl' |
142 | }, |
143 | get_local(++invokeIndex), { |
144 | 'return_type': 'i64', |
145 | 'name': 'extend_u/i32' |
146 | }, { |
147 | 'return_type': 'i64', |
148 | 'name': 'add' |
149 | } |
150 | ] |
151 | |
152 | invokeCode = invokeCode.concat(i32wrapCode) |
153 | invokerType.push('i32') |
154 | } else { |
155 | checkCode.push(get_local(index)) |
156 | invokeCode.push(get_local(invokeIndex)) |
157 | } |
158 | invokerType.push('i32') |
159 | // check export |
160 | checkType.push(baseType) |
161 | // invoke |
162 | invokeType.push(baseType) |
163 | invokeIndex++ |
164 | }) |
165 | |
166 | module[7].entries[0].code = checkCode.concat(setGlobals, [call(0), end()]) |
167 | invokeCode.push(i32_const(0)) |
168 | invokeCode.push(call_indirect(3)) |
169 | invokeCode.push(end()) |
170 | module[7].entries[1].code = invokeCode |
171 | return module |
172 | } |
173 | |
174 | function call (index) { |
175 | return { |
176 | 'name': 'call', |
177 | 'immediates': index |
178 | } |
179 | } |
180 | |
181 | function call_indirect (index) { |
182 | return { |
183 | 'name': 'call_indirect', |
184 | 'immediates': { |
185 | 'index': index, |
186 | 'reserved': 0 |
187 | } |
188 | } |
189 | } |
190 | |
191 | function end () { |
192 | return { |
193 | name: 'end' |
194 | } |
195 | } |
196 | |
197 | function get_local (index) { |
198 | return { |
199 | name: 'get_local', |
200 | immediates: index |
201 | } |
202 | } |
203 | |
204 | function i32_const (num) { |
205 | return { |
206 | 'return_type': 'i32', |
207 | 'name': 'const', |
208 | 'immediates': num |
209 | } |
210 | } |
211 | |
212 | function i64_const (num) { |
213 | return { |
214 | 'return_type': 'i64', |
215 | 'name': 'const', |
216 | 'immediates': num |
217 | } |
218 | } |
219 | |
220 | function shr_u() { |
221 | return { |
222 | 'return_type': 'i64', |
223 | 'name': 'shr_u' |
224 | } |
225 | } |
226 | |
227 | function wrap_i64() { |
228 | return { |
229 | 'return_type': 'i32', |
230 | 'name': 'wrap/i64' |
231 | } |
232 | } |
233 |
Built with git-ssb-web