diff options
-rw-r--r-- | src/tools/wasm-split/instrumenter.cpp | 44 | ||||
-rw-r--r-- | test/lit/wasm-split/instrument-memory64.wast | 49 |
2 files changed, 72 insertions, 21 deletions
diff --git a/src/tools/wasm-split/instrumenter.cpp b/src/tools/wasm-split/instrumenter.cpp index 38ebd271a..1c825f29f 100644 --- a/src/tools/wasm-split/instrumenter.cpp +++ b/src/tools/wasm-split/instrumenter.cpp @@ -177,32 +177,12 @@ void Instrumenter::instrumentFuncs() { // the instrumented run than funtions with larger timestamps. void Instrumenter::addProfileExport(size_t numFuncs) { - // Create and export a function to dump the profile into a given memory - // buffer. The function takes the available address and buffer size as - // arguments and returns the total size of the profile. It only actually - // writes the profile if the given space is sufficient to hold it. - auto name = Names::getValidFunctionName(*wasm, config.profileExport); - auto writeProfile = Builder::makeFunction( - name, Signature({Type::i32, Type::i32}, Type::i32), {}); - writeProfile->hasExplicitName = true; - writeProfile->setLocalName(0, "addr"); - writeProfile->setLocalName(1, "size"); - // Calculate the size of the profile: // 8 bytes module hash + // 4 bytes for the timestamp for each function const size_t profileSize = 8 + 4 * numFuncs; - // Create the function body - Builder builder(*wasm); - auto getAddr = [&]() { return builder.makeLocalGet(0, Type::i32); }; - auto getSize = [&]() { return builder.makeLocalGet(1, Type::i32); }; - auto hashConst = [&]() { return builder.makeConst(int64_t(moduleHash)); }; - auto profileSizeConst = [&]() { - return builder.makeConst(int32_t(profileSize)); - }; - - // Also make sure there is a memory with enough pages to write into + // Make sure there is a memory with enough pages to write into size_t pages = (profileSize + Memory::kPageSize - 1) / Memory::kPageSize; if (wasm->memories.empty()) { wasm->addMemory(Builder::makeMemory("0")); @@ -215,6 +195,28 @@ void Instrumenter::addProfileExport(size_t numFuncs) { } } + auto ptrType = wasm->memories[0]->indexType; + + // Create and export a function to dump the profile into a given memory + // buffer. The function takes the available address and buffer size as + // arguments and returns the total size of the profile. It only actually + // writes the profile if the given space is sufficient to hold it. + auto name = Names::getValidFunctionName(*wasm, config.profileExport); + auto writeProfile = + Builder::makeFunction(name, Signature({ptrType, Type::i32}, Type::i32), {}); + writeProfile->hasExplicitName = true; + writeProfile->setLocalName(0, "addr"); + writeProfile->setLocalName(1, "size"); + + // Create the function body + Builder builder(*wasm); + auto getAddr = [&]() { return builder.makeLocalGet(0, ptrType); }; + auto getSize = [&]() { return builder.makeLocalGet(1, Type::i32); }; + auto hashConst = [&]() { return builder.makeConst(int64_t(moduleHash)); }; + auto profileSizeConst = [&]() { + return builder.makeConst(int32_t(profileSize)); + }; + // Write the hash followed by all the time stamps Expression* writeData = builder.makeStore( 8, 0, 1, getAddr(), hashConst(), Type::i64, wasm->memories[0]->name); diff --git a/test/lit/wasm-split/instrument-memory64.wast b/test/lit/wasm-split/instrument-memory64.wast new file mode 100644 index 000000000..ec737b95f --- /dev/null +++ b/test/lit/wasm-split/instrument-memory64.wast @@ -0,0 +1,49 @@ +;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. + +;; Check that the instrumentation is correct when the output memory is 64-bit. + +;; RUN: wasm-split %s -all --instrument -S -o - | filecheck %s + +;; Check that the output round trips and validates as well +;; RUN: wasm-split %s -all --instrument -g -o %t +;; RUN: wasm-opt %t -all --print | filecheck %s + +(module + (import "env" "foo" (func $foo)) + (export "bar" (func $bar)) + + (memory $mem i64 1 1) + + (func $bar + (call $foo) + ) + (func $baz (param i32) (result i32) + (local.get 0) + ) +) + +;; Check that the $addr parameter is an i64. + +;; CHECK: (func $__write_profile (type $2) (param $addr i64) (param $size i32) (result i32) +;; CHECK-NEXT: (if +;; CHECK-NEXT: (i32.ge_u +;; CHECK-NEXT: (local.get $size) +;; CHECK-NEXT: (i32.const 16) +;; CHECK-NEXT: ) +;; CHECK-NEXT: (block +;; CHECK-NEXT: (i64.store align=1 +;; CHECK-NEXT: (local.get $addr) +;; CHECK-NEXT: (i64.const {{.*}}) +;; CHECK-NEXT: ) +;; CHECK-NEXT: (i32.store offset=8 align=1 +;; CHECK-NEXT: (local.get $addr) +;; CHECK-NEXT: (global.get $bar_timestamp) +;; CHECK-NEXT: ) +;; CHECK-NEXT: (i32.store offset=12 align=1 +;; CHECK-NEXT: (local.get $addr) +;; CHECK-NEXT: (global.get $baz_timestamp) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) +;; CHECK-NEXT: (i32.const 16) +;; CHECK-NEXT: ) |