diff options
author | Alon Zakai <alonzakai@gmail.com> | 2016-04-05 09:49:37 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2016-04-05 09:49:37 -0700 |
commit | 155223a2a0dd222817881dab85fa11166cc5bbb3 (patch) | |
tree | 7f10e15b941474c2b23c741e20ee2657c54026ca /src/binaryen-shell.cpp | |
parent | b243bf42bf89bee18ece60fb0607cf1fb70ce702 (diff) | |
parent | ea448f35ada45647c200019cc34b4315cb16cdd9 (diff) | |
download | binaryen-155223a2a0dd222817881dab85fa11166cc5bbb3.tar.gz binaryen-155223a2a0dd222817881dab85fa11166cc5bbb3.tar.bz2 binaryen-155223a2a0dd222817881dab85fa11166cc5bbb3.zip |
Merge pull request #312 from WebAssembly/webidl
WebIDL bindings
Diffstat (limited to 'src/binaryen-shell.cpp')
-rw-r--r-- | src/binaryen-shell.cpp | 169 |
1 files changed, 2 insertions, 167 deletions
diff --git a/src/binaryen-shell.cpp b/src/binaryen-shell.cpp index 8fc067562..72fad992b 100644 --- a/src/binaryen-shell.cpp +++ b/src/binaryen-shell.cpp @@ -23,6 +23,7 @@ #include <memory> #include "pass.h" +#include "shell-interface.h" #include "support/command-line.h" #include "support/file.h" #include "wasm-interpreter.h" @@ -37,172 +38,6 @@ using namespace wasm; MixedArena globalAllocator; -IString ASSERT_RETURN("assert_return"), - ASSERT_TRAP("assert_trap"), - ASSERT_INVALID("assert_invalid"), - SPECTEST("spectest"), - PRINT("print"), - INVOKE("invoke"), - EXIT("exit"); - -struct ExitException {}; -struct TrapException {}; -struct ParseException {}; - -// -// Implementation of the shell interpreter execution environment -// - -struct ShellExternalInterface : ModuleInstance::ExternalInterface { - // The underlying memory can be accessed through unaligned pointers which - // isn't well-behaved in C++. WebAssembly nonetheless expects it to behave - // properly. Avoid emitting unaligned load/store by checking for alignment - // explicitly, and performing memcpy if unaligned. - // - // The allocated memory tries to have the same alignment as the memory being - // simulated. - class Memory { - // Use char because it doesn't run afoul of aliasing rules. - std::vector<char> memory; - template <typename T> - static bool aligned(const char* address) { - static_assert(!(sizeof(T) & (sizeof(T) - 1)), "must be a power of 2"); - return 0 == (reinterpret_cast<uintptr_t>(address) & (sizeof(T) - 1)); - } - Memory(Memory&) = delete; - Memory& operator=(const Memory&) = delete; - - public: - Memory() {} - void resize(size_t newSize) { - // Ensure the smallest allocation is large enough that most allocators - // will provide page-aligned storage. This hopefully allows the - // interpreter's memory to be as aligned as the memory being simulated, - // ensuring that the performance doesn't needlessly degrade. - // - // The code is optimistic this will work until WG21's p0035r0 happens. - const size_t minSize = 1 << 12; - size_t oldSize = memory.size(); - memory.resize(std::max(minSize, newSize)); - if (newSize < oldSize && newSize < minSize) { - std::memset(&memory[newSize], 0, minSize - newSize); - } - } - template <typename T> - void set(size_t address, T value) { - if (aligned<T>(&memory[address])) { - *reinterpret_cast<T*>(&memory[address]) = value; - } else { - std::memcpy(&memory[address], &value, sizeof(T)); - } - } - template <typename T> - T get(size_t address) { - if (aligned<T>(&memory[address])) { - return *reinterpret_cast<T*>(&memory[address]); - } else { - T loaded; - std::memcpy(&loaded, &memory[address], sizeof(T)); - return loaded; - } - } - } memory; - - ShellExternalInterface() : memory() {} - - void init(Module& wasm) override { - memory.resize(wasm.memory.initial * wasm::Memory::kPageSize); - // apply memory segments - for (auto segment : wasm.memory.segments) { - assert(segment.offset + segment.size <= wasm.memory.initial * wasm::Memory::kPageSize); - for (size_t i = 0; i != segment.size; ++i) { - memory.set(segment.offset + i, segment.data[i]); - } - } - } - - Literal callImport(Import *import, ModuleInstance::LiteralList& arguments) override { - if (import->module == SPECTEST && import->base == PRINT) { - for (auto argument : arguments) { - std::cout << argument << '\n'; - } - return Literal(); - } else if (import->module == ENV && import->base == EXIT) { - // XXX hack for torture tests - std::cout << "exit()\n"; - throw ExitException(); - } - std::cout << "callImport " << import->name.str << "\n"; - abort(); - } - - Literal load(Load* load, size_t addr) override { - // ignore align - assume we are on x86 etc. which does that - switch (load->type) { - case i32: { - switch (load->bytes) { - case 1: return load->signed_ ? Literal((int32_t)memory.get<int8_t>(addr)) : Literal((int32_t)memory.get<uint8_t>(addr)); - case 2: return load->signed_ ? Literal((int32_t)memory.get<int16_t>(addr)) : Literal((int32_t)memory.get<uint16_t>(addr)); - case 4: return load->signed_ ? Literal((int32_t)memory.get<int32_t>(addr)) : Literal((int32_t)memory.get<uint32_t>(addr)); - default: abort(); - } - break; - } - case i64: { - switch (load->bytes) { - case 1: return load->signed_ ? Literal((int64_t)memory.get<int8_t>(addr)) : Literal((int64_t)memory.get<uint8_t>(addr)); - case 2: return load->signed_ ? Literal((int64_t)memory.get<int16_t>(addr)) : Literal((int64_t)memory.get<uint16_t>(addr)); - case 4: return load->signed_ ? Literal((int64_t)memory.get<int32_t>(addr)) : Literal((int64_t)memory.get<uint32_t>(addr)); - case 8: return load->signed_ ? Literal((int64_t)memory.get<int64_t>(addr)) : Literal((int64_t)memory.get<uint64_t>(addr)); - default: abort(); - } - break; - } - case f32: return Literal(memory.get<float>(addr)); - case f64: return Literal(memory.get<double>(addr)); - default: abort(); - } - } - - void store(Store* store, size_t addr, Literal value) override { - // ignore align - assume we are on x86 etc. which does that - switch (store->type) { - case i32: { - switch (store->bytes) { - case 1: memory.set<int8_t>(addr, value.geti32()); break; - case 2: memory.set<int16_t>(addr, value.geti32()); break; - case 4: memory.set<int32_t>(addr, value.geti32()); break; - default: abort(); - } - break; - } - case i64: { - switch (store->bytes) { - case 1: memory.set<int8_t>(addr, (int8_t)value.geti64()); break; - case 2: memory.set<int16_t>(addr, (int16_t)value.geti64()); break; - case 4: memory.set<int32_t>(addr, (int32_t)value.geti64()); break; - case 8: memory.set<int64_t>(addr, value.geti64()); break; - default: abort(); - } - break; - } - // write floats carefully, ensuring all bits reach memory - case f32: memory.set<int32_t>(addr, value.reinterpreti32()); break; - case f64: memory.set<int64_t>(addr, value.reinterpreti64()); break; - default: abort(); - } - } - - void growMemory(size_t /*oldSize*/, size_t newSize) override { - memory.resize(newSize); - } - - void trap(const char* why) override { - std::cerr << "[trap " << why << "]\n"; - throw TrapException(); - } -}; - // // An invocation into a module // @@ -285,7 +120,7 @@ static void run_asserts(size_t* i, bool* checked, AllocatingModule* wasm, new SExpressionWasmBuilder(wasm, *curr[1], [&]() { invalid = true; throw ParseException(); - }) + }, false) ); } catch (const ParseException&) { invalid = true; |