Skip to content

Commit 073d370

Browse files
Let s2wasm emit binary output (#1465)
* Emit invokeFuncs list as metadata * Refactor s2wasm to use ModuleWriter * Fix wasm-emscripten-finalize metadata output for binary output * Add a flag to emit binary from s2wasm NOTE: I chose to emit text by default, and binary behind a flag. This mismatches with asm2wasm (and the expectations of users of a "2wasm" tool), but doesn't break any existing users of s2wasm. If s2wasm is deprecated in favor of lld, this will be the least disruptive change, and we won't have to live with awkward defaults for too long. * Emit source maps in the binary output of s2wasm * Only emit binary with an outfile specified
1 parent be92434 commit 073d370

File tree

99 files changed

+177
-108
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

99 files changed

+177
-108
lines changed

src/tools/s2wasm.cpp

Lines changed: 68 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "support/file.h"
2727
#include "s2wasm.h"
2828
#include "wasm-emscripten.h"
29+
#include "wasm-io.h"
2930
#include "wasm-linker.h"
3031
#include "wasm-printing.h"
3132
#include "wasm-validator.h"
@@ -38,7 +39,12 @@ int main(int argc, const char *argv[]) {
3839
bool generateEmscriptenGlue = false;
3940
bool allowMemoryGrowth = false;
4041
bool importMemory = false;
42+
bool emitBinary = false;
43+
bool debugInfo = false;
4144
std::string startFunction;
45+
std::string sourceMapFilename;
46+
std::string sourceMapUrl;
47+
std::string symbolMap;
4248
std::vector<std::string> archiveLibraries;
4349
TrapMode trapMode = TrapMode::Allow;
4450
unsigned numReservedFunctionPointers = 0;
@@ -61,7 +67,7 @@ int main(int argc, const char *argv[]) {
6167
[&startFunction](Options *, const std::string& argument) {
6268
startFunction = argument.size() ? argument : "main";
6369
})
64-
.add("--global-base", "-g", "Where to start to place globals",
70+
.add("--global-base", "", "Where to start to place globals",
6571
Options::Arguments::One,
6672
[](Options *o, const std::string& argument) {
6773
o->extra["global-base"] = argument;
@@ -130,12 +136,47 @@ int main(int argc, const char *argv[]) {
130136
const std::string &argument) {
131137
numReservedFunctionPointers = std::stoi(argument);
132138
})
139+
.add("--emit-binary", "",
140+
"Emit binary instead of text for the output file",
141+
Options::Arguments::Zero,
142+
[&emitBinary](Options *, const std::string &) {
143+
emitBinary = true;
144+
})
145+
.add("--debuginfo", "-g",
146+
"Emit names section in wasm binary (or full debuginfo in wast)",
147+
Options::Arguments::Zero,
148+
[&debugInfo](Options *, const std::string &) {
149+
debugInfo = true;
150+
})
151+
.add("--source-map", "-sm",
152+
"Emit source map (if using binary output) to the specified file",
153+
Options::Arguments::One,
154+
[&sourceMapFilename](Options *, const std::string& argument) {
155+
sourceMapFilename = argument;
156+
})
157+
.add("--source-map-url", "-su",
158+
"Use specified string as source map URL",
159+
Options::Arguments::One,
160+
[&sourceMapUrl](Options *, const std::string& argument) {
161+
sourceMapUrl = argument;
162+
})
163+
.add("--symbolmap", "-s",
164+
"Emit a symbol map (indexes => names)",
165+
Options::Arguments::One,
166+
[&symbolMap](Options *, const std::string& argument) {
167+
symbolMap = argument;
168+
})
133169
.add_positional("INFILE", Options::Arguments::One,
134170
[](Options *o, const std::string& argument) {
135171
o->extra["infile"] = argument;
136172
});
137173
options.parse(argc, argv);
138174

175+
if (options.extra["output"].size() == 0) {
176+
// when no output file is specified, we emit text to stdout
177+
emitBinary = false;
178+
}
179+
139180
if (allowMemoryGrowth && !generateEmscriptenGlue) {
140181
Fatal() << "Error: adding memory growth code without Emscripten glue. "
141182
"This doesn't do anything.\n";
@@ -187,13 +228,13 @@ int main(int argc, const char *argv[]) {
187228
linker.layout();
188229

189230
std::string metadata;
231+
Module& wasm = linker.getOutput().wasm;
190232
if (generateEmscriptenGlue) {
191-
Module& wasm = linker.getOutput().wasm;
192233
if (options.debug) {
193234
std::cerr << "Emscripten gluing..." << std::endl;
194235
WasmPrinter::printModule(&wasm, std::cerr);
195236
}
196-
metadata = ";; METADATA: " + emscriptenGlue(
237+
metadata = emscriptenGlue(
197238
wasm,
198239
allowMemoryGrowth,
199240
linker.getStackPointerAddress(),
@@ -204,18 +245,36 @@ int main(int argc, const char *argv[]) {
204245

205246
if (options.extra["validate"] != "none") {
206247
if (options.debug) std::cerr << "Validating..." << std::endl;
207-
Module* output = &linker.getOutput().wasm;
208-
if (!wasm::WasmValidator().validate(*output,
248+
if (!wasm::WasmValidator().validate(wasm,
209249
WasmValidator::Globally | (options.extra["validate"] == "web" ? WasmValidator::Web : 0))) {
210-
WasmPrinter::printModule(output);
250+
WasmPrinter::printModule(&wasm);
211251
Fatal() << "Error: linked module is not valid.\n";
212252
}
213253
}
214254

215255
if (options.debug) std::cerr << "Printing..." << std::endl;
216-
Output output(options.extra["output"], Flags::Text, options.debug ? Flags::Debug : Flags::Release);
217-
WasmPrinter::printModule(&linker.getOutput().wasm, output.getStream());
218-
output << metadata;
256+
auto outputDebugFlag = options.debug ? Flags::Debug : Flags::Release;
257+
auto outputBinaryFlag = emitBinary ? Flags::Binary : Flags::Text;
258+
Output output(options.extra["output"], outputBinaryFlag, outputDebugFlag);
259+
260+
ModuleWriter writer;
261+
writer.setDebug(options.debug);
262+
writer.setDebugInfo(debugInfo);
263+
writer.setSymbolMap(symbolMap);
264+
writer.setBinary(emitBinary);
265+
if (emitBinary) {
266+
writer.setSourceMapFilename(sourceMapFilename);
267+
writer.setSourceMapUrl(sourceMapUrl);
268+
}
269+
writer.write(wasm, output);
270+
271+
if (generateEmscriptenGlue) {
272+
if (emitBinary) {
273+
std::cout << metadata;
274+
} else {
275+
output << ";; METADATA: " << metadata;
276+
}
277+
}
219278

220279
if (options.debug) std::cerr << "Done." << std::endl;
221280
return 0;

src/tools/wasm-emscripten-finalize.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,10 +132,11 @@ int main(int argc, const char *argv[]) {
132132
// writer.setSourceMapUrl(sourceMapUrl);
133133
// }
134134
writer.write(wasm, output);
135-
if (!emitBinary) {
136-
output << ";; METADATA: ";
135+
if (emitBinary) {
136+
std::cout << metadata;
137+
} else {
138+
output << ";; METADATA: " << metadata;
137139
}
138-
output << metadata;
139140

140141
return 0;
141142
}

src/wasm-emscripten.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,15 @@ std::string EmscriptenGlueGenerator::generateEmscriptenMetadata(
623623
}
624624
meta << "]";
625625

626+
meta << ", \"invokeFuncs\": [";
627+
commaFirst = true;
628+
for (const auto& import : wasm.imports) {
629+
if (import->name.startsWith("invoke_")) {
630+
meta << maybeComma() << '"' << import->name.str << '"';
631+
}
632+
}
633+
meta << "]";
634+
626635
meta << " }\n";
627636

628637
return meta.str();

test/dot_s/alias.wast

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,4 +66,4 @@
6666
)
6767
)
6868
)
69-
;; METADATA: { "asmConsts": {},"staticBump": 28, "initializers": [], "declares": [], "externs": [], "implementedFunctions": ["___exit","___needs_exit","___wasm_nullptr","_stackSave","_stackAlloc","_stackRestore","_dynCall_v"], "exports": ["__exit","__needs_exit","stackSave","stackAlloc","stackRestore","dynCall_v"] }
69+
;; METADATA: { "asmConsts": {},"staticBump": 28, "initializers": [], "declares": [], "externs": [], "implementedFunctions": ["___exit","___needs_exit","___wasm_nullptr","_stackSave","_stackAlloc","_stackRestore","_dynCall_v"], "exports": ["__exit","__needs_exit","stackSave","stackAlloc","stackRestore","dynCall_v"], "invokeFuncs": [] }

test/dot_s/alternate-lcomm.wast

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,4 @@
3434
)
3535
)
3636
)
37-
;; METADATA: { "asmConsts": {},"staticBump": 16, "initializers": [], "declares": [], "externs": [], "implementedFunctions": ["_stackSave","_stackAlloc","_stackRestore"], "exports": ["stackSave","stackAlloc","stackRestore"] }
37+
;; METADATA: { "asmConsts": {},"staticBump": 16, "initializers": [], "declares": [], "externs": [], "implementedFunctions": ["_stackSave","_stackAlloc","_stackRestore"], "exports": ["stackSave","stackAlloc","stackRestore"], "invokeFuncs": [] }

test/dot_s/asm_const.wast

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,4 @@
4646
)
4747
)
4848
)
49-
;; METADATA: { "asmConsts": {"0": ["{ Module.print(\"hello, world!\"); }", ["v"]]},"staticBump": 51, "initializers": [], "declares": [], "externs": [], "implementedFunctions": ["_main","_stackSave","_stackAlloc","_stackRestore"], "exports": ["main","stackSave","stackAlloc","stackRestore"] }
49+
;; METADATA: { "asmConsts": {"0": ["{ Module.print(\"hello, world!\"); }", ["v"]]},"staticBump": 51, "initializers": [], "declares": [], "externs": [], "implementedFunctions": ["_main","_stackSave","_stackAlloc","_stackRestore"], "exports": ["main","stackSave","stackAlloc","stackRestore"], "invokeFuncs": [] }

test/dot_s/basics.wast

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,4 +137,4 @@
137137
)
138138
)
139139
)
140-
;; METADATA: { "asmConsts": {},"staticBump": 52, "initializers": [], "declares": ["puts"], "externs": [], "implementedFunctions": ["_main","___wasm_nullptr","_stackSave","_stackAlloc","_stackRestore","_dynCall_iii"], "exports": ["main","stackSave","stackAlloc","stackRestore","dynCall_iii"] }
140+
;; METADATA: { "asmConsts": {},"staticBump": 52, "initializers": [], "declares": ["puts"], "externs": [], "implementedFunctions": ["_main","___wasm_nullptr","_stackSave","_stackAlloc","_stackRestore","_dynCall_iii"], "exports": ["main","stackSave","stackAlloc","stackRestore","dynCall_iii"], "invokeFuncs": [] }

test/dot_s/bcp-1.wast

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -353,4 +353,4 @@
353353
)
354354
)
355355
)
356-
;; METADATA: { "asmConsts": {},"staticBump": 104, "initializers": [], "declares": ["abort","exit"], "externs": [], "implementedFunctions": ["_bad0","_bad1","_bad2","_bad3","_bad4","_bad5","_bad6","_bad7","_bad8","_bad9","_bad10","_good0","_good1","_good2","_opt0","_opt1","_opt2","_main","___wasm_nullptr","_stackSave","_stackAlloc","_stackRestore","_dynCall_i","_dynCall_ii"], "exports": ["bad0","bad1","bad2","bad3","bad4","bad5","bad6","bad7","bad8","bad9","bad10","good0","good1","good2","opt0","opt1","opt2","main","stackSave","stackAlloc","stackRestore","dynCall_i","dynCall_ii"] }
356+
;; METADATA: { "asmConsts": {},"staticBump": 104, "initializers": [], "declares": ["abort","exit"], "externs": [], "implementedFunctions": ["_bad0","_bad1","_bad2","_bad3","_bad4","_bad5","_bad6","_bad7","_bad8","_bad9","_bad10","_good0","_good1","_good2","_opt0","_opt1","_opt2","_main","___wasm_nullptr","_stackSave","_stackAlloc","_stackRestore","_dynCall_i","_dynCall_ii"], "exports": ["bad0","bad1","bad2","bad3","bad4","bad5","bad6","bad7","bad8","bad9","bad10","good0","good1","good2","opt0","opt1","opt2","main","stackSave","stackAlloc","stackRestore","dynCall_i","dynCall_ii"], "invokeFuncs": [] }

test/dot_s/data-offset-folding.wast

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,4 @@
3636
)
3737
)
3838
)
39-
;; METADATA: { "asmConsts": {},"staticBump": 420, "initializers": [], "declares": [], "externs": [], "implementedFunctions": ["_stackSave","_stackAlloc","_stackRestore"], "exports": ["stackSave","stackAlloc","stackRestore"] }
39+
;; METADATA: { "asmConsts": {},"staticBump": 420, "initializers": [], "declares": [], "externs": [], "implementedFunctions": ["_stackSave","_stackAlloc","_stackRestore"], "exports": ["stackSave","stackAlloc","stackRestore"], "invokeFuncs": [] }

test/dot_s/debug.wast

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,4 +87,4 @@
8787
)
8888
)
8989
)
90-
;; METADATA: { "asmConsts": {},"staticBump": 12, "initializers": [], "declares": [], "externs": [], "implementedFunctions": ["_fib","_stackSave","_stackAlloc","_stackRestore"], "exports": ["fib","stackSave","stackAlloc","stackRestore"] }
90+
;; METADATA: { "asmConsts": {},"staticBump": 12, "initializers": [], "declares": [], "externs": [], "implementedFunctions": ["_fib","_stackSave","_stackAlloc","_stackRestore"], "exports": ["fib","stackSave","stackAlloc","stackRestore"], "invokeFuncs": [] }

0 commit comments

Comments
 (0)