]>
git.proxmox.com Git - rustc.git/blob - src/binaryen/src/tools/s2wasm.cpp
2 * Copyright 2015 WebAssembly Community Group participants
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 // s2wasm console tool
23 #include "ir/trapping.h"
24 #include "support/colors.h"
25 #include "support/command-line.h"
26 #include "support/file.h"
28 #include "wasm-emscripten.h"
29 #include "wasm-linker.h"
30 #include "wasm-printing.h"
31 #include "wasm-validator.h"
33 using namespace cashew
;
36 int main(int argc
, const char *argv
[]) {
37 bool ignoreUnknownSymbols
= false;
38 bool generateEmscriptenGlue
= false;
39 bool allowMemoryGrowth
= false;
40 bool importMemory
= false;
41 std::string startFunction
;
42 std::vector
<std::string
> archiveLibraries
;
43 TrapMode trapMode
= TrapMode::Allow
;
44 Options
options("s2wasm", "Link .s file into .wast");
45 options
.extra
["validate"] = "wasm";
47 .add("--output", "-o", "Output file (stdout if not specified)",
48 Options::Arguments::One
,
49 [](Options
*o
, const std::string
&argument
) {
50 o
->extra
["output"] = argument
;
53 .add("--ignore-unknown", "", "Ignore unknown symbols",
54 Options::Arguments::Zero
,
55 [&ignoreUnknownSymbols
](Options
*, const std::string
&) {
56 ignoreUnknownSymbols
= true;
58 .add("--start", "", "Generate the start method (default: main)",
59 Options::Arguments::Optional
,
60 [&startFunction
](Options
*, const std::string
&argument
) {
61 startFunction
= argument
.size() ? argument
: "main";
63 .add("--global-base", "-g", "Where to start to place globals",
64 Options::Arguments::One
,
65 [](Options
*o
, const std::string
&argument
) {
66 o
->extra
["global-base"] = argument
;
68 .add("--allocate-stack", "-s", "Size of the user stack in linear memory",
69 Options::Arguments::One
,
70 [](Options
*o
, const std::string
&argument
) {
71 o
->extra
["stack-allocation"] = argument
;
73 .add("--initial-memory", "-i", "Initial size of the linear memory",
74 Options::Arguments::One
,
75 [](Options
*o
, const std::string
&argument
) {
76 o
->extra
["initial-memory"] = argument
;
78 .add("--max-memory", "-m", "Maximum size of the linear memory",
79 Options::Arguments::One
,
80 [](Options
*o
, const std::string
&argument
) {
81 o
->extra
["max-memory"] = argument
;
83 .add("--allow-memory-growth", "", "Allow linear memory to grow at runtime",
84 Options::Arguments::Zero
,
85 [&allowMemoryGrowth
](Options
*, const std::string
&) {
86 allowMemoryGrowth
= true;
88 .add("--trap-mode", "",
89 "Strategy for handling potentially trapping instructions. Valid "
90 "values are \"allow\", \"js\", and \"clamp\"",
91 Options::Arguments::One
,
92 [&trapMode
](Options
*o
, const std::string
&argument
) {
94 trapMode
= trapModeFromString(argument
);
95 } catch (std::invalid_argument e
) {
96 std::cerr
<< "Error: " << e
.what() << "\n";
100 .add("--emscripten-glue", "-e", "Generate emscripten glue",
101 Options::Arguments::Zero
,
102 [&generateEmscriptenGlue
](Options
*, const std::string
&) {
103 generateEmscriptenGlue
= true;
105 .add("--import-memory", "", "Import the linear memory instead of exporting it",
106 Options::Arguments::Zero
,
107 [&importMemory
](Options
*, const std::string
&) {
110 .add("--library", "-l", "Add archive library",
111 Options::Arguments::N
,
112 [&archiveLibraries
](Options
*o
, const std::string
&argument
) {
113 archiveLibraries
.push_back(argument
);
115 .add("--validate", "-v", "Control validation of the output module",
116 Options::Arguments::One
,
117 [](Options
*o
, const std::string
&argument
) {
118 if (argument
!= "web" && argument
!= "none" && argument
!= "wasm") {
119 std::cerr
<< "Valid arguments for --validate flag are 'wasm', 'web' and 'none'.\n";
122 o
->extra
["validate"] = argument
;
124 .add_positional("INFILE", Options::Arguments::One
,
125 [](Options
*o
, const std::string
&argument
) {
126 o
->extra
["infile"] = argument
;
128 options
.parse(argc
, argv
);
130 if (allowMemoryGrowth
&& !generateEmscriptenGlue
) {
131 Fatal() << "Error: adding memory growth code without Emscripten glue. "
132 "This doesn't do anything.\n";
135 auto debugFlag
= options
.debug
? Flags::Debug
: Flags::Release
;
136 auto input(read_file
<std::string
>(options
.extra
["infile"], Flags::Text
, debugFlag
));
138 if (options
.debug
) std::cerr
<< "Parsing and wasming..." << std::endl
;
139 uint64_t globalBase
= options
.extra
.find("global-base") != options
.extra
.end()
140 ? std::stoull(options
.extra
["global-base"])
142 uint64_t stackAllocation
=
143 options
.extra
.find("stack-allocation") != options
.extra
.end()
144 ? std::stoull(options
.extra
["stack-allocation"])
146 uint64_t initialMem
=
147 options
.extra
.find("initial-memory") != options
.extra
.end()
148 ? std::stoull(options
.extra
["initial-memory"])
151 options
.extra
.find("max-memory") != options
.extra
.end()
152 ? std::stoull(options
.extra
["max-memory"])
154 if (options
.debug
) std::cerr
<< "Global base " << globalBase
<< '\n';
156 Linker
linker(globalBase
, stackAllocation
, initialMem
, maxMem
,
157 importMemory
|| generateEmscriptenGlue
, ignoreUnknownSymbols
, startFunction
,
160 S2WasmBuilder
mainbuilder(input
.c_str(), options
.debug
);
161 linker
.linkObject(mainbuilder
);
163 if (trapMode
!= TrapMode::Allow
) {
164 Module
* wasm
= &(linker
.getOutput().wasm
);
165 PassRunner
runner(wasm
);
166 addTrapModePass(runner
, trapMode
);
170 for (const auto& m
: archiveLibraries
) {
171 auto archiveFile(read_file
<std::vector
<char>>(m
, Flags::Binary
, debugFlag
));
173 Archive
lib(archiveFile
, error
);
174 if (error
) Fatal() << "Error opening archive " << m
<< "\n";
175 linker
.linkArchive(lib
);
180 std::string metadata
;
181 if (generateEmscriptenGlue
) {
182 Module
& wasm
= linker
.getOutput().wasm
;
184 std::cerr
<< "Emscripten gluing..." << std::endl
;
185 WasmPrinter::printModule(&wasm
, std::cerr
);
187 metadata
= emscriptenGlue(
190 linker
.getStackPointerAddress(),
191 linker
.getStaticBump(),
192 linker
.getOutput().getInitializerFunctions());
195 if (options
.extra
["validate"] != "none") {
196 if (options
.debug
) std::cerr
<< "Validating..." << std::endl
;
197 Module
* output
= &linker
.getOutput().wasm
;
198 if (!wasm::WasmValidator().validate(*output
,
199 WasmValidator::Globally
| (options
.extra
["validate"] == "web" ? WasmValidator::Web
: 0))) {
200 WasmPrinter::printModule(output
);
201 Fatal() << "Error: linked module is not valid.\n";
205 if (options
.debug
) std::cerr
<< "Printing..." << std::endl
;
206 Output
output(options
.extra
["output"], Flags::Text
, options
.debug
? Flags::Debug
: Flags::Release
);
207 WasmPrinter::printModule(&linker
.getOutput().wasm
, output
.getStream());
210 if (options
.debug
) std::cerr
<< "Done." << std::endl
;