git ssb

0+

wanderer🌟 / wasm-persist



Tree: 75864bd5ab5d242349cbe42dcc37db22b686e9c5

Files: 75864bd5ab5d242349cbe42dcc37db22b686e9c5 / injectGettersSetters.js

6737 bytesRaw
1const leb128 = require('leb128').unsigned
2const Pipe = require('buffer-pipe')
3const {Iterator, json2wasm} = require('wasm-json-toolkit')
4
5const EXTERNAL_KIND = json2wasm.EXTERNAL_KIND
6
7module.exports = function prepare (wasm, include, symbol) {
8 let globalI64SetterIndex, globalI32SetterIndex, globalGetterIndex, funcSection
9 let numOfFuncs = 0
10 let numOfImports = 0
11 const addedCodeEntries = []
12 const globalsGetterSetters = []
13
14 const needExporting = {
15 'function': [],
16 'global': []
17 }
18
19 const it = new Iterator(wasm)
20
21 for (const section of it) {
22 if (section.type === 'type') {
23 const numOfTypes = section.count
24 // form: func, 1 param, i32, no return
25 const globalI32SetterType = Buffer.from([0x60, 0x01, 0x7f, 0x0])
26 // form: func, 2 param, i32, i32, no return
27 const globalI64SetterType = Buffer.from([0x60, 0x02, 0x7f, 0x7f, 0x0])
28 // form: func, 0 param, i32, 1 return
29 const globalGetterType = Buffer.from([0x60, 0x00, 0x1, 0x7f])
30 section.appendEntries([globalI32SetterType, globalI64SetterType, globalGetterType])
31
32 globalI32SetterIndex = leb128.encode(numOfTypes)
33 globalI64SetterIndex = leb128.encode(numOfTypes + 1)
34 globalGetterIndex = leb128.encode(numOfTypes + 2)
35 } else if (section.type === 'import') {
36 // parse the import section to build the function indexes
37 const json = section.toJSON()
38 numOfImports = json.entries.filter(entry => entry.kind === 'function').length
39 } else if (section.type === 'function') {
40 // mark functions to be exported
41 numOfFuncs = section.count
42 funcSection = section
43 needExporting['function'] = Array(section.count).fill(true)
44 } else if (section.type === 'table') {
45 needExporting['table'] = true && include.table
46 } else if (section.type === 'memory') {
47 needExporting['memory'] = true && include.memory
48 } else if (section.type === 'global') {
49 const json = section.toJSON()
50 const addedFuncs = []
51 if (!include.globals) {
52 include.globals = new Array(json.entries.length).fill(true)
53 }
54 for (const i in json.entries) {
55 const type = json.entries[i].type
56 const lebIndex = leb128.encode(i)
57 if (type.mutability && include.globals[i]) {
58 if (type.contentType === 'i32') {
59 globalsGetterSetters.push(type.contentType)
60 addedFuncs.push(globalGetterIndex)
61 addedFuncs.push(globalI32SetterIndex)
62 // getter
63 // size, local count, get_global, index, end
64 addedCodeEntries.push(Buffer.concat([
65 Buffer.from([0x03 + lebIndex.length, 0x00, 0x23]),
66 lebIndex,
67 Buffer.from([0x0b])
68 ]))
69 // setter
70 // size, local count, get_local, index , set_global, index, end
71 addedCodeEntries.push(Buffer.concat([
72 Buffer.from([0x05 + lebIndex.length, 0x00, 0x20, 0x0, 0x24]),
73 lebIndex,
74 Buffer.from([0x0b])
75 ]))
76 } else {
77 globalsGetterSetters.push(type.contentType)
78 addedFuncs.push(globalGetterIndex)
79 addedFuncs.push(globalGetterIndex)
80 addedFuncs.push(globalI64SetterIndex)
81 // 64 bit
82 // getter high
83 addedCodeEntries.push(Buffer.concat([
84 Buffer.from([0x07 + lebIndex.length, 0x00, 0x23]),
85 lebIndex,
86 Buffer.from([0x42, 0x20, 0x88, 0xa7, 0x0b])
87 ]))
88
89 // get low
90 addedCodeEntries.push(Buffer.concat([
91 Buffer.from([0x04 + lebIndex.length, 0x00, 0x23]),
92 lebIndex,
93 Buffer.from([0xa7, 0x0b])
94 ]))
95 // (set_global $b
96 // (i64.add
97 // (i64.shl (i64.extend_u/i32 (get_local 0)) (i64.const 32))
98 // (i64.extend_u/i32 (get_local 1))))
99 // setter
100 addedCodeEntries.push(Buffer.concat([
101 Buffer.from([0x0d + lebIndex.length, 0x00, 0x20, 0x01, 0xad, 0x42, 0x20, 0x86, 0x20, 0x00, 0xad, 0x7c, 0x24]),
102 lebIndex,
103 Buffer.from([0x0b])
104 ]))
105 }
106 }
107 }
108 funcSection.appendEntries(addedFuncs)
109 } else if (section.type === 'export') {
110 // export the memory
111 const addedExports = []
112 if (needExporting['memory']) {
113 const funcExp = generateFuncExport(`${symbol}memory`, 0, 'memory')
114 addedExports.push(funcExp)
115 }
116
117 // export the table
118 if (needExporting['table']) {
119 const funcExp = generateFuncExport(`${symbol}table`, 0, 'table')
120 addedExports.push(funcExp)
121 }
122
123 // export functions
124 const funcs = needExporting['function']
125 for (let index in funcs) {
126 index = Number(index)
127 const funcExp = generateFuncExport(`${symbol}func_${index + numOfImports}`, numOfImports + index, 'function')
128 addedExports.push(funcExp)
129 }
130
131 // export globals
132 let globalFuncIndex = 0
133 for (let index in globalsGetterSetters) {
134 const type = globalsGetterSetters[index]
135 const funcIndex = numOfImports + numOfFuncs + globalFuncIndex
136 if (type === 'i32') {
137 // getter
138 const getter = generateFuncExport(`${symbol}global_getter_${type}_${index}`, funcIndex, 'function')
139 addedExports.push(getter)
140
141 // setter
142 const setter = generateFuncExport(`${symbol}global_setter_${type}_${index}`, funcIndex + 1, 'function')
143 addedExports.push(setter)
144 globalFuncIndex += 2
145 } else {
146 // i64s
147 // setter high
148 const setterHigh = generateFuncExport(`${symbol}global_getter_${type}_${index}_high`, funcIndex, 'function')
149 addedExports.push(setterHigh)
150 // setter Low
151 const setterLow = generateFuncExport(`${symbol}global_getter_${type}_${index}_low`, funcIndex + 1, 'function')
152 addedExports.push(setterLow)
153 // getter
154 const getter = generateFuncExport(`${symbol}global_setter_${type}_${index}`, funcIndex + 2, 'function')
155 addedExports.push(getter)
156 globalFuncIndex += 3
157 }
158 }
159 section.appendEntries(addedExports)
160 } else if (section.type === 'code') {
161 section.appendEntries(addedCodeEntries)
162 }
163 }
164 return it.wasm
165}
166
167function generateFuncExport (name, index, type) {
168 const setterHigh = new Pipe()
169 const fieldString = Buffer.from(name)
170 leb128.write(fieldString.length, setterHigh)
171 setterHigh.write(fieldString)
172 setterHigh.write(Buffer.from([EXTERNAL_KIND[type]]))
173 leb128.write(index, setterHigh)
174 return setterHigh.buffer
175}
176

Built with git-ssb-web