nirguna 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ChangeLog +846 -0
- package/README.md +140 -0
- package/bin/ishvara.js +174 -0
- package/lib/ishvara.js +29 -0
- package/package.json +111 -0
- package/packages/compiler-fasm/compiler.js +75 -0
- package/packages/compiler-wasm/compiler.js +62 -0
- package/packages/operator-wasm/index.js +55 -0
- package/packages/optimizer-fasm/optimizer.js +15 -0
- package/packages/optimizer-wasm/optimizer.js +13 -0
- package/packages/printer-fasm/printer/printer.js +30 -0
- package/packages/printer-fasm/printer/visitors/assignment-expression.js +47 -0
- package/packages/printer-fasm/printer/visitors/block-statement.js +7 -0
- package/packages/printer-fasm/printer/visitors/call-expression.js +56 -0
- package/packages/printer-fasm/printer/visitors/expression-statement/expression-statement.js +34 -0
- package/packages/printer-fasm/printer/visitors/expression-statement/print-in-out.js +37 -0
- package/packages/printer-fasm/printer/visitors/expression-statement/print-jmp-far.js +30 -0
- package/packages/printer-fasm/printer/visitors/labeled-statement.js +14 -0
- package/packages/printer-fasm/printer/visitors/member-expression.js +5 -0
- package/packages/printer-fasm/printer/visitors/sequence-expression.js +17 -0
- package/packages/printer-fasm/printer/visitors/string-literal.js +55 -0
- package/packages/printer-fasm/printer/visitors/tagged-template-expression.js +4 -0
- package/packages/printer-fasm/printer.js +7 -0
- package/packages/printer-wasm/printer/maybe-type-annotation.js +15 -0
- package/packages/printer-wasm/printer/params.js +72 -0
- package/packages/printer-wasm/printer/printer.js +32 -0
- package/packages/printer-wasm/printer/visitors/block-statement.js +33 -0
- package/packages/printer-wasm/printer/visitors/call-expression/call-expression.js +53 -0
- package/packages/printer-wasm/printer/visitors/call-expression/is-wasm-type.js +6 -0
- package/packages/printer-wasm/printer/visitors/export-named-declaration.js +3 -0
- package/packages/printer-wasm/printer/visitors/expression-statement/expression-statement.js +38 -0
- package/packages/printer-wasm/printer/visitors/expression-statement/print-wasm-import.js +81 -0
- package/packages/printer-wasm/printer/visitors/expression-statement/print-wasm-memory.js +31 -0
- package/packages/printer-wasm/printer/visitors/function-declaration.js +91 -0
- package/packages/printer-wasm/printer/visitors/identifier.js +11 -0
- package/packages/printer-wasm/printer/visitors/if-statement.js +128 -0
- package/packages/printer-wasm/printer/visitors/program.js +26 -0
- package/packages/printer-wasm/printer/visitors/return.js +16 -0
- package/packages/printer-wasm/printer.js +10 -0
- package/packages/test-wasm/test.js +45 -0
- package/packages/transformer-fasm/transformer.js +70 -0
- package/packages/transformer-wasm/transformer.js +20 -0
- package/packages/translator-fasm/dump.js +68 -0
- package/packages/translator-fasm/translator.js +15 -0
- package/packages/translator-wasm/translator.js +51 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import {types} from '@putout/babel';
|
|
2
|
+
|
|
3
|
+
const {isCallExpression} = types;
|
|
4
|
+
|
|
5
|
+
export const isWastMemory = (expression) => {
|
|
6
|
+
if (!isCallExpression(expression))
|
|
7
|
+
return;
|
|
8
|
+
|
|
9
|
+
const {name} = expression.node.callee;
|
|
10
|
+
|
|
11
|
+
return name === '__ishvara_wasm_memory';
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export function printWasmMemory(path, printer) {
|
|
15
|
+
const {print} = printer;
|
|
16
|
+
const [first, second] = path.get('arguments');
|
|
17
|
+
|
|
18
|
+
print('(memory ');
|
|
19
|
+
|
|
20
|
+
if (!second) {
|
|
21
|
+
print(first);
|
|
22
|
+
} else {
|
|
23
|
+
print('(export ');
|
|
24
|
+
print(first);
|
|
25
|
+
print(')');
|
|
26
|
+
print.space();
|
|
27
|
+
print(second);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
print(')');
|
|
31
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import {types} from '@putout/babel';
|
|
2
|
+
import {isNext, isNextParent} from '@putout/printer/is';
|
|
3
|
+
import {printParams} from '../params.js';
|
|
4
|
+
|
|
5
|
+
const {
|
|
6
|
+
isAssignmentExpression,
|
|
7
|
+
isTSModuleBlock,
|
|
8
|
+
isBlockStatement,
|
|
9
|
+
isExpressionStatement,
|
|
10
|
+
isFunctionDeclaration,
|
|
11
|
+
} = types;
|
|
12
|
+
|
|
13
|
+
export const FunctionDeclaration = {
|
|
14
|
+
print(path, printer, semantics) {
|
|
15
|
+
const {print} = printer;
|
|
16
|
+
const {generator, returnType} = path.node;
|
|
17
|
+
|
|
18
|
+
print('(');
|
|
19
|
+
print('func');
|
|
20
|
+
|
|
21
|
+
if (!generator) {
|
|
22
|
+
print(' ');
|
|
23
|
+
} else {
|
|
24
|
+
print('*');
|
|
25
|
+
print.space();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
print('$');
|
|
29
|
+
print('__id');
|
|
30
|
+
|
|
31
|
+
if (path.parentPath.isExportNamedDeclaration()) {
|
|
32
|
+
print(' ');
|
|
33
|
+
print('(');
|
|
34
|
+
print('export ');
|
|
35
|
+
print('"');
|
|
36
|
+
print('__id');
|
|
37
|
+
print('"');
|
|
38
|
+
print(')');
|
|
39
|
+
print(' ');
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
printParams(path, printer, semantics, {
|
|
43
|
+
braceOpen: '(param ',
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
if (returnType) {
|
|
47
|
+
print.space();
|
|
48
|
+
print('(');
|
|
49
|
+
print('result ');
|
|
50
|
+
print('__returnType');
|
|
51
|
+
print(')');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
print('__body');
|
|
55
|
+
print(')');
|
|
56
|
+
},
|
|
57
|
+
afterSatisfy: () => [isNext, isNextParent, isInsideBlockStatement],
|
|
58
|
+
after(path, {indent, write}) {
|
|
59
|
+
if (isNextAssign(path) || isNextFunction(path) || isNext(path))
|
|
60
|
+
indent();
|
|
61
|
+
|
|
62
|
+
write.breakline();
|
|
63
|
+
//maybe.write.newline(notInsideExportDefaultWithBody(path));
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const isNextFunction = (path) => {
|
|
68
|
+
const next = path.getNextSibling();
|
|
69
|
+
return isFunctionDeclaration(next);
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const isNextAssign = (path) => {
|
|
73
|
+
const next = path.getNextSibling();
|
|
74
|
+
|
|
75
|
+
if (!isExpressionStatement(next))
|
|
76
|
+
return false;
|
|
77
|
+
|
|
78
|
+
return isAssignmentExpression(next.node.expression);
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
function isInsideBlockStatement(path) {
|
|
82
|
+
const {parentPath} = path;
|
|
83
|
+
|
|
84
|
+
if (isTSModuleBlock(parentPath.parentPath))
|
|
85
|
+
return true;
|
|
86
|
+
|
|
87
|
+
if (!isBlockStatement(parentPath))
|
|
88
|
+
return false;
|
|
89
|
+
|
|
90
|
+
return !path.node.body.body.length;
|
|
91
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import {maybeTypeAnnotation} from '../maybe-type-annotation.js';
|
|
2
|
+
|
|
3
|
+
export const Identifier = maybeTypeAnnotation((path, printer) => {
|
|
4
|
+
const {write, maybe} = printer;
|
|
5
|
+
|
|
6
|
+
const {node} = path;
|
|
7
|
+
const {name, optional} = node;
|
|
8
|
+
|
|
9
|
+
write(name);
|
|
10
|
+
maybe.write(optional, '?');
|
|
11
|
+
});
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import {types} from '@putout/babel';
|
|
2
|
+
import {exists, isInsideIf} from '@putout/printer/is';
|
|
3
|
+
|
|
4
|
+
const {
|
|
5
|
+
isBlockStatement,
|
|
6
|
+
isFunctionDeclaration,
|
|
7
|
+
isStatement,
|
|
8
|
+
isReturnStatement,
|
|
9
|
+
} = types;
|
|
10
|
+
|
|
11
|
+
const isTopLevel = ({parentPath}) => parentPath.parentPath.isProgram();
|
|
12
|
+
|
|
13
|
+
const isInsideNestedBody = ({parentPath}) => {
|
|
14
|
+
if (parentPath.type !== 'BlockStatement')
|
|
15
|
+
return false;
|
|
16
|
+
|
|
17
|
+
return parentPath.parentPath.type === 'BlockStatement';
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const isEmptyBody = (path) => !path.node.body.length;
|
|
21
|
+
|
|
22
|
+
const isLastEmptyInsideBody = (path) => {
|
|
23
|
+
const {parentPath} = path;
|
|
24
|
+
|
|
25
|
+
if (!isBlockStatement(parentPath))
|
|
26
|
+
return false;
|
|
27
|
+
|
|
28
|
+
if (!isBlockStatement(path.node.consequent))
|
|
29
|
+
return false;
|
|
30
|
+
|
|
31
|
+
if (path.node.consequent.body.length)
|
|
32
|
+
return false;
|
|
33
|
+
|
|
34
|
+
return isFunctionDeclaration(path.parentPath.parentPath);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export const IfStatement = (path, {indent, print, maybe, write, traverse}) => {
|
|
38
|
+
const {parentPath} = path;
|
|
39
|
+
const partOfAlternate = parentPath.get('alternate');
|
|
40
|
+
|
|
41
|
+
if (path !== partOfAlternate)
|
|
42
|
+
indent();
|
|
43
|
+
|
|
44
|
+
print('(if');
|
|
45
|
+
|
|
46
|
+
if (path.node.test.typeArguments) {
|
|
47
|
+
print.space();
|
|
48
|
+
print('(result ');
|
|
49
|
+
print(path.get('test.typeArguments.params.0.typeName'));
|
|
50
|
+
print(')');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
indent.inc();
|
|
54
|
+
print.breakline();
|
|
55
|
+
|
|
56
|
+
print('__test');
|
|
57
|
+
print.breakline();
|
|
58
|
+
print('(then');
|
|
59
|
+
|
|
60
|
+
const consequent = path.get('consequent');
|
|
61
|
+
const alternate = path.get('alternate');
|
|
62
|
+
const isConsequentBlock = consequent.isBlockStatement();
|
|
63
|
+
const isVar = consequent.isVariableDeclaration();
|
|
64
|
+
|
|
65
|
+
if (isConsequentBlock) {
|
|
66
|
+
print.space();
|
|
67
|
+
print(consequent);
|
|
68
|
+
|
|
69
|
+
if (isInsideIf(path.parentPath) || isInsideNestedBody(path))
|
|
70
|
+
maybe.print.newline(isEmptyBody(consequent));
|
|
71
|
+
} else {
|
|
72
|
+
const isRet = isReturnStatement(consequent);
|
|
73
|
+
print.newline();
|
|
74
|
+
indent.inc();
|
|
75
|
+
maybe.indent(!isRet);
|
|
76
|
+
print(consequent);
|
|
77
|
+
indent.dec();
|
|
78
|
+
maybe.print.newline(!isRet);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
indent();
|
|
82
|
+
print(')');
|
|
83
|
+
print.newline();
|
|
84
|
+
|
|
85
|
+
if (alternate.isBlockStatement()) {
|
|
86
|
+
write.space();
|
|
87
|
+
write('(else');
|
|
88
|
+
write.space();
|
|
89
|
+
traverse(alternate);
|
|
90
|
+
} else if (alternate.isIfStatement()) {
|
|
91
|
+
if (alternate.get('consequent').isBlockStatement())
|
|
92
|
+
write.space();
|
|
93
|
+
else
|
|
94
|
+
indent();
|
|
95
|
+
|
|
96
|
+
write('(else ');
|
|
97
|
+
traverse(alternate);
|
|
98
|
+
} else if (exists(alternate)) {
|
|
99
|
+
maybe.write.newline(isVar);
|
|
100
|
+
maybe.indent(!isConsequentBlock);
|
|
101
|
+
maybe.write.space(isConsequentBlock);
|
|
102
|
+
write('(else');
|
|
103
|
+
write.splitter();
|
|
104
|
+
indent.inc();
|
|
105
|
+
|
|
106
|
+
const isRet = isReturnStatement(alternate);
|
|
107
|
+
maybe.indent(!isRet);
|
|
108
|
+
traverse(alternate);
|
|
109
|
+
maybe.write.newline(!isRet);
|
|
110
|
+
indent.dec();
|
|
111
|
+
indent();
|
|
112
|
+
write(')');
|
|
113
|
+
write.newline();
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const nextPath = path.parentPath.getNextSibling();
|
|
117
|
+
|
|
118
|
+
if (path === partOfAlternate && !isTopLevel(path) && !isStatement(nextPath))
|
|
119
|
+
print.newline();
|
|
120
|
+
|
|
121
|
+
if (isLastEmptyInsideBody(path))
|
|
122
|
+
print.newline();
|
|
123
|
+
|
|
124
|
+
indent.dec();
|
|
125
|
+
indent();
|
|
126
|
+
print(')');
|
|
127
|
+
print.newline();
|
|
128
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import {hasCoupleTrailingComments} from '@putout/printer/is';
|
|
2
|
+
|
|
3
|
+
export const Program = (path, printer) => {
|
|
4
|
+
const {body} = path.node;
|
|
5
|
+
const {
|
|
6
|
+
traverse,
|
|
7
|
+
write,
|
|
8
|
+
indent,
|
|
9
|
+
} = printer;
|
|
10
|
+
|
|
11
|
+
traverse(path.get('interpreter'));
|
|
12
|
+
write('(');
|
|
13
|
+
write('module');
|
|
14
|
+
indent.inc();
|
|
15
|
+
write.breakline();
|
|
16
|
+
|
|
17
|
+
path.get('body').forEach(traverse);
|
|
18
|
+
indent.dec();
|
|
19
|
+
write.newline();
|
|
20
|
+
write(')');
|
|
21
|
+
|
|
22
|
+
if (body.length && hasCoupleTrailingComments(body.at(-1)))
|
|
23
|
+
return;
|
|
24
|
+
|
|
25
|
+
write.endOfFile();
|
|
26
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export const ReturnStatement = (path, printer) => {
|
|
2
|
+
const {
|
|
3
|
+
indent,
|
|
4
|
+
print,
|
|
5
|
+
maybe,
|
|
6
|
+
} = printer;
|
|
7
|
+
|
|
8
|
+
indent();
|
|
9
|
+
print('(');
|
|
10
|
+
print('return');
|
|
11
|
+
maybe.print.space(path.node.argument);
|
|
12
|
+
|
|
13
|
+
print('__argument');
|
|
14
|
+
print(')');
|
|
15
|
+
print.newline();
|
|
16
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
const {entries} = Object;
|
|
2
|
+
|
|
3
|
+
export const prepare = (wast) => {
|
|
4
|
+
const result = {};
|
|
5
|
+
let stack = [];
|
|
6
|
+
let imports = [];
|
|
7
|
+
|
|
8
|
+
for (const [name, value] of entries(wast)) {
|
|
9
|
+
if (name === 'stack') {
|
|
10
|
+
stack = value;
|
|
11
|
+
continue;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (name === 'imports') {
|
|
15
|
+
imports = value;
|
|
16
|
+
continue;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
result[name] = (...args) => {
|
|
20
|
+
value(...args);
|
|
21
|
+
|
|
22
|
+
return stack[0];
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
result.declareImport = (module, name, override) => {
|
|
27
|
+
for (const [i, [currentModule, currentName]] of imports.entries()) {
|
|
28
|
+
if (module === currentModule && name === currentName) {
|
|
29
|
+
imports[i].push(override);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
result.undeclareImport = (module, name) => {
|
|
36
|
+
for (const [i, [currentModule, currentName]] of imports.entries()) {
|
|
37
|
+
if (module === currentModule && name === currentName) {
|
|
38
|
+
imports[i].pop();
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
return result;
|
|
45
|
+
};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import {readFileSync as _readFileSync} from 'node:fs';
|
|
2
|
+
import putout from 'putout';
|
|
3
|
+
import * as removeUselessOperand from '@putout/plugin-remove-useless-operand';
|
|
4
|
+
import * as removeNestedBlocks from '@putout/plugin-remove-nested-blocks';
|
|
5
|
+
import * as fasm from '@nirguna/plugin-fasm';
|
|
6
|
+
import * as ishvara from '@nirguna/plugin-ishvara';
|
|
7
|
+
import * as bundler from '@nirguna/plugin-bandler-fasm';
|
|
8
|
+
|
|
9
|
+
const defaultConfig = {
|
|
10
|
+
rules: {},
|
|
11
|
+
plugins: [],
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const parseConfig = (config) => ({
|
|
15
|
+
...defaultConfig,
|
|
16
|
+
...config,
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
export const transform = (source, config) => {
|
|
20
|
+
const {
|
|
21
|
+
debug,
|
|
22
|
+
plugins,
|
|
23
|
+
rules,
|
|
24
|
+
readFileSync = _readFileSync,
|
|
25
|
+
} = parseConfig(config);
|
|
26
|
+
|
|
27
|
+
const variables = [];
|
|
28
|
+
const functions = [];
|
|
29
|
+
|
|
30
|
+
const {code: bundled} = putout(source, {
|
|
31
|
+
isTS: true,
|
|
32
|
+
rules: {
|
|
33
|
+
'ishvara/bundler-fasm/apply-debug': ['on', {
|
|
34
|
+
debug,
|
|
35
|
+
count: 0,
|
|
36
|
+
variables,
|
|
37
|
+
functions,
|
|
38
|
+
}],
|
|
39
|
+
'ishvara/bundler-fasm/replace-section-data-with-let': ['on', {
|
|
40
|
+
variables,
|
|
41
|
+
}],
|
|
42
|
+
'ishvara/bundler-fasm/replace-section-code-with-functions': ['on', {
|
|
43
|
+
functions,
|
|
44
|
+
}],
|
|
45
|
+
},
|
|
46
|
+
plugins: [
|
|
47
|
+
['ishvara/bundler-fasm', bundler],
|
|
48
|
+
],
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
const {code, places} = putout(bundled, {
|
|
52
|
+
fixCount: 5,
|
|
53
|
+
isTS: true,
|
|
54
|
+
rules: {
|
|
55
|
+
...rules,
|
|
56
|
+
'ishvara/fasm/apply-include': ['on', {
|
|
57
|
+
readFileSync,
|
|
58
|
+
}],
|
|
59
|
+
},
|
|
60
|
+
plugins: [
|
|
61
|
+
...plugins,
|
|
62
|
+
['remove-useless-operand', removeUselessOperand],
|
|
63
|
+
['remove-nested-blocks', removeNestedBlocks],
|
|
64
|
+
['ishvara/ishvara', ishvara],
|
|
65
|
+
['ishvara/fasm', fasm],
|
|
66
|
+
],
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
return [code, places];
|
|
70
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import putout from 'putout';
|
|
2
|
+
import * as removeNestedBlocks from '@putout/plugin-remove-nested-blocks';
|
|
3
|
+
import * as esm from '@putout/plugin-esm';
|
|
4
|
+
import * as ishvara from '@nirguna/plugin-ishvara';
|
|
5
|
+
import * as wasm from '@nirguna/plugin-wasm';
|
|
6
|
+
|
|
7
|
+
export const transform = (source) => {
|
|
8
|
+
const {code, places} = putout(source, {
|
|
9
|
+
fix: true,
|
|
10
|
+
isTS: true,
|
|
11
|
+
plugins: [
|
|
12
|
+
['ishvara/wasm', wasm],
|
|
13
|
+
['ishvara/ishvara', ishvara],
|
|
14
|
+
['esm', esm],
|
|
15
|
+
['remove-nested-blocks', removeNestedBlocks],
|
|
16
|
+
],
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
return [code, places];
|
|
20
|
+
};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Decoder,
|
|
3
|
+
DecoderOptions,
|
|
4
|
+
Formatter,
|
|
5
|
+
FormatterSyntax,
|
|
6
|
+
} from 'iced-x86';
|
|
7
|
+
|
|
8
|
+
function parseBitness(source) {
|
|
9
|
+
if (source.startsWith('use32'))
|
|
10
|
+
return 32;
|
|
11
|
+
|
|
12
|
+
return 16;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const dump = (source, binary) => {
|
|
16
|
+
const exampleRip = 0x0000000000007c00n;
|
|
17
|
+
const hexBytesColumnByteLength = 10;
|
|
18
|
+
const bitness = parseBitness(source);
|
|
19
|
+
|
|
20
|
+
const decoder = new Decoder(bitness, binary, DecoderOptions.None);
|
|
21
|
+
|
|
22
|
+
decoder.ip = exampleRip;
|
|
23
|
+
// This decodes all bytes. There's also `decode()` which decodes the next instruction,
|
|
24
|
+
// `decodeInstructions(count)` which decodes `count` instructions and `decodeOut(instruction)`
|
|
25
|
+
// which overwrites an existing instruction.
|
|
26
|
+
const instructions = decoder.decodeAll();
|
|
27
|
+
|
|
28
|
+
// Create a nasm formatter. It supports: Masm, Nasm, Gas (AT&T) and Intel (XED).
|
|
29
|
+
// There's also `FastFormatter` which uses less code (smaller wasm files).
|
|
30
|
+
// const formatter = new FastFormatter();
|
|
31
|
+
const formatter = new Formatter(FormatterSyntax.Intel);
|
|
32
|
+
|
|
33
|
+
// Change some options, there are many more
|
|
34
|
+
formatter.digitSeparator = '`';
|
|
35
|
+
formatter.firstOperandCharIndex = 10;
|
|
36
|
+
// Format the instructions
|
|
37
|
+
|
|
38
|
+
const output = instructions.map((instruction) => {
|
|
39
|
+
// Eg. "00007FFAC46ACDB2 488DAC2400FFFFFF lea rbp,[rsp-100h]"
|
|
40
|
+
let line = instruction.ip.toString(16);
|
|
41
|
+
|
|
42
|
+
line += ' ';
|
|
43
|
+
const startIndex = Number(instruction.ip - exampleRip);
|
|
44
|
+
|
|
45
|
+
for (const b of binary.slice(startIndex, startIndex + instruction.length)) {
|
|
46
|
+
line += ('0' + b.toString(16))
|
|
47
|
+
.substr(-2)
|
|
48
|
+
.toUpperCase();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
for (let i = instruction.length; i < hexBytesColumnByteLength; i++)
|
|
52
|
+
line += ' ';
|
|
53
|
+
|
|
54
|
+
line += ' ';
|
|
55
|
+
line += formatter.format(instruction);
|
|
56
|
+
|
|
57
|
+
return line;
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// Free wasm memory
|
|
61
|
+
for (const instruction of instructions)
|
|
62
|
+
instruction.free();
|
|
63
|
+
|
|
64
|
+
formatter.free();
|
|
65
|
+
decoder.free();
|
|
66
|
+
|
|
67
|
+
return output.join('\n');
|
|
68
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import * as fasm from 'fasm.js';
|
|
2
|
+
import {dump} from './dump.js';
|
|
3
|
+
|
|
4
|
+
export const translate = async (source, options = {}) => {
|
|
5
|
+
const {type} = options;
|
|
6
|
+
const [binary, places] = await fasm.translate(source);
|
|
7
|
+
|
|
8
|
+
if (type === 'dump')
|
|
9
|
+
return [
|
|
10
|
+
dump(source, binary),
|
|
11
|
+
[],
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
return [binary, places];
|
|
15
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import createWabt from 'wabt';
|
|
2
|
+
import {tryCatch} from 'try-catch';
|
|
3
|
+
|
|
4
|
+
export const translate = async (wast, options = {}) => {
|
|
5
|
+
const {name = 'ishvara.wast', type} = options;
|
|
6
|
+
|
|
7
|
+
const {parseWat} = await createWabt();
|
|
8
|
+
const [error, parsedWat] = tryCatch(parseWat, name, wast);
|
|
9
|
+
|
|
10
|
+
if (error)
|
|
11
|
+
return [null, toPlaces(name, error)];
|
|
12
|
+
|
|
13
|
+
const {log, buffer} = parsedWat.toBinary({
|
|
14
|
+
log: type === 'dump',
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
return [
|
|
18
|
+
log || buffer,
|
|
19
|
+
[],
|
|
20
|
+
];
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
function toPlaces(name, error) {
|
|
24
|
+
const [, first] = error.message.split('\n');
|
|
25
|
+
|
|
26
|
+
const list = first
|
|
27
|
+
.replace(`${name}�`, '')
|
|
28
|
+
.split(':');
|
|
29
|
+
|
|
30
|
+
list.shift();
|
|
31
|
+
|
|
32
|
+
const [line, column] = list;
|
|
33
|
+
|
|
34
|
+
list.shift();
|
|
35
|
+
list.shift();
|
|
36
|
+
list.shift();
|
|
37
|
+
|
|
38
|
+
const messageRaw = list
|
|
39
|
+
.join(':')
|
|
40
|
+
.slice(1);
|
|
41
|
+
|
|
42
|
+
const message = messageRaw[0].toUpperCase() + messageRaw.slice(1);
|
|
43
|
+
|
|
44
|
+
return [{
|
|
45
|
+
message,
|
|
46
|
+
position: {
|
|
47
|
+
line: Number(line),
|
|
48
|
+
column: Number(column),
|
|
49
|
+
},
|
|
50
|
+
}];
|
|
51
|
+
}
|