summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDerek Schuff <dschuff@chromium.org>2016-05-11 15:34:49 -0700
committerDerek Schuff <dschuff@chromium.org>2016-05-11 15:34:49 -0700
commitac827e35fec84074d9d8141ca2c94ad01ca9c5c3 (patch)
tree38f1c4b00de8af9f0545974847e4ab04f13b45fd
parent9c79f86a3f518c60840b416287a5d26502911ad6 (diff)
downloadbinaryen-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.h26
-rw-r--r--src/shell-interface.h6
-rw-r--r--src/wasm-interpreter.h12
-rw-r--r--src/wasm-linker.cpp12
-rw-r--r--src/wasm-linker.h42
-rw-r--r--src/wasm.h30
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 {