summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/s2wasm-main.cpp21
-rw-r--r--src/s2wasm.h63
2 files changed, 75 insertions, 9 deletions
diff --git a/src/s2wasm-main.cpp b/src/s2wasm-main.cpp
index d7a18f547..752494aac 100644
--- a/src/s2wasm-main.cpp
+++ b/src/s2wasm-main.cpp
@@ -58,6 +58,16 @@ int main(int argc, const char *argv[]) {
[](Options *o, const std::string &argument) {
o->extra["stack-allocation"] = argument;
})
+ .add("--initial-memory", "-i", "Initial size of the linear memory",
+ Options::Arguments::One,
+ [](Options *o, const std::string &argument) {
+ o->extra["initial-memory"] = argument;
+ })
+ .add("--max-memory", "-m", "Maximum size of the linear memory",
+ Options::Arguments::One,
+ [](Options *o, const std::string &argument) {
+ o->extra["max-memory"] = argument;
+ })
.add_positional("INFILE", Options::Arguments::One,
[](Options *o, const std::string &argument) {
o->extra["infile"] = argument;
@@ -75,9 +85,18 @@ int main(int argc, const char *argv[]) {
options.extra.find("stack-allocation") != options.extra.end()
? std::stoull(options.extra["stack-allocation"])
: 0;
+ size_t initialMem =
+ options.extra.find("initial-memory") != options.extra.end()
+ ? std::stoull(options.extra["initial-memory"])
+ : 0;
+ size_t maxMem =
+ options.extra.find("max-memory") != options.extra.end()
+ ? std::stoull(options.extra["max-memory"])
+ : 0;
if (options.debug) std::cerr << "Global base " << globalBase << '\n';
S2WasmBuilder s2wasm(wasm, input.c_str(), options.debug, globalBase,
- stackAllocation, ignoreUnknownSymbols, startFunction);
+ stackAllocation, initialMem, maxMem, ignoreUnknownSymbols,
+ startFunction);
if (options.debug) std::cerr << "Emscripten gluing..." << std::endl;
std::stringstream meta;
diff --git a/src/s2wasm.h b/src/s2wasm.h
index 6725e305b..87c0c2881 100644
--- a/src/s2wasm.h
+++ b/src/s2wasm.h
@@ -49,6 +49,7 @@ class S2WasmBuilder {
public:
S2WasmBuilder(AllocatingModule& wasm, const char* input, bool debug,
size_t globalBase, size_t stackAllocation,
+ size_t userInitialMemory, size_t userMaxMemory,
bool ignoreUnknownSymbols, Name startFunction)
: wasm(wasm),
allocator(wasm.allocator),
@@ -57,7 +58,19 @@ class S2WasmBuilder {
startFunction(startFunction),
globalBase(globalBase),
nextStatic(globalBase),
- initialMemory(0) {
+ minInitialMemory(0),
+ userInitialMemory(userInitialMemory),
+ userMaxMemory(userMaxMemory) {
+ if (userMaxMemory && userMaxMemory < userInitialMemory) {
+ Fatal() << "Specified max memory " << userMaxMemory <<
+ " is < specified initial memory " << userInitialMemory;
+ }
+ if (roundUpToPageSize(userMaxMemory) != userMaxMemory) {
+ Fatal() << "Specified max memory " << userMaxMemory << " is not a multiple of 64k";
+ }
+ if (roundUpToPageSize(userInitialMemory) != userInitialMemory) {
+ Fatal() << "Specified initial memory " << userInitialMemory << " is not a multiple of 64k";
+ }
s = input;
scan();
s = input;
@@ -77,7 +90,10 @@ class S2WasmBuilder {
size_t globalBase, // where globals can start to be statically allocated, i.e., the data segment
nextStatic; // location of next static allocation
std::map<Name, int32_t> staticAddresses; // name => address
- size_t initialMemory; // Initial size (in bytes) of memory (after linking, this is rounded and set on the wasm object in pages)
+ size_t minInitialMemory; // Minimum initial size (in bytes) of memory.
+ size_t userInitialMemory; // Initial memory size (in bytes) specified by the user.
+ size_t userMaxMemory; // Max memory size (in bytes) specified by the user.
+ //(after linking, this is rounded and set on the wasm object in pages)
struct Relocation {
uint32_t* data;
@@ -96,6 +112,23 @@ class S2WasmBuilder {
// utilities
+ // For fatal errors which could arise from input (i.e. not assertion failures)
+ class Fatal {
+ public:
+ Fatal() {
+ std::cerr << "Fatal: ";
+ }
+ template<typename T>
+ Fatal &operator<<(T arg) {
+ std::cerr << std::forward<T>(arg);
+ return *this;
+ }
+ ~Fatal() {
+ std::cerr << "\n";
+ exit(1);
+ }
+ };
+
void skipWhitespace() {
while (1) {
while (*s && isspace(*s)) s++;
@@ -399,7 +432,7 @@ class S2WasmBuilder {
addressSegments[nextStatic] = wasm.memory.segments.size();
wasm.memory.segments.emplace_back(
nextStatic, reinterpret_cast<char*>(raw), pointerSize);
- initialMemory = nextStatic + pointerSize;
+ minInitialMemory = nextStatic + pointerSize;
}
nextStatic += pointerSize;
}
@@ -410,7 +443,7 @@ class S2WasmBuilder {
nextStatic = (nextStatic + 15) & static_cast<size_t>(-16);
staticAddresses[".stack"] = nextStatic;
nextStatic += stackAllocation;
- initialMemory = nextStatic;
+ minInitialMemory = nextStatic;
}
void process() {
@@ -1155,7 +1188,7 @@ class S2WasmBuilder {
wasm.memory.segments.emplace_back(nextStatic, (const char*)&(*raw)[0], size);
}
nextStatic += size;
- initialMemory = nextStatic;
+ minInitialMemory = nextStatic;
}
void parseLcomm(Name name, size_t align=1) {
@@ -1169,7 +1202,7 @@ class S2WasmBuilder {
while (nextStatic % align) nextStatic++;
staticAddresses[name] = nextStatic;
nextStatic += size;
- initialMemory = nextStatic;
+ minInitialMemory = nextStatic;
}
void skipImports() {
@@ -1183,11 +1216,25 @@ class S2WasmBuilder {
}
}
+ static size_t roundUpToPageSize(size_t size) {
+ return (size + Memory::kPageSize - 1) & Memory::kPageMask;
+ }
+
void fix() {
// Round the memory size up to a page, and update the page-increment versions
// of initial and max
- wasm.memory.initial = ((initialMemory + Memory::kPageSize - 1) & Memory::kPageMask) /
- Memory::kPageSize;
+ size_t initialMem = roundUpToPageSize(minInitialMemory);
+ if (userInitialMemory) {
+ if (initialMem > userInitialMemory) {
+ Fatal() << "Specified initial memory size " << userInitialMemory <<
+ " is smaller than required size " << initialMem;
+ }
+ wasm.memory.initial = userInitialMemory / Memory::kPageSize;
+ } else {
+ wasm.memory.initial = initialMem / Memory::kPageSize;
+ }
+
+ if (userMaxMemory) wasm.memory.max = userMaxMemory / Memory::kPageSize;
wasm.memory.exportName = MEMORY;
// XXX For now, export all functions marked .globl.