diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/tools/wasm-ctor-eval.cpp | 57 |
1 files changed, 38 insertions, 19 deletions
diff --git a/src/tools/wasm-ctor-eval.cpp b/src/tools/wasm-ctor-eval.cpp index f03bbec1d..b0a1c0551 100644 --- a/src/tools/wasm-ctor-eval.cpp +++ b/src/tools/wasm-ctor-eval.cpp @@ -199,12 +199,24 @@ struct CtorEvalExternalInterface : EvallingModuleInstance::ExternalInterface { EvallingModuleInstance* instance; std::map<Name, std::shared_ptr<EvallingModuleInstance>> linkedInstances; + // A representation of the contents of wasm memory as we execute. + std::vector<char> memory; + CtorEvalExternalInterface( std::map<Name, std::shared_ptr<EvallingModuleInstance>> linkedInstances_ = {}) { linkedInstances.swap(linkedInstances_); } + // Called when we want to apply the current state of execution to the Module. + // Until this is called the Module is never changed. + void applyToModule() { + // If nothing was ever written to memory then there is nothing to update. + if (!memory.empty()) { + applyMemoryToModule(); + } + } + void init(Module& wasm_, EvallingModuleInstance& instance_) override { wasm = &wasm_; instance = &instance_; @@ -365,22 +377,12 @@ private: // TODO: handle unaligned too, see shell-interface template<typename T> T* getMemory(Address address) { - // this must be in the singleton segment. resize as needed - if (wasm->memory.segments.size() == 0) { - std::vector<char> temp; - Builder builder(*wasm); - wasm->memory.segments.push_back( - Memory::Segment(builder.makeConst(int32_t(0)), temp)); - } - // memory should already have been flattened - assert(wasm->memory.segments[0].offset->cast<Const>()->value.getInteger() == - 0); + // resize the memory buffer as needed. auto max = address + sizeof(T); - auto& data = wasm->memory.segments[0].data; - if (max > data.size()) { - data.resize(max); + if (max > memory.size()) { + memory.resize(max); } - return (T*)(&data[address]); + return (T*)(&memory[address]); } template<typename T> void doStore(Address address, T value) { @@ -394,6 +396,23 @@ private: memcpy(&ret, getMemory<T>(address), sizeof(T)); return ret; } + + void applyMemoryToModule() { + // Memory must have already been flattened into the standard form: one + // segment at offset 0, or none. + if (wasm->memory.segments.empty()) { + Builder builder(*wasm); + std::vector<char> empty; + wasm->memory.segments.push_back( + Memory::Segment(builder.makeConst(int32_t(0)), empty)); + } + auto& segment = wasm->memory.segments[0]; + assert(segment.offset->cast<Const>()->value.getInteger() == 0); + + // Copy the current memory contents after execution into the Module's + // memory. + segment.data = memory; + } }; void evalCtors(Module& wasm, std::vector<std::string> ctors) { @@ -422,8 +441,6 @@ void evalCtors(Module& wasm, std::vector<std::string> ctors) { // TODO: if we knew priorities, we could reorder? for (auto& ctor : ctors) { std::cerr << "trying to eval " << ctor << '\n'; - // snapshot memory, as either the entire function is done, or none - auto memoryBefore = wasm.memory; // snapshot globals (note that STACKTOP might be modified, but should // be returned, so that works out) auto globalsBefore = instance.globals; @@ -437,16 +454,18 @@ void evalCtors(Module& wasm, std::vector<std::string> ctors) { // that's it, we failed, so stop here, cleaning up partial // memory changes first std::cerr << " ...stopping since could not eval: " << fail.why << "\n"; - wasm.memory = memoryBefore; return; } if (instance.globals != globalsBefore) { std::cerr << " ...stopping since globals modified\n"; - wasm.memory = memoryBefore; return; } std::cerr << " ...success on " << ctor << ".\n"; - // success, the entire function was evalled! + + // Success, the entire function was evalled! Apply the results of + // execution to the module. + interface.applyToModule(); + // we can nop the function (which may be used elsewhere) // and remove the export auto* exp = wasm.getExport(ctor); |