Skip to content

Commit e6ea668

Browse files
authored
add docs and error hints when a Call should be a CallImport (#1081)
* add docs and error hints when a Call should be a CallImport * fix binaryen API docs in docs/
1 parent 812943d commit e6ea668

8 files changed

Lines changed: 1381 additions & 746 deletions

File tree

bin/binaryen.js

Lines changed: 657 additions & 651 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bin/wasm.js

Lines changed: 661 additions & 21 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

build-js.sh

Lines changed: 18 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -56,15 +56,19 @@ else
5656
# See https://gist.github.com/rsms/e33c61a25a31c08260161a087be03169
5757
fi
5858

59-
echo "building wasm.js"
59+
if [ "$1" != "-g" ]; then
60+
EMCC_ARGS="$EMCC_ARGS --closure 1"
61+
fi
62+
63+
echo "building shared bitcode"
6064

6165
"$EMSCRIPTEN/em++" \
6266
$EMCC_ARGS \
63-
src/wasm-js.cpp \
6467
src/ast/ExpressionAnalyzer.cpp \
6568
src/ast/ExpressionManipulator.cpp \
6669
src/passes/pass.cpp \
6770
src/passes/CoalesceLocals.cpp \
71+
src/passes/CodeFolding.cpp \
6872
src/passes/CodePushing.cpp \
6973
src/passes/DeadCodeElimination.cpp \
7074
src/passes/DuplicateFunctionElimination.cpp \
@@ -80,7 +84,6 @@ echo "building wasm.js"
8084
src/passes/MergeBlocks.cpp \
8185
src/passes/Metrics.cpp \
8286
src/passes/NameList.cpp \
83-
src/passes/NameManager.cpp \
8487
src/passes/OptimizeInstructions.cpp \
8588
src/passes/PickLoadSigns.cpp \
8689
src/passes/PostEmscripten.cpp \
@@ -117,84 +120,27 @@ echo "building wasm.js"
117120
src/wasm/literal.cpp \
118121
src/cfg/Relooper.cpp \
119122
-Isrc/ \
120-
-o bin/wasm${OUT_FILE_SUFFIX}.js \
121-
-s MODULARIZE=1 \
122-
-s 'EXPORT_NAME="WasmJS"'
123-
#-DWASM_JS_DEBUG
124-
#-DWASM_INTERPRETER_DEBUG=2
125-
126-
echo "building binaryen.js to bitcode"
123+
-o shared.bc
127124

128-
if [ "$1" != "-g" ]; then
129-
EMCC_ARGS="$EMCC_ARGS --closure 1"
130-
fi
125+
echo "building wasm.js"
131126

132127
"$EMSCRIPTEN/em++" \
133128
$EMCC_ARGS \
134-
-std=c++11 \
135-
src/ast/ExpressionAnalyzer.cpp \
136-
src/ast/ExpressionManipulator.cpp \
137-
src/passes/pass.cpp \
138-
src/passes/CoalesceLocals.cpp \
139-
src/passes/CodePushing.cpp \
140-
src/passes/DeadCodeElimination.cpp \
141-
src/passes/DuplicateFunctionElimination.cpp \
142-
src/passes/ExtractFunction.cpp \
143-
src/passes/FlattenControlFlow.cpp \
144-
src/passes/Inlining.cpp \
145-
src/passes/InstrumentLocals.cpp \
146-
src/passes/InstrumentMemory.cpp \
147-
src/passes/LegalizeJSInterface.cpp \
148-
src/passes/LocalCSE.cpp \
149-
src/passes/LogExecution.cpp \
150-
src/passes/MemoryPacking.cpp \
151-
src/passes/MergeBlocks.cpp \
152-
src/passes/Metrics.cpp \
153-
src/passes/NameList.cpp \
154-
src/passes/NameManager.cpp \
155-
src/passes/OptimizeInstructions.cpp \
156-
src/passes/PickLoadSigns.cpp \
157-
src/passes/PostEmscripten.cpp \
158-
src/passes/Precompute.cpp \
159-
src/passes/PrintCallGraph.cpp \
160-
src/passes/Print.cpp \
161-
src/passes/RelooperJumpThreading.cpp \
162-
src/passes/RemoveImports.cpp \
163-
src/passes/RemoveMemory.cpp \
164-
src/passes/RemoveUnusedBrs.cpp \
165-
src/passes/RemoveUnusedModuleElements.cpp \
166-
src/passes/RemoveUnusedNames.cpp \
167-
src/passes/ReorderFunctions.cpp \
168-
src/passes/ReorderLocals.cpp \
169-
src/passes/ReReloop.cpp \
170-
src/passes/SSAify.cpp \
171-
src/passes/SimplifyLocals.cpp \
172-
src/passes/Untee.cpp \
173-
src/passes/Vacuum.cpp \
174-
src/wasm-emscripten.cpp \
175-
src/support/colors.cpp \
176-
src/support/safe_integer.cpp \
177-
src/support/bits.cpp \
178-
src/support/threads.cpp \
179-
src/asmjs/asm_v_wasm.cpp \
180-
src/asmjs/shared-constants.cpp \
181-
src/wasm/wasm.cpp \
182-
src/wasm/wasm-type.cpp \
183-
src/wasm/wasm-binary.cpp \
184-
src/wasm/wasm-s-parser.cpp \
185-
src/wasm/literal.cpp \
186-
src/binaryen-c.cpp \
187-
src/cfg/Relooper.cpp \
188-
-o binaryen.bc \
189-
-Isrc/
129+
src/wasm-js.cpp \
130+
shared.bc \
131+
-Isrc/ \
132+
-o bin/wasm${OUT_FILE_SUFFIX}.js \
133+
-s MODULARIZE=1 \
134+
-s 'EXPORT_NAME="WasmJS"'
190135

191-
echo "building binaryen.js to js"
136+
echo "building binaryen.js"
192137

193138
"$EMSCRIPTEN/em++" \
194139
$EMCC_ARGS \
195-
binaryen.bc \
140+
src/binaryen-c.cpp \
141+
shared.bc \
142+
-Isrc/ \
196143
-s 'EXPORTED_FUNCTIONS=["_BinaryenNone", "_BinaryenInt32", "_BinaryenInt64", "_BinaryenFloat32", "_BinaryenFloat64", "_BinaryenUndefined", "_BinaryenModuleCreate", "_BinaryenModuleDispose", "_BinaryenAddFunctionType", "_BinaryenGetFunctionTypeBySignature", "_BinaryenLiteralInt32", "_BinaryenLiteralInt64", "_BinaryenLiteralFloat32", "_BinaryenLiteralFloat64", "_BinaryenLiteralFloat32Bits", "_BinaryenLiteralFloat64Bits", "_BinaryenClzInt32", "_BinaryenCtzInt32", "_BinaryenPopcntInt32", "_BinaryenNegFloat32", "_BinaryenAbsFloat32", "_BinaryenCeilFloat32", "_BinaryenFloorFloat32", "_BinaryenTruncFloat32", "_BinaryenNearestFloat32", "_BinaryenSqrtFloat32", "_BinaryenEqZInt32", "_BinaryenClzInt64", "_BinaryenCtzInt64", "_BinaryenPopcntInt64", "_BinaryenNegFloat64", "_BinaryenAbsFloat64", "_BinaryenCeilFloat64", "_BinaryenFloorFloat64", "_BinaryenTruncFloat64", "_BinaryenNearestFloat64", "_BinaryenSqrtFloat64", "_BinaryenEqZInt64", "_BinaryenExtendSInt32", "_BinaryenExtendUInt32", "_BinaryenWrapInt64", "_BinaryenTruncSFloat32ToInt32", "_BinaryenTruncSFloat32ToInt64", "_BinaryenTruncUFloat32ToInt32", "_BinaryenTruncUFloat32ToInt64", "_BinaryenTruncSFloat64ToInt32", "_BinaryenTruncSFloat64ToInt64", "_BinaryenTruncUFloat64ToInt32", "_BinaryenTruncUFloat64ToInt64", "_BinaryenReinterpretFloat32", "_BinaryenReinterpretFloat64", "_BinaryenConvertSInt32ToFloat32", "_BinaryenConvertSInt32ToFloat64", "_BinaryenConvertUInt32ToFloat32", "_BinaryenConvertUInt32ToFloat64", "_BinaryenConvertSInt64ToFloat32", "_BinaryenConvertSInt64ToFloat64", "_BinaryenConvertUInt64ToFloat32", "_BinaryenConvertUInt64ToFloat64", "_BinaryenPromoteFloat32", "_BinaryenDemoteFloat64", "_BinaryenReinterpretInt32", "_BinaryenReinterpretInt64", "_BinaryenAddInt32", "_BinaryenSubInt32", "_BinaryenMulInt32", "_BinaryenDivSInt32", "_BinaryenDivUInt32", "_BinaryenRemSInt32", "_BinaryenRemUInt32", "_BinaryenAndInt32", "_BinaryenOrInt32", "_BinaryenXorInt32", "_BinaryenShlInt32", "_BinaryenShrUInt32", "_BinaryenShrSInt32", "_BinaryenRotLInt32", "_BinaryenRotRInt32", "_BinaryenEqInt32", "_BinaryenNeInt32", "_BinaryenLtSInt32", "_BinaryenLtUInt32", "_BinaryenLeSInt32", "_BinaryenLeUInt32", "_BinaryenGtSInt32", "_BinaryenGtUInt32", "_BinaryenGeSInt32", "_BinaryenGeUInt32", "_BinaryenAddInt64", "_BinaryenSubInt64", "_BinaryenMulInt64", "_BinaryenDivSInt64", "_BinaryenDivUInt64", "_BinaryenRemSInt64", "_BinaryenRemUInt64", "_BinaryenAndInt64", "_BinaryenOrInt64", "_BinaryenXorInt64", "_BinaryenShlInt64", "_BinaryenShrUInt64", "_BinaryenShrSInt64", "_BinaryenRotLInt64", "_BinaryenRotRInt64", "_BinaryenEqInt64", "_BinaryenNeInt64", "_BinaryenLtSInt64", "_BinaryenLtUInt64", "_BinaryenLeSInt64", "_BinaryenLeUInt64", "_BinaryenGtSInt64", "_BinaryenGtUInt64", "_BinaryenGeSInt64", "_BinaryenGeUInt64", "_BinaryenAddFloat32", "_BinaryenSubFloat32", "_BinaryenMulFloat32", "_BinaryenDivFloat32", "_BinaryenCopySignFloat32", "_BinaryenMinFloat32", "_BinaryenMaxFloat32", "_BinaryenEqFloat32", "_BinaryenNeFloat32", "_BinaryenLtFloat32", "_BinaryenLeFloat32", "_BinaryenGtFloat32", "_BinaryenGeFloat32", "_BinaryenAddFloat64", "_BinaryenSubFloat64", "_BinaryenMulFloat64", "_BinaryenDivFloat64", "_BinaryenCopySignFloat64", "_BinaryenMinFloat64", "_BinaryenMaxFloat64", "_BinaryenEqFloat64", "_BinaryenNeFloat64", "_BinaryenLtFloat64", "_BinaryenLeFloat64", "_BinaryenGtFloat64", "_BinaryenGeFloat64", "_BinaryenPageSize", "_BinaryenCurrentMemory", "_BinaryenGrowMemory", "_BinaryenHasFeature", "_BinaryenBlock", "_BinaryenIf", "_BinaryenLoop", "_BinaryenBreak", "_BinaryenSwitch", "_BinaryenCall", "_BinaryenCallImport", "_BinaryenCallIndirect", "_BinaryenGetLocal", "_BinaryenSetLocal", "_BinaryenTeeLocal", "_BinaryenGetGlobal", "_BinaryenSetGlobal", "_BinaryenLoad", "_BinaryenStore", "_BinaryenConst", "_BinaryenUnary", "_BinaryenBinary", "_BinaryenSelect", "_BinaryenDrop", "_BinaryenReturn", "_BinaryenHost", "_BinaryenNop", "_BinaryenUnreachable", "_BinaryenExpressionPrint", "_BinaryenAddFunction", "_BinaryenAddGlobal", "_BinaryenAddImport", "_BinaryenRemoveImport", "_BinaryenAddExport", "_BinaryenRemoveExport", "_BinaryenSetFunctionTable", "_BinaryenSetMemory", "_BinaryenSetStart", "_BinaryenModuleParse", "_BinaryenModulePrint", "_BinaryenModuleValidate", "_BinaryenModuleOptimize", "_BinaryenModuleAutoDrop", "_BinaryenModuleWrite", "_BinaryenModuleRead", "_BinaryenModuleInterpret", "_RelooperCreate", "_RelooperAddBlock", "_RelooperAddBranch", "_RelooperAddBlockWithSwitch", "_RelooperAddBranchForSwitch", "_RelooperRenderAndDispose", "_BinaryenSetAPITracing"]' \
197144
-o bin/binaryen${OUT_FILE_SUFFIX}.js \
198-
--memory-init-file 0 \
199145
--pre-js src/js/binaryen.js-pre.js \
200146
--post-js src/js/binaryen.js-post.js

docs/binaryen.js.Markdown

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ Unprefixed expressions:
211211
* `break(label, condition, value)`: Create a break, to a label, and with an optional condition, and optional value.
212212
* `switch(labels, defaultLabel, condition, value)`: Create a switch (aka br_table), with a list of labels, a default label, a condition, and an optional value.
213213
* `call(name, operands, type)`: Create a call, to a function name, with operands, and having a specific return type (note that we must specify the return type here as we may not have created the function being called yet, and we may want to optimize this function before we do so, so the API requires that each function be independent of the others, which means that we can't depend on the definition of another function).
214-
* `call(name, operands, type)`: Similar to `call`, but calls an imported function.
214+
* `callImport(name, operands, type)`: Similar to `call`, but calls an imported function.
215215
* `callIndirect(target, operands, type)`: Similar to `call`, but calls indirectly, i.e., via a function pointer, so an expression replaces the name as the called value.
216216
* `getLocal(index, type)`: Create a get_local, for the local at the specified index, and having a specific type (the type is required for the same reasons as in `call`).
217217
* `setLocal(index, value)`: Create a set_local, for the local at the specified index, and setting the specified value.

src/binaryen-c.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,9 @@ BinaryenExpressionRef BinaryenSwitch(BinaryenModuleRef module, const char **name
281281
// type returned by the function being called, as that
282282
// function might not have been created yet, so we don't
283283
// know what it is.
284+
// Also note that WebAssembly does not differentiate
285+
// between Call and CallImport, but Binaryen does, so you
286+
// must use CallImport if calling an import, and vice versa.
284287
BinaryenExpressionRef BinaryenCall(BinaryenModuleRef module, const char *target, BinaryenExpressionRef* operands, BinaryenIndex numOperands, BinaryenType returnType);
285288
BinaryenExpressionRef BinaryenCallImport(BinaryenModuleRef module, const char *target, BinaryenExpressionRef* operands, BinaryenIndex numOperands, BinaryenType returnType);
286289
BinaryenExpressionRef BinaryenCallIndirect(BinaryenModuleRef module, BinaryenExpressionRef target, BinaryenExpressionRef* operands, BinaryenIndex numOperands, const char* type);

src/wasm/wasm-validator.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,12 @@ void WasmValidator::visitSwitch(Switch *curr) {
168168
void WasmValidator::visitCall(Call *curr) {
169169
if (!validateGlobally) return;
170170
auto* target = getModule()->getFunctionOrNull(curr->target);
171-
if (!shouldBeTrue(!!target, curr, "call target must exist")) return;
171+
if (!shouldBeTrue(!!target, curr, "call target must exist")) {
172+
if (getModule()->getImportOrNull(curr->target)) {
173+
std::cerr << "(perhaps it should be a CallImport instead of Call?)\n";
174+
}
175+
return;
176+
}
172177
if (!shouldBeTrue(curr->operands.size() == target->params.size(), curr, "call param number must match")) return;
173178
for (size_t i = 0; i < curr->operands.size(); i++) {
174179
if (!shouldBeEqualOrFirstIsUnreachable(curr->operands[i]->type, target->params[i], curr, "call param types must match")) {
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
var module = new Binaryen.Module();
2+
3+
var signature = module.addFunctionType("v", Binaryen.none, []);
4+
module.addImport("fn", "env", "fn", signature);
5+
6+
module.addFunction("main", signature, [], module.block("", [
7+
module.call("fn", [], Binaryen.none) // should be callImport
8+
]));
9+
module.addExport("main", "main");
10+
11+
console.log(module.emitText());
12+
13+
module.validate(); // fails
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
(module
2+
(type $v (func))
3+
(import "env" "fn" (func $fn))
4+
(memory $0 0)
5+
(export "main" (func $main))
6+
(func $main (type $v)
7+
(call $fn)
8+
)
9+
)
10+
11+
[wasm-validator error in function $main] unexpected false: call target must exist, on
12+
(call $fn)
13+
(perhaps it should be a CallImport instead of Call?)
14+
(module
15+
(type $v (func))
16+
(import "env" "fn" (func $fn))
17+
(memory $0 0)
18+
(export "main" (func $main))
19+
(func $main (type $v)
20+
(call $fn)
21+
)
22+
)

0 commit comments

Comments
 (0)