diff options
author | Derek Schuff <dschuff@chromium.org> | 2016-05-11 15:34:49 -0700 |
---|---|---|
committer | Derek Schuff <dschuff@chromium.org> | 2016-05-11 15:34:49 -0700 |
commit | ac827e35fec84074d9d8141ca2c94ad01ca9c5c3 (patch) | |
tree | 38f1c4b00de8af9f0545974847e4ab04f13b45fd | |
parent | 9c79f86a3f518c60840b416287a5d26502911ad6 (diff) | |
download | binaryen-ac827e35fec84074d9d8141ca2c94ad01ca9c5c3.tar.gz binaryen-ac827e35fec84074d9d8141ca2c94ad01ca9c5c3.tar.bz2 binaryen-ac827e35fec84074d9d8141ca2c94ad01ca9c5c3.zip |
Introduce a separate type for linear memory addresses (#477)
We've been using size_t (and other things) for addresses, which is
generally wrong because it depends on the host, when it should in fact
depend on the target. This is a partial fix for #278 (i.e. it's the
right fix, I don't think it's applied quite everywhere yet).
-rw-r--r-- | src/s2wasm.h | 26 | ||||
-rw-r--r-- | src/shell-interface.h | 6 | ||||
-rw-r--r-- | src/wasm-interpreter.h | 12 | ||||
-rw-r--r-- | src/wasm-linker.cpp | 12 | ||||
-rw-r--r-- | src/wasm-linker.h | 42 | ||||
-rw-r--r-- | src/wasm.h | 30 |
6 files changed, 66 insertions, 62 deletions
diff --git a/src/s2wasm.h b/src/s2wasm.h index 9c0ac81e2..2850ac564 100644 --- a/src/s2wasm.h +++ b/src/s2wasm.h @@ -1028,7 +1028,7 @@ class S2WasmBuilder { return; } skipWhitespace(); - size_t align = 4; // XXX default? + Address align = 4; // XXX default? if (match(".globl")) { mustMatch(name.str); skipWhitespace(); @@ -1037,7 +1037,7 @@ class S2WasmBuilder { align = getInt(); skipWhitespace(); } - align = (size_t)1 << align; // convert from power to actual bytes + align = (Address)1 << align; // convert from power to actual bytes if (match(".lcomm")) { parseLcomm(name, align); return; @@ -1046,7 +1046,7 @@ class S2WasmBuilder { mustMatch(":"); std::vector<char> raw; bool zero = true; - std::vector<std::pair<LinkerObject::Relocation*, size_t>> currRelocations; // [relocation, offset in raw] + std::vector<std::pair<LinkerObject::Relocation*, Address>> currRelocations; // [relocation, offset in raw] while (1) { skipWhitespace(); if (match(".asci")) { @@ -1062,7 +1062,7 @@ class S2WasmBuilder { if (z) raw.push_back(0); zero = false; } else if (match(".zero") || match(".skip")) { - int32_t size = getInt(); + Address size = getInt(); if (size <= 0) { abort_on(".zero with zero or negative size"); } @@ -1071,29 +1071,29 @@ class S2WasmBuilder { value = getInt(); if (value != 0) zero = false; } - for (size_t i = 0, e = size; i < e; i++) { + for (Address i = 0, e = size; i < e; i++) { raw.push_back(value); } } else if (match(".int8")) { - size_t size = raw.size(); + Address size = raw.size(); raw.resize(size + 1); (*(int8_t*)(&raw[size])) = getInt(); zero = false; } else if (match(".int16")) { - size_t size = raw.size(); + Address size = raw.size(); raw.resize(size + 2); int16_t val = getInt(); memcpy(&raw[size], &val, sizeof(val)); zero = false; } else if (match(".int32")) { - size_t size = raw.size(); + Address size = raw.size(); raw.resize(size + 4); if (getConst((uint32_t*)&raw[size])) { // just the size, as we may reallocate; we must fix this later, if it's a relocation currRelocations.emplace_back(linkerObj->getCurrentRelocation(), size); } zero = false; } else if (match(".int64")) { - size_t size = raw.size(); + Address size = raw.size(); raw.resize(size + 8); int64_t val = getInt64(); memcpy(&raw[size], &val, sizeof(val)); @@ -1103,11 +1103,11 @@ class S2WasmBuilder { } } skipWhitespace(); - size_t size = raw.size(); + Address size = raw.size(); if (match(".size")) { mustMatch(name.str); mustMatch(","); - size_t seenSize = atoi(getStr().str); // TODO: optimize + Address seenSize = atoi(getStr().str); // TODO: optimize assert(seenSize >= size); while (raw.size() < seenSize) { raw.push_back(0); @@ -1127,10 +1127,10 @@ class S2WasmBuilder { } } - void parseLcomm(Name name, size_t align=1) { + void parseLcomm(Name name, Address align=1) { mustMatch(name.str); skipComma(); - size_t size = getInt(); + Address size = getInt(); if (*s == ',') { skipComma(); getInt(); diff --git a/src/shell-interface.h b/src/shell-interface.h index 1dbabf3fa..4e56bb8e1 100644 --- a/src/shell-interface.h +++ b/src/shell-interface.h @@ -111,7 +111,7 @@ struct ShellExternalInterface : ModuleInstance::ExternalInterface { abort(); } - Literal load(Load* load, size_t addr) override { + Literal load(Load* load, Address addr) override { switch (load->type) { case i32: { switch (load->bytes) { @@ -138,7 +138,7 @@ struct ShellExternalInterface : ModuleInstance::ExternalInterface { } } - void store(Store* store, size_t addr, Literal value) override { + void store(Store* store, Address addr, Literal value) override { switch (store->type) { case i32: { switch (store->bytes) { @@ -166,7 +166,7 @@ struct ShellExternalInterface : ModuleInstance::ExternalInterface { } } - void growMemory(size_t /*oldSize*/, size_t newSize) override { + void growMemory(Address /*oldSize*/, Address newSize) override { memory.resize(newSize); } diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 584e4cab4..c40132b18 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -92,9 +92,9 @@ public: struct ExternalInterface { virtual void init(Module& wasm) {} virtual Literal callImport(Import* import, LiteralList& arguments) = 0; - virtual Literal load(Load* load, size_t addr) = 0; - virtual void store(Store* store, size_t addr, Literal value) = 0; - virtual void growMemory(size_t oldSize, size_t newSize) = 0; + virtual Literal load(Load* load, Address addr) = 0; + virtual void store(Store* store, Address addr, Literal value) = 0; + virtual void growMemory(Address oldSize, Address newSize) = 0; virtual void trap(const char* why) = 0; }; @@ -722,10 +722,10 @@ private: return ret; } - size_t memorySize; // in pages + Address memorySize; // in pages template <class LS> - size_t getFinalAddress(LS* curr, Literal ptr) { + Address getFinalAddress(LS* curr, Literal ptr) { auto trapIfGt = [this](uint64_t lhs, uint64_t rhs, const char* msg) { if (lhs > rhs) { std::stringstream ss; @@ -733,7 +733,7 @@ private: externalInterface->trap(ss.str().c_str()); } }; - uint32_t memorySizeBytes = memorySize * Memory::kPageSize; + Address memorySizeBytes = memorySize * Memory::kPageSize; uint64_t addr = ptr.type == i32 ? ptr.geti32() : ptr.geti64(); trapIfGt(curr->offset, memorySizeBytes, "offset > memory"); trapIfGt(addr, memorySizeBytes - curr->offset, "final > memory"); diff --git a/src/wasm-linker.cpp b/src/wasm-linker.cpp index a4bd97e2f..6b1fd4625 100644 --- a/src/wasm-linker.cpp +++ b/src/wasm-linker.cpp @@ -33,10 +33,10 @@ extern cashew::IString MEMORY; } -void Linker::placeStackPointer(size_t stackAllocation) { +void Linker::placeStackPointer(Address stackAllocation) { // ensure this is the first allocation assert(nextStatic == globalBase || nextStatic == 1); - const size_t pointerSize = 4; + const Address pointerSize = 4; // Unconditionally allocate space for the stack pointer. Emscripten // allocates the stack itself, and initializes the stack pointer itself. out.addStatic(pointerSize, pointerSize, "__stack_pointer"); @@ -85,7 +85,7 @@ void Linker::layout() { // Update the segments with their addresses now that they have been allocated. for (const auto& seg : out.segments) { - size_t address = staticAddresses[seg.first]; + Address address = staticAddresses[seg.first]; out.wasm.memory.segments[seg.second].offset = address; segmentsByAddress[address] = seg.second; } @@ -97,7 +97,7 @@ void Linker::layout() { // The minimum initial memory size is the amount of static variables we have // allocated. Round it up to a page, and update the page-increment versions // of initial and max - size_t initialMem = roundUpToPageSize(nextStatic); + Address initialMem = roundUpToPageSize(nextStatic); if (userInitialMemory) { if (initialMem > userInitialMemory) { Fatal() << "Specified initial memory size " << userInitialMemory << @@ -260,13 +260,13 @@ void Linker::emscriptenGlue(std::ostream& o) { Linker* parent; std::map<std::string, std::set<std::string>> sigsForCode; - std::map<std::string, size_t> ids; + std::map<std::string, Address> ids; std::set<std::string> allSigs; void visitCallImport(CallImport* curr) { if (curr->target == EMSCRIPTEN_ASM_CONST) { auto arg = curr->operands[0]->cast<Const>(); - size_t segmentIndex = parent->segmentsByAddress[arg->value.geti32()]; + Address segmentIndex = parent->segmentsByAddress[arg->value.geti32()]; std::string code = escape(&parent->out.wasm.memory.segments[segmentIndex].data[0]); int32_t id; if (ids.count(code) == 0) { diff --git a/src/wasm-linker.h b/src/wasm-linker.h index 08d6e5f1e..41c0f3c7e 100644 --- a/src/wasm-linker.h +++ b/src/wasm-linker.h @@ -71,7 +71,7 @@ class LinkerObject { LinkerObject() {} // Allocate a static object - void addStatic(size_t allocSize, size_t alignment, Name name) { + void addStatic(Address allocSize, Address alignment, Name name) { staticObjects.emplace_back(allocSize, alignment, name); } @@ -99,13 +99,15 @@ class LinkerObject { } // Add an initializer segment for the named static variable. - void addSegment(Name name, const char* data, size_t size) { - segments[name] = wasm.memory.segments.size(); + void addSegment(Name name, const char* data, Address size) { + assert(wasm.memory.segments.size() < std::numeric_limits<Address>::max()); + segments[name] = static_cast<Address>(wasm.memory.segments.size()); wasm.memory.segments.emplace_back(0, data, size); } void addSegment(Name name, std::vector<char>& data) { - segments[name] = wasm.memory.segments.size(); + assert(wasm.memory.segments.size() < std::numeric_limits<Address>::max()); + segments[name] = static_cast<Address>(wasm.memory.segments.size()); wasm.memory.segments.emplace_back(0, data); } @@ -129,10 +131,10 @@ class LinkerObject { private: struct StaticObject { - size_t allocSize; - size_t alignment; + Address allocSize; + Address alignment; Name name; - StaticObject(size_t allocSize, size_t alignment, Name name) : + StaticObject(Address allocSize, Address alignment, Name name) : allocSize(allocSize), alignment(alignment), name(name) {} }; @@ -146,7 +148,7 @@ class LinkerObject { using CallList = std::vector<Call*>; std::map<Name, CallList> undefinedFunctionCalls; - std::map<Name, size_t> segments; // name => segment index (in wasm module) + std::map<Name, Address> segments; // name => segment index (in wasm module) std::vector<Name> initializerFunctions; @@ -160,8 +162,8 @@ class LinkerObject { // applying the relocations, resulting in an executable wasm module. class Linker { public: - Linker(size_t globalBase, size_t stackAllocation, - size_t userInitialMemory, size_t userMaxMemory, + Linker(Address globalBase, Address stackAllocation, + Address userInitialMemory, Address userMaxMemory, bool ignoreUnknownSymbols, Name startFunction, bool debug) : ignoreUnknownSymbols(ignoreUnknownSymbols), @@ -221,8 +223,8 @@ class Linker { private: // Allocate a static variable and return its address in linear memory - size_t allocateStatic(size_t allocSize, size_t alignment, Name name) { - size_t address = alignAddr(nextStatic, alignment); + Address allocateStatic(Address allocSize, Address alignment, Name name) { + Address address = alignAddr(nextStatic, alignment); staticAddresses[name] = address; nextStatic = address + allocSize; return address; @@ -230,7 +232,7 @@ class Linker { // Allocate space for a stack pointer and (if stackAllocation > 0) set up a // relocation for it to point to the top of the stack. - void placeStackPointer(size_t stackAllocation); + void placeStackPointer(Address stackAllocation); template<class C> void printSet(std::ostream& o, C& c) { @@ -248,7 +250,7 @@ class Linker { // signature in the indirect function table. void makeDynCallThunks(); - static size_t roundUpToPageSize(size_t size) { + static Address roundUpToPageSize(Address size) { return (size + Memory::kPageSize - 1) & Memory::kPageMask; } @@ -270,16 +272,16 @@ class Linker { Name startFunction; // where globals can start to be statically allocated, i.e., the data segment - size_t globalBase; - size_t nextStatic; // location of next static allocation - size_t userInitialMemory; // Initial memory size (in bytes) specified by the user. - size_t userMaxMemory; // Max memory size (in bytes) specified by the user. + Address globalBase; + Address nextStatic; // location of next static allocation + Address userInitialMemory; // Initial memory size (in bytes) specified by the user. + Address userMaxMemory; // Max memory size (in bytes) specified by the user. //(after linking, this is rounded and set on the wasm object in pages) - size_t stackAllocation; + Address stackAllocation; bool debug; std::unordered_map<cashew::IString, int32_t> staticAddresses; // name => address - std::unordered_map<size_t, size_t> segmentsByAddress; // address => segment index + std::unordered_map<Address, Address> segmentsByAddress; // address => segment index std::unordered_map<cashew::IString, size_t> functionIndexes; }; diff --git a/src/wasm.h b/src/wasm.h index 2e3a63105..9f5f6820c 100644 --- a/src/wasm.h +++ b/src/wasm.h @@ -89,9 +89,11 @@ struct Name : public cashew::IString { }; // An index in a wasm module - typedef uint32_t Index; +// An address in linear memory. For now only wasm32 +typedef uint32_t Address; + // Types enum WasmType { @@ -1054,10 +1056,10 @@ public: Load() {} Load(MixedArena& allocator) {} - uint32_t bytes; + uint8_t bytes; bool signed_; - uint32_t offset; - uint32_t align; + Address offset; + Address align; Expression *ptr; // type must be set during creation, cannot be inferred @@ -1068,9 +1070,9 @@ public: Store() {} Store(MixedArena& allocator) {} - unsigned bytes; - uint32_t offset; - unsigned align; + uint8_t bytes; + Address offset; + Address align; Expression *ptr, *value; void finalize() { @@ -1264,26 +1266,26 @@ public: class Memory { public: - static const size_t kPageSize = 64 * 1024; - static const size_t kPageMask = ~(kPageSize - 1); + static const Address kPageSize = 64 * 1024; + static const Address kPageMask = ~(kPageSize - 1); struct Segment { - size_t offset; + Address offset; std::vector<char> data; // TODO: optimize Segment() {} - Segment(size_t offset, const char *init, size_t size) : offset(offset) { + Segment(Address offset, const char *init, Address size) : offset(offset) { data.resize(size); std::copy_n(init, size, data.begin()); } - Segment(size_t offset, std::vector<char>& init) : offset(offset) { + Segment(Address offset, std::vector<char>& init) : offset(offset) { data.swap(init); } }; - size_t initial, max; // sizes are in pages + Address initial, max; // sizes are in pages std::vector<Segment> segments; Name exportName; - Memory() : initial(0), max((uint32_t)-1) {} + Memory() : initial(0), max((Address)-1) {} }; class Module { |