| 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90 |
21x
21x
21x
21x
42x
42x
42x
21x
42x
42x
42x
90x
90x
42x
21x
42x
42x
42x
50x
50x
50x
21x
21x
42x
21x
42x
42x
42x
42x
42x
42x
42x
42x
42x
42x
42x
42x
42x
42x
42x
| // @flow
import { varuint32, varuint7 } from '../numbers';
import { emitString } from '../string';
import OutputStream from '../../utils/output-stream';
import type { NameSectionType } from '../../generator/flow/types';
// Emit Module name subsection
const emitModuleName = (name: string): OutputStream => {
const moduleSubsection = new OutputStream();
emitString(moduleSubsection, name, `name_len: ${name}`);
return moduleSubsection;
};
// Emit Functions subsection
const emitFunctionNames = (
names: Array<{ index: number, name: string }>
): OutputStream => {
const stream = new OutputStream();
stream.push(varuint32, names.length, `count: ${String(names.length)}`);
names.forEach(({ index, name }) => {
stream.push(varuint32, index, `index: ${String(index)}`);
emitString(stream, name, `name_len: ${name}`);
});
return stream;
};
// Emit Locals subsection
const emitLocals = (
localsMap: Array<{
index: number,
locals: Array<{ index: number, name: string }>,
}>
): OutputStream => {
const stream = new OutputStream();
// WebAssembly Binary Encoding docs are not the best on how this should be encoded.
// This is pretty much lifted from wabt C++ source code. First comes the number
// or functions, where each function is a header of a u32 function index followed
// by locals + params count with each local/param encoded as a name_map
stream.push(
varuint32,
localsMap.length,
`count: ${String(localsMap.length)}`
);
localsMap.forEach(({ index: funIndex, locals }) => {
stream.push(varuint32, funIndex, `function index: ${String(funIndex)}`);
stream.push(
varuint32,
locals.length,
`number of params and locals ${locals.length}`
);
locals.forEach(({ index, name }) => {
stream.push(varuint32, index, `index: ${String(index)}`);
emitString(stream, name, `name_len: ${name}`);
});
});
return stream;
};
// Emit the Name custom section.
const emit = (nameSection: NameSectionType): OutputStream => {
const stream = new OutputStream();
// Name identifier/header as this is a custom section which requires a string id
emitString(stream, 'name', 'name_len: name');
// NOTE: Every subsection header is encoded here, not in the individual subsection
// logic.
const moduleSubsection = emitModuleName(nameSection.module);
stream.push(varuint7, 0, 'name_type: Module');
stream.push(varuint32, moduleSubsection.size, 'name_payload_len');
stream.write(moduleSubsection);
const functionSubsection = emitFunctionNames(nameSection.functions);
stream.push(varuint7, 1, 'name_type: Function');
stream.push(varuint32, functionSubsection.size, 'name_payload_len');
stream.write(functionSubsection);
const localsSubsection = emitLocals(nameSection.locals);
stream.push(varuint7, 2, 'name_type: Locals');
stream.push(varuint32, localsSubsection.size, 'name_payload_len');
stream.write(localsSubsection);
return stream;
};
export default emit;
|