mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 21:01:08 +00:00
Bug 1827704 - Migrate to the upstream wasm2c for RLBox sandboxing r=glandium
Differential Revision: https://phabricator.services.mozilla.com/D175439
This commit is contained in:
parent
4d6ebc058d
commit
ed0bb19d78
6
config/external/rlbox/rlbox_config.h
vendored
6
config/external/rlbox/rlbox_config.h
vendored
@ -21,4 +21,10 @@
|
||||
// fixed.
|
||||
#define RLBOX_EMBEDDER_PROVIDES_TLS_STATIC_VARIABLES
|
||||
|
||||
// When instantiating a wasm sandbox, rlbox requires the name of the wasm module
|
||||
// being instantiated. LLVM and wasm2c use the module name by choosing the name
|
||||
// used to generate the wasm file. In Firefox this is a static library called
|
||||
// rlbox
|
||||
#define RLBOX_WASM2C_MODULE_NAME rlbox
|
||||
|
||||
#endif
|
||||
|
13
config/external/rlbox_wasm2c_sandbox/moz.build
vendored
13
config/external/rlbox_wasm2c_sandbox/moz.build
vendored
@ -6,8 +6,19 @@
|
||||
|
||||
EXPORTS.mozilla.rlbox += [
|
||||
"/third_party/rlbox_wasm2c_sandbox/include/rlbox_wasm2c_sandbox.hpp",
|
||||
"/third_party/rlbox_wasm2c_sandbox/include/rlbox_wasm2c_tls.hpp",
|
||||
]
|
||||
EXPORTS += [
|
||||
"/third_party/rlbox_wasm2c_sandbox/include/wasm2c_rt_mem.h",
|
||||
"/third_party/rlbox_wasm2c_sandbox/include/wasm2c_rt_minwasi.h",
|
||||
]
|
||||
|
||||
SOURCES += ["rlbox_wasm2c_thread_locals.cpp"]
|
||||
SOURCES += [
|
||||
"/third_party/rlbox_wasm2c_sandbox/src/wasm2c_rt_mem.c",
|
||||
"/third_party/rlbox_wasm2c_sandbox/src/wasm2c_rt_minwasi.c",
|
||||
"rlbox_wasm2c_thread_locals.cpp",
|
||||
]
|
||||
|
||||
LOCAL_INCLUDES += ["/third_party/wasm2c/wasm2c/"]
|
||||
|
||||
FINAL_LIBRARY = "xul"
|
||||
|
@ -7,10 +7,10 @@ bugzilla:
|
||||
origin:
|
||||
name: rlbox_wasm2c_sandbox
|
||||
description: rlbox integration for the wasm2c sandboxed code
|
||||
url: https://github.com/PLSysSec/rlbox_wasm2c_sandbox
|
||||
url: https://github.com/PLSysSec/rlbox_wasm2c_sandbox/tree/upstream-wasm2c
|
||||
|
||||
release: commit 54e8469095e7929c66aeecdc26f23f502b986218 (2021-12-08T08:12:13Z).
|
||||
revision: 54e8469095e7929c66aeecdc26f23f502b986218
|
||||
release: 7e4ff0ebca2c7644a297bfe51a53b9904f0999b2 (2023-04-13T05:07:28Z).
|
||||
revision: 7e4ff0ebca2c7644a297bfe51a53b9904f0999b2
|
||||
|
||||
license: MIT
|
||||
license-file: LICENSE
|
||||
@ -32,5 +32,3 @@ vendoring:
|
||||
- CMakeLists.txt
|
||||
- LibrarySandbox.md
|
||||
- README.md
|
||||
|
||||
|
||||
|
@ -10,10 +10,8 @@
|
||||
|
||||
// Load general firefox configuration of RLBox
|
||||
# include "mozilla/rlbox/rlbox_config.h"
|
||||
|
||||
# include "mozilla/rlbox/rlbox_wasm2c_sandbox.hpp"
|
||||
|
||||
# include "mozilla/rlbox/rlbox.hpp"
|
||||
# include "mozilla/rlbox/rlbox_wasm2c_tls.hpp"
|
||||
# include "wasm-rt.h"
|
||||
|
||||
# include "nsExceptionHandler.h"
|
||||
|
||||
@ -26,16 +24,13 @@ extern "C" {
|
||||
|
||||
// Any error encountered by the wasm2c runtime or wasm sandboxed library code
|
||||
// is configured to call the below trap handler.
|
||||
void moz_wasm2c_trap_handler(const char* msg) {
|
||||
MOZ_CRASH_UNSAFE_PRINTF("wasm2c crash: %s", msg);
|
||||
void moz_wasm2c_trap_handler(wasm_rt_trap_t code) {
|
||||
MOZ_CRASH_UNSAFE_PRINTF("wasm2c crash: %s", wasm_rt_strerror(code));
|
||||
}
|
||||
|
||||
// The below function is called if a malloc in sandboxed code returns null
|
||||
// This indicates that the sandbox has run out of memory.
|
||||
void moz_wasm2c_malloc_failed(uint32_t size) {
|
||||
// We don't use the allocation size information for now
|
||||
(void)size;
|
||||
|
||||
void moz_wasm2c_memgrow_failed() {
|
||||
CrashReporter::AnnotateCrashReport(
|
||||
CrashReporter::Annotation::WasmLibrarySandboxMallocFailed, true);
|
||||
}
|
||||
|
@ -4,10 +4,13 @@
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
LOCAL_INCLUDES += ["/third_party/wasm2c/"]
|
||||
LOCAL_INCLUDES += [
|
||||
"/third_party/picosha2/",
|
||||
"/third_party/wasm2c/include/",
|
||||
]
|
||||
|
||||
GeneratedFile(
|
||||
"config.h",
|
||||
"wabt/config.h",
|
||||
script="preprocess_wasm2c_config.py",
|
||||
entry_point="generate_config",
|
||||
inputs=["/third_party/wasm2c/src/config.h.in"],
|
||||
@ -18,6 +21,8 @@ HOST_SOURCES += [
|
||||
"/third_party/wasm2c/src/apply-names.cc",
|
||||
"/third_party/wasm2c/src/binary-reader-ir.cc",
|
||||
"/third_party/wasm2c/src/binary-reader-logging.cc",
|
||||
"/third_party/wasm2c/src/binary-reader-objdump.cc",
|
||||
"/third_party/wasm2c/src/binary-reader-opcnt.cc",
|
||||
"/third_party/wasm2c/src/binary-reader.cc",
|
||||
"/third_party/wasm2c/src/binary-writer-spec.cc",
|
||||
"/third_party/wasm2c/src/binary-writer.cc",
|
||||
@ -27,12 +32,12 @@ HOST_SOURCES += [
|
||||
"/third_party/wasm2c/src/common.cc",
|
||||
"/third_party/wasm2c/src/config.cc",
|
||||
"/third_party/wasm2c/src/decompiler.cc",
|
||||
"/third_party/wasm2c/src/emscripten-helpers.cc",
|
||||
"/third_party/wasm2c/src/error-formatter.cc",
|
||||
"/third_party/wasm2c/src/expr-visitor.cc",
|
||||
"/third_party/wasm2c/src/feature.cc",
|
||||
"/third_party/wasm2c/src/filenames.cc",
|
||||
"/third_party/wasm2c/src/generate-names.cc",
|
||||
"/third_party/wasm2c/src/hash-util.cc",
|
||||
"/third_party/wasm2c/src/ir-util.cc",
|
||||
"/third_party/wasm2c/src/ir.cc",
|
||||
"/third_party/wasm2c/src/leb128.cc",
|
||||
@ -43,9 +48,9 @@ HOST_SOURCES += [
|
||||
"/third_party/wasm2c/src/opcode.cc",
|
||||
"/third_party/wasm2c/src/option-parser.cc",
|
||||
"/third_party/wasm2c/src/resolve-names.cc",
|
||||
"/third_party/wasm2c/src/sha256.cc",
|
||||
"/third_party/wasm2c/src/shared-validator.cc",
|
||||
"/third_party/wasm2c/src/stream.cc",
|
||||
"/third_party/wasm2c/src/string-view.cc",
|
||||
"/third_party/wasm2c/src/token.cc",
|
||||
"/third_party/wasm2c/src/tracing.cc",
|
||||
"/third_party/wasm2c/src/type-checker.cc",
|
||||
@ -59,6 +64,10 @@ HOST_SOURCES += [
|
||||
# wasm2c sources
|
||||
HOST_SOURCES += [
|
||||
"/third_party/wasm2c/src/c-writer.cc",
|
||||
"/third_party/wasm2c/src/prebuilt/wasm2c_header_bottom.cc",
|
||||
"/third_party/wasm2c/src/prebuilt/wasm2c_header_top.cc",
|
||||
"/third_party/wasm2c/src/prebuilt/wasm2c_source_declarations.cc",
|
||||
"/third_party/wasm2c/src/prebuilt/wasm2c_source_includes.cc",
|
||||
"/third_party/wasm2c/src/tools/wasm2c.cc",
|
||||
]
|
||||
|
||||
|
30
config/external/wasm2c_sandbox_compiler/moz.yaml
vendored
30
config/external/wasm2c_sandbox_compiler/moz.yaml
vendored
@ -7,44 +7,40 @@ bugzilla:
|
||||
origin:
|
||||
name: wasm2c_sandbox_compiler
|
||||
description: wasm2c fork used for rlbox sandboxing
|
||||
url: https://github.com/PLSysSec/wasm2c_sandbox_compiler
|
||||
url: https://github.com/WebAssembly/wabt
|
||||
|
||||
release: 3266be52998117f47b490d026b02e4193d5d3338 (2022-11-24T04:56:29Z).
|
||||
revision: 3266be52998117f47b490d026b02e4193d5d3338
|
||||
release: ad5f1385fa7afe29e98d69b6167132162675228f (2023-04-13T05:14:45Z).
|
||||
revision: ad5f1385fa7afe29e98d69b6167132162675228f
|
||||
|
||||
license: Apache-2.0
|
||||
license-file: LICENSE
|
||||
|
||||
vendoring:
|
||||
url: https://github.com/PLSysSec/wasm2c_sandbox_compiler
|
||||
url: https://github.com/WebAssembly/wabt
|
||||
source-hosting: github
|
||||
vendor-directory: third_party/wasm2c
|
||||
|
||||
# ideally we would have exclude *, and the explicitly include certain folders, but this does not work
|
||||
# so just explicitly exclude what we don't want for now
|
||||
exclude:
|
||||
# dirs
|
||||
- cmake
|
||||
- docs
|
||||
- fuzz-in
|
||||
- include/wabt/interp
|
||||
- man
|
||||
- scripts
|
||||
- src/interp
|
||||
- src/template
|
||||
- test
|
||||
- third_party
|
||||
- src/interp
|
||||
- wasm2c/examples
|
||||
# files
|
||||
- .clang-format
|
||||
- .flake8
|
||||
- .gitattributes
|
||||
- .gitignore
|
||||
- .gitmodules
|
||||
- .style.yapf
|
||||
- .*
|
||||
- CMakeLists.txt
|
||||
- Contributing.md
|
||||
- Makefile
|
||||
- README.md
|
||||
- ubsan.blacklist
|
||||
- wasm2c/examples/hello/.gitignore
|
||||
- wasm2c/wasm-rt-runner.c
|
||||
- wasm2c/wasm-rt-static-runner.c
|
||||
- src/tools/s*
|
||||
- src/tools/wasm-*
|
||||
- src/tools/wast*
|
||||
- src/tools/wat*
|
||||
- src/tools/wasm2w*
|
||||
|
@ -15,13 +15,16 @@ import itertools
|
||||
# This python script knows how to replace the following variables normally configured by cmake for
|
||||
# the wasm2c source
|
||||
known_vars = [
|
||||
"#cmakedefine CMAKE_PROJECT_VERSION",
|
||||
'#cmakedefine WABT_VERSION_STRING "@WABT_VERSION_STRING@"',
|
||||
"#cmakedefine WABT_DEBUG @WABT_DEBUG@",
|
||||
"#cmakedefine01 HAVE_ALLOCA_H",
|
||||
"#cmakedefine01 HAVE_UNISTD_H",
|
||||
"#cmakedefine01 HAVE_SNPRINTF",
|
||||
"#cmakedefine01 HAVE_SSIZE_T",
|
||||
"#cmakedefine01 HAVE_STRCASECMP",
|
||||
"#cmakedefine01 HAVE_WIN32_VT100",
|
||||
"#cmakedefine01 WABT_BIG_ENDIAN",
|
||||
"#cmakedefine01 HAVE_OPENSSL_SHA_H",
|
||||
"#cmakedefine01 COMPILER_IS_CLANG",
|
||||
"#cmakedefine01 COMPILER_IS_GNU",
|
||||
"#cmakedefine01 COMPILER_IS_MSVC",
|
||||
@ -31,13 +34,14 @@ known_vars = [
|
||||
|
||||
# The above variables are replaced with the code shown below
|
||||
replaced_variables = """
|
||||
#include "mozilla-config.h"
|
||||
|
||||
#define CMAKE_PROJECT_VERSION "Firefox-in-tree-version"
|
||||
|
||||
// mozilla-config.h defines the following which is used
|
||||
// - HAVE_ALLOCA_H
|
||||
// - HAVE_UNISTD_H
|
||||
#include "mozilla-config.h"
|
||||
|
||||
#define WABT_VERSION_STRING "Firefox-in-tree-version"
|
||||
|
||||
#define WABT_DEBUG 0
|
||||
|
||||
#ifdef _WIN32
|
||||
// Ignore whatever is set in mozilla-config.h wrt alloca because it is
|
||||
@ -55,6 +59,21 @@ replaced_variables = """
|
||||
#define HAVE_WIN32_VT100 0
|
||||
#endif
|
||||
|
||||
#if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && defined(__ORDER_BIG_ENDIAN__)
|
||||
# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
# define WABT_BIG_ENDIAN 0
|
||||
# elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
# define WABT_BIG_ENDIAN 1
|
||||
# else
|
||||
# error "Can't handle mixed-endian architectures"
|
||||
# endif
|
||||
#else
|
||||
# error "Don't know how to determine endianness"
|
||||
#endif
|
||||
|
||||
/* Use internal Pico-SHA. Never use OpenSSL */
|
||||
#define HAVE_OPENSSL_SHA_H 0
|
||||
|
||||
/* Whether snprintf is defined by stdio.h */
|
||||
#define HAVE_SNPRINTF 1
|
||||
|
||||
|
@ -499,7 +499,7 @@ $(LIBRARY): $(OBJS) $(STATIC_LIBS) $(EXTRA_DEPS) $(GLOBAL_DEPS)
|
||||
$(WASM_ARCHIVE): $(CWASMOBJS) $(CPPWASMOBJS) $(STATIC_LIBS) $(EXTRA_DEPS) $(GLOBAL_DEPS)
|
||||
$(REPORT_BUILD_VERBOSE)
|
||||
$(RM) $(WASM_ARCHIVE)
|
||||
$(WASM_CXX) -o $@ -Wl,--export-all -Wl,--stack-first -Wl,-z,stack-size=$(if $(MOZ_OPTIMIZE),262144,1048576) -Wl,--no-entry -Wl,--growable-table $(CWASMOBJS) $(CPPWASMOBJS) -lwasi-emulated-process-clocks
|
||||
$(WASM_CXX) -o $@ -Wl,--export-all -Wl,--stack-first -Wl,-z,stack-size=$(if $(MOZ_OPTIMIZE),262144,1048576) -Wl,--no-entry -Wl,--growable-table -Wl,--import-memory -Wl,--import-table $(CWASMOBJS) $(CPPWASMOBJS) -lwasi-emulated-process-clocks
|
||||
|
||||
$(addsuffix .c,$(WASM_ARCHIVE)): $(WASM_ARCHIVE) $(DIST)/host/bin/wasm2c$(HOST_BIN_SUFFIX)
|
||||
$(DIST)/host/bin/wasm2c$(HOST_BIN_SUFFIX) -o $@ $<
|
||||
|
@ -36,15 +36,12 @@ RLBoxHunspell* RLBoxHunspell::Create(const nsCString& affpath,
|
||||
|
||||
#if defined(MOZ_WASM_SANDBOXING_HUNSPELL) && !defined(HAVE_64BIT_BUILD)
|
||||
// By default, the rlbox sandbox size is smaller on 32-bit builds than the max
|
||||
// 4GB We may need to ask for a larger sandbox size for hunspell to spellcheck
|
||||
// in some locales See Bug 1739669 for more details
|
||||
// 4GB. We may need to ask for a larger sandbox size for hunspell to
|
||||
// spellcheck in some locales See Bug 1739669 for more details
|
||||
|
||||
const uint64_t defaultMaxSizeForSandbox =
|
||||
wasm_rt_get_default_max_linear_memory_size();
|
||||
|
||||
// We first get the size of the dictionary.
|
||||
// This is actually the first read we try on dpath and it might fail for
|
||||
// whatever filesystem reasons (invalid path, unaccessible, ...).
|
||||
// We first get the size of the dictionary. This is actually the first read we
|
||||
// try on dpath and it might fail for whatever filesystem reasons (invalid
|
||||
// path, unaccessible, ...).
|
||||
Result<int64_t, nsresult> dictSizeResult =
|
||||
mozHunspellFileMgrHost::GetSize(dpath);
|
||||
NS_ENSURE_TRUE(dictSizeResult.isOk(), nullptr);
|
||||
@ -59,13 +56,12 @@ RLBoxHunspell* RLBoxHunspell::Create(const nsCString& affpath,
|
||||
// and bug 1739761 for the analysis behind this.
|
||||
const uint64_t expectedMaxMemory = static_cast<uint64_t>(4.8 * dictSize);
|
||||
|
||||
// If we expect a higher memory usage, override the defaults
|
||||
// else stick with the defaults for the sandbox
|
||||
const uint64_t selectedMaxMemory =
|
||||
std::max(expectedMaxMemory, defaultMaxSizeForSandbox);
|
||||
// Get a capacity of at least the expected size
|
||||
const w2c_mem_capacity capacity = get_valid_wasm2c_memory_capacity(
|
||||
expectedMaxMemory, true /* wasm's 32-bit memory */);
|
||||
|
||||
bool success = sandbox->create_sandbox(/* shouldAbortOnFailure = */ false,
|
||||
selectedMaxMemory);
|
||||
bool success =
|
||||
sandbox->create_sandbox(/* shouldAbortOnFailure = */ false, &capacity);
|
||||
#elif defined(MOZ_WASM_SANDBOXING_HUNSPELL)
|
||||
bool success = sandbox->create_sandbox(/* shouldAbortOnFailure = */ false);
|
||||
#else
|
||||
|
@ -55,7 +55,9 @@ UniquePtr<RLBoxSandboxDataBase> RLBoxWOFF2SandboxPool::CreateSandboxData(
|
||||
auto sandbox = MakeUnique<rlbox_sandbox_woff2>();
|
||||
|
||||
#if defined(MOZ_WASM_SANDBOXING_WOFF2)
|
||||
bool createOK = sandbox->create_sandbox(/* infallible = */ false, aSize);
|
||||
const w2c_mem_capacity capacity =
|
||||
get_valid_wasm2c_memory_capacity(aSize, true /* 32-bit wasm memory*/);
|
||||
bool createOK = sandbox->create_sandbox(/* infallible = */ false, &capacity);
|
||||
#else
|
||||
bool createOK = sandbox->create_sandbox();
|
||||
#endif
|
||||
|
@ -1415,7 +1415,9 @@ RLBoxExpatSandboxPool::CreateSandboxData(uint64_t aSize) {
|
||||
auto sandbox = mozilla::MakeUnique<rlbox_sandbox_expat>();
|
||||
|
||||
#ifdef MOZ_WASM_SANDBOXING_EXPAT
|
||||
bool create_ok = sandbox->create_sandbox(/* infallible = */ false, aSize);
|
||||
const w2c_mem_capacity capacity =
|
||||
get_valid_wasm2c_memory_capacity(aSize, true /* 32-bit wasm memory*/);
|
||||
bool create_ok = sandbox->create_sandbox(/* infallible = */ false, &capacity);
|
||||
#else
|
||||
bool create_ok = sandbox->create_sandbox();
|
||||
#endif
|
||||
|
@ -17,20 +17,26 @@ EXPORTS += [
|
||||
SOURCES += [
|
||||
"!rlbox.wasm.c",
|
||||
"/third_party/wasm2c/wasm2c/wasm-rt-impl.c",
|
||||
"/third_party/wasm2c/wasm2c/wasm-rt-os-unix.c",
|
||||
"/third_party/wasm2c/wasm2c/wasm-rt-os-win.c",
|
||||
"/third_party/wasm2c/wasm2c/wasm-rt-wasi.c",
|
||||
]
|
||||
|
||||
# Configure the wasm runtime to use a custom trap handler that calls MOZ_CRASH
|
||||
DEFINES["WASM_RT_CUSTOM_TRAP_HANDLER"] = "moz_wasm2c_trap_handler"
|
||||
# Configuration for the wasm2c runtime used by RLBox
|
||||
|
||||
# Configure the wasm runtime to invoke a callback when a malloc fails inside
|
||||
# the sandbox. This information is used to annotate crash reports
|
||||
DEFINES["WASM2C_MALLOC_FAIL_CALLBACK"] = "moz_wasm2c_malloc_failed"
|
||||
# Use a mmap style allocation
|
||||
DEFINES["WASM_RT_USE_MMAP"] = 1
|
||||
|
||||
# Don't use internal signal handler as Firefox already provides one
|
||||
DEFINES["WASM_RT_SKIP_SIGNAL_RECOVERY"] = 1
|
||||
|
||||
# We provide a custom trap handler that calls MOZ_CRASH
|
||||
DEFINES["WASM_RT_TRAP_HANDLER"] = "moz_wasm2c_trap_handler"
|
||||
|
||||
# Don't limit the nested call depth
|
||||
DEFINES["WASM_RT_USE_STACK_DEPTH_COUNT"] = 0
|
||||
|
||||
# Configure the wasm runtime to invoke a callback when a Wasm memory growth
|
||||
# fails inside the sandbox. This information is used to annotate crash reports.
|
||||
DEFINES["WASM_RT_GROW_FAILED_HANDLER"] = "moz_wasm2c_memgrow_failed"
|
||||
|
||||
# Configuration that removes the wasm2c functions from shared library exports
|
||||
DEFINES["WASM_DONT_EXPORT_FUNCS"] = True
|
||||
|
||||
FINAL_LIBRARY = "xul"
|
||||
|
||||
|
21
third_party/picosha2/LICENSE
vendored
Normal file
21
third_party/picosha2/LICENSE
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 okdshin
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
138
third_party/picosha2/README.md
vendored
Normal file
138
third_party/picosha2/README.md
vendored
Normal file
@ -0,0 +1,138 @@
|
||||
# PicoSHA2 - a C++ SHA256 hash generator
|
||||
|
||||
Copyright © 2017 okdshin
|
||||
|
||||
## Introduction
|
||||
|
||||
PicoSHA2 is a tiny SHA256 hash generator for C++ with following properties:
|
||||
|
||||
- header-file only
|
||||
- no external dependencies (only uses standard C++ libraries)
|
||||
- STL-friendly
|
||||
- licensed under MIT License
|
||||
|
||||
## Generating SHA256 hash and hash hex string
|
||||
|
||||
```c++
|
||||
// any STL sequantial container (vector, list, dequeue...)
|
||||
std::string src_str = "The quick brown fox jumps over the lazy dog";
|
||||
|
||||
std::vector<unsigned char> hash(picosha2::k_digest_size);
|
||||
picosha2::hash256(src_str.begin(), src_str.end(), hash.begin(), hash.end());
|
||||
|
||||
std::string hex_str = picosha2::bytes_to_hex_string(hash.begin(), hash.end());
|
||||
```
|
||||
|
||||
## Generating SHA256 hash and hash hex string from byte stream
|
||||
|
||||
```c++
|
||||
picosha2::hash256_one_by_one hasher;
|
||||
...
|
||||
hasher.process(block.begin(), block.end());
|
||||
...
|
||||
hasher.finish();
|
||||
|
||||
std::vector<unsigned char> hash(picosha2::k_digest_size);
|
||||
hasher.get_hash_bytes(hash.begin(), hash.end());
|
||||
|
||||
std::string hex_str = picosha2::get_hash_hex_string(hasher);
|
||||
```
|
||||
|
||||
The file `example/interactive_hasher.cpp` has more detailed information.
|
||||
|
||||
## Generating SHA256 hash from a binary file
|
||||
|
||||
```c++
|
||||
std::ifstream f("file.txt", std::ios::binary);
|
||||
std::vector<unsigned char> s(picosha2::k_digest_size);
|
||||
picosha2::hash256(f, s.begin(), s.end());
|
||||
```
|
||||
|
||||
This `hash256` may use less memory than reading whole of the file.
|
||||
|
||||
## Generating SHA256 hash hex string from std::string
|
||||
|
||||
```c++
|
||||
std::string src_str = "The quick brown fox jumps over the lazy dog";
|
||||
std::string hash_hex_str;
|
||||
picosha2::hash256_hex_string(src_str, hash_hex_str);
|
||||
std::cout << hash_hex_str << std::endl;
|
||||
//this output is "d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592"
|
||||
```
|
||||
|
||||
```c++
|
||||
std::string src_str = "The quick brown fox jumps over the lazy dog";
|
||||
std::string hash_hex_str = picosha2::hash256_hex_string(src_str);
|
||||
std::cout << hash_hex_str << std::endl;
|
||||
//this output is "d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592"
|
||||
```
|
||||
|
||||
```c++
|
||||
std::string src_str = "The quick brown fox jumps over the lazy dog.";//add '.'
|
||||
std::string hash_hex_str = picosha2::hash256_hex_string(src_str.begin(), src_str.end());
|
||||
std::cout << hash_hex_str << std::endl;
|
||||
//this output is "ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c"
|
||||
```
|
||||
|
||||
## Generating SHA256 hash hex string from byte sequence
|
||||
|
||||
```c++
|
||||
std::vector<unsigned char> src_vect(...);
|
||||
std::string hash_hex_str;
|
||||
picosha2::hash256_hex_string(src_vect, hash_hex_str);
|
||||
```
|
||||
|
||||
```c++
|
||||
std::vector<unsigned char> src_vect(...);
|
||||
std::string hash_hex_str = picosha2::hash256_hex_string(src_vect);
|
||||
```
|
||||
|
||||
```c++
|
||||
unsigned char src_c_array[picosha2::k_digest_size] = {...};
|
||||
std::string hash_hex_str;
|
||||
picosha2::hash256_hex_string(src_c_array, src_c_array+picosha2::k_digest_size, hash_hex_str);
|
||||
```
|
||||
|
||||
```c++
|
||||
unsigned char src_c_array[picosha2::k_digest_size] = {...};
|
||||
std::string hash_hex_str = picosha2::hash256_hex_string(src_c_array, src_c_array+picosha2::k_digest_size);
|
||||
```
|
||||
|
||||
|
||||
## Generating SHA256 hash byte sequence from STL sequential container
|
||||
|
||||
```c++
|
||||
//any STL sequantial container (vector, list, dequeue...)
|
||||
std::string src_str = "The quick brown fox jumps over the lazy dog";
|
||||
|
||||
//any STL sequantial containers (vector, list, dequeue...)
|
||||
std::vector<unsigned char> hash(picosha2::k_digest_size);
|
||||
|
||||
// in: container, out: container
|
||||
picosha2::hash256(src_str, hash);
|
||||
```
|
||||
|
||||
```c++
|
||||
//any STL sequantial container (vector, list, dequeue...)
|
||||
std::string src_str = "The quick brown fox jumps over the lazy dog";
|
||||
|
||||
//any STL sequantial containers (vector, list, dequeue...)
|
||||
std::vector<unsigned char> hash(picosha2::k_digest_size);
|
||||
|
||||
// in: iterator pair, out: contaner
|
||||
picosha2::hash256(src_str.begin(), src_str.end(), hash);
|
||||
```
|
||||
|
||||
```c++
|
||||
std::string src_str = "The quick brown fox jumps over the lazy dog";
|
||||
unsigned char hash_byte_c_array[picosha2::k_digest_size];
|
||||
// in: container, out: iterator(pointer) pair
|
||||
picosha2::hash256(src_str, hash_byte_c_array, hash_byte_c_array+picosha2::k_digest_size);
|
||||
```
|
||||
|
||||
```c++
|
||||
std::string src_str = "The quick brown fox jumps over the lazy dog";
|
||||
std::vector<unsigned char> hash(picosha2::k_digest_size);
|
||||
// in: iterator pair, out: iterator pair
|
||||
picosha2::hash256(src_str.begin(), src_str.end(), hash.begin(), hash.end());
|
||||
```
|
25
third_party/picosha2/moz.yaml
vendored
Normal file
25
third_party/picosha2/moz.yaml
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
schema: 1
|
||||
|
||||
bugzilla:
|
||||
product: Core
|
||||
component: "General"
|
||||
|
||||
origin:
|
||||
name: picosha2
|
||||
description: tiny header-only SHA256 hash generator for C++
|
||||
url: https://github.com/okdshin/PicoSHA2
|
||||
|
||||
release: 27fcf6979298949e8a462e16d09a0351c18fcaf2 (2022-08-08T10:31:07Z).
|
||||
revision: 27fcf6979298949e8a462e16d09a0351c18fcaf2
|
||||
|
||||
license: MIT
|
||||
license-file: LICENSE
|
||||
|
||||
vendoring:
|
||||
url: https://github.com/okdshin/PicoSHA2
|
||||
source-hosting: github
|
||||
vendor-directory: third_party/picosha2
|
||||
exclude:
|
||||
- example/*
|
||||
- test/*
|
||||
- CMakeLists.txt
|
377
third_party/picosha2/picosha2.h
vendored
Normal file
377
third_party/picosha2/picosha2.h
vendored
Normal file
@ -0,0 +1,377 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (C) 2017 okdshin
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
#ifndef PICOSHA2_H
|
||||
#define PICOSHA2_H
|
||||
// picosha2:20140213
|
||||
|
||||
#ifndef PICOSHA2_BUFFER_SIZE_FOR_INPUT_ITERATOR
|
||||
#define PICOSHA2_BUFFER_SIZE_FOR_INPUT_ITERATOR \
|
||||
1048576 //=1024*1024: default is 1MB memory
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <iterator>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
namespace picosha2 {
|
||||
typedef unsigned long word_t;
|
||||
typedef unsigned char byte_t;
|
||||
|
||||
static const size_t k_digest_size = 32;
|
||||
|
||||
namespace detail {
|
||||
inline byte_t mask_8bit(byte_t x) { return x & 0xff; }
|
||||
|
||||
inline word_t mask_32bit(word_t x) { return x & 0xffffffff; }
|
||||
|
||||
const word_t add_constant[64] = {
|
||||
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
|
||||
0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
|
||||
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
|
||||
0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||||
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
|
||||
0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
|
||||
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
|
||||
0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
||||
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
|
||||
0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
|
||||
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2};
|
||||
|
||||
const word_t initial_message_digest[8] = {0x6a09e667, 0xbb67ae85, 0x3c6ef372,
|
||||
0xa54ff53a, 0x510e527f, 0x9b05688c,
|
||||
0x1f83d9ab, 0x5be0cd19};
|
||||
|
||||
inline word_t ch(word_t x, word_t y, word_t z) { return (x & y) ^ ((~x) & z); }
|
||||
|
||||
inline word_t maj(word_t x, word_t y, word_t z) {
|
||||
return (x & y) ^ (x & z) ^ (y & z);
|
||||
}
|
||||
|
||||
inline word_t rotr(word_t x, std::size_t n) {
|
||||
assert(n < 32);
|
||||
return mask_32bit((x >> n) | (x << (32 - n)));
|
||||
}
|
||||
|
||||
inline word_t bsig0(word_t x) { return rotr(x, 2) ^ rotr(x, 13) ^ rotr(x, 22); }
|
||||
|
||||
inline word_t bsig1(word_t x) { return rotr(x, 6) ^ rotr(x, 11) ^ rotr(x, 25); }
|
||||
|
||||
inline word_t shr(word_t x, std::size_t n) {
|
||||
assert(n < 32);
|
||||
return x >> n;
|
||||
}
|
||||
|
||||
inline word_t ssig0(word_t x) { return rotr(x, 7) ^ rotr(x, 18) ^ shr(x, 3); }
|
||||
|
||||
inline word_t ssig1(word_t x) { return rotr(x, 17) ^ rotr(x, 19) ^ shr(x, 10); }
|
||||
|
||||
template <typename RaIter1, typename RaIter2>
|
||||
void hash256_block(RaIter1 message_digest, RaIter2 first, RaIter2 last) {
|
||||
assert(first + 64 == last);
|
||||
static_cast<void>(last); // for avoiding unused-variable warning
|
||||
word_t w[64];
|
||||
std::fill(w, w + 64, word_t(0));
|
||||
for (std::size_t i = 0; i < 16; ++i) {
|
||||
w[i] = (static_cast<word_t>(mask_8bit(*(first + i * 4))) << 24) |
|
||||
(static_cast<word_t>(mask_8bit(*(first + i * 4 + 1))) << 16) |
|
||||
(static_cast<word_t>(mask_8bit(*(first + i * 4 + 2))) << 8) |
|
||||
(static_cast<word_t>(mask_8bit(*(first + i * 4 + 3))));
|
||||
}
|
||||
for (std::size_t i = 16; i < 64; ++i) {
|
||||
w[i] = mask_32bit(ssig1(w[i - 2]) + w[i - 7] + ssig0(w[i - 15]) +
|
||||
w[i - 16]);
|
||||
}
|
||||
|
||||
word_t a = *message_digest;
|
||||
word_t b = *(message_digest + 1);
|
||||
word_t c = *(message_digest + 2);
|
||||
word_t d = *(message_digest + 3);
|
||||
word_t e = *(message_digest + 4);
|
||||
word_t f = *(message_digest + 5);
|
||||
word_t g = *(message_digest + 6);
|
||||
word_t h = *(message_digest + 7);
|
||||
|
||||
for (std::size_t i = 0; i < 64; ++i) {
|
||||
word_t temp1 = h + bsig1(e) + ch(e, f, g) + add_constant[i] + w[i];
|
||||
word_t temp2 = bsig0(a) + maj(a, b, c);
|
||||
h = g;
|
||||
g = f;
|
||||
f = e;
|
||||
e = mask_32bit(d + temp1);
|
||||
d = c;
|
||||
c = b;
|
||||
b = a;
|
||||
a = mask_32bit(temp1 + temp2);
|
||||
}
|
||||
*message_digest += a;
|
||||
*(message_digest + 1) += b;
|
||||
*(message_digest + 2) += c;
|
||||
*(message_digest + 3) += d;
|
||||
*(message_digest + 4) += e;
|
||||
*(message_digest + 5) += f;
|
||||
*(message_digest + 6) += g;
|
||||
*(message_digest + 7) += h;
|
||||
for (std::size_t i = 0; i < 8; ++i) {
|
||||
*(message_digest + i) = mask_32bit(*(message_digest + i));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename InIter>
|
||||
void output_hex(InIter first, InIter last, std::ostream& os) {
|
||||
os.setf(std::ios::hex, std::ios::basefield);
|
||||
while (first != last) {
|
||||
os.width(2);
|
||||
os.fill('0');
|
||||
os << static_cast<unsigned int>(*first);
|
||||
++first;
|
||||
}
|
||||
os.setf(std::ios::dec, std::ios::basefield);
|
||||
}
|
||||
|
||||
template <typename InIter>
|
||||
void bytes_to_hex_string(InIter first, InIter last, std::string& hex_str) {
|
||||
std::ostringstream oss;
|
||||
output_hex(first, last, oss);
|
||||
hex_str.assign(oss.str());
|
||||
}
|
||||
|
||||
template <typename InContainer>
|
||||
void bytes_to_hex_string(const InContainer& bytes, std::string& hex_str) {
|
||||
bytes_to_hex_string(bytes.begin(), bytes.end(), hex_str);
|
||||
}
|
||||
|
||||
template <typename InIter>
|
||||
std::string bytes_to_hex_string(InIter first, InIter last) {
|
||||
std::string hex_str;
|
||||
bytes_to_hex_string(first, last, hex_str);
|
||||
return hex_str;
|
||||
}
|
||||
|
||||
template <typename InContainer>
|
||||
std::string bytes_to_hex_string(const InContainer& bytes) {
|
||||
std::string hex_str;
|
||||
bytes_to_hex_string(bytes, hex_str);
|
||||
return hex_str;
|
||||
}
|
||||
|
||||
class hash256_one_by_one {
|
||||
public:
|
||||
hash256_one_by_one() { init(); }
|
||||
|
||||
void init() {
|
||||
buffer_.clear();
|
||||
std::fill(data_length_digits_, data_length_digits_ + 4, word_t(0));
|
||||
std::copy(detail::initial_message_digest,
|
||||
detail::initial_message_digest + 8, h_);
|
||||
}
|
||||
|
||||
template <typename RaIter>
|
||||
void process(RaIter first, RaIter last) {
|
||||
add_to_data_length(static_cast<word_t>(std::distance(first, last)));
|
||||
std::copy(first, last, std::back_inserter(buffer_));
|
||||
std::size_t i = 0;
|
||||
for (; i + 64 <= buffer_.size(); i += 64) {
|
||||
detail::hash256_block(h_, buffer_.begin() + i,
|
||||
buffer_.begin() + i + 64);
|
||||
}
|
||||
buffer_.erase(buffer_.begin(), buffer_.begin() + i);
|
||||
}
|
||||
|
||||
void finish() {
|
||||
byte_t temp[64];
|
||||
std::fill(temp, temp + 64, byte_t(0));
|
||||
std::size_t remains = buffer_.size();
|
||||
std::copy(buffer_.begin(), buffer_.end(), temp);
|
||||
temp[remains] = 0x80;
|
||||
|
||||
if (remains > 55) {
|
||||
std::fill(temp + remains + 1, temp + 64, byte_t(0));
|
||||
detail::hash256_block(h_, temp, temp + 64);
|
||||
std::fill(temp, temp + 64 - 4, byte_t(0));
|
||||
} else {
|
||||
std::fill(temp + remains + 1, temp + 64 - 4, byte_t(0));
|
||||
}
|
||||
|
||||
write_data_bit_length(&(temp[56]));
|
||||
detail::hash256_block(h_, temp, temp + 64);
|
||||
}
|
||||
|
||||
template <typename OutIter>
|
||||
void get_hash_bytes(OutIter first, OutIter last) const {
|
||||
for (const word_t* iter = h_; iter != h_ + 8; ++iter) {
|
||||
for (std::size_t i = 0; i < 4 && first != last; ++i) {
|
||||
*(first++) = detail::mask_8bit(
|
||||
static_cast<byte_t>((*iter >> (24 - 8 * i))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void add_to_data_length(word_t n) {
|
||||
word_t carry = 0;
|
||||
data_length_digits_[0] += n;
|
||||
for (std::size_t i = 0; i < 4; ++i) {
|
||||
data_length_digits_[i] += carry;
|
||||
if (data_length_digits_[i] >= 65536u) {
|
||||
carry = data_length_digits_[i] >> 16;
|
||||
data_length_digits_[i] &= 65535u;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
void write_data_bit_length(byte_t* begin) {
|
||||
word_t data_bit_length_digits[4];
|
||||
std::copy(data_length_digits_, data_length_digits_ + 4,
|
||||
data_bit_length_digits);
|
||||
|
||||
// convert byte length to bit length (multiply 8 or shift 3 times left)
|
||||
word_t carry = 0;
|
||||
for (std::size_t i = 0; i < 4; ++i) {
|
||||
word_t before_val = data_bit_length_digits[i];
|
||||
data_bit_length_digits[i] <<= 3;
|
||||
data_bit_length_digits[i] |= carry;
|
||||
data_bit_length_digits[i] &= 65535u;
|
||||
carry = (before_val >> (16 - 3)) & 65535u;
|
||||
}
|
||||
|
||||
// write data_bit_length
|
||||
for (int i = 3; i >= 0; --i) {
|
||||
(*begin++) = static_cast<byte_t>(data_bit_length_digits[i] >> 8);
|
||||
(*begin++) = static_cast<byte_t>(data_bit_length_digits[i]);
|
||||
}
|
||||
}
|
||||
std::vector<byte_t> buffer_;
|
||||
word_t data_length_digits_[4]; // as 64bit integer (16bit x 4 integer)
|
||||
word_t h_[8];
|
||||
};
|
||||
|
||||
inline void get_hash_hex_string(const hash256_one_by_one& hasher,
|
||||
std::string& hex_str) {
|
||||
byte_t hash[k_digest_size];
|
||||
hasher.get_hash_bytes(hash, hash + k_digest_size);
|
||||
return bytes_to_hex_string(hash, hash + k_digest_size, hex_str);
|
||||
}
|
||||
|
||||
inline std::string get_hash_hex_string(const hash256_one_by_one& hasher) {
|
||||
std::string hex_str;
|
||||
get_hash_hex_string(hasher, hex_str);
|
||||
return hex_str;
|
||||
}
|
||||
|
||||
namespace impl {
|
||||
template <typename RaIter, typename OutIter>
|
||||
void hash256_impl(RaIter first, RaIter last, OutIter first2, OutIter last2, int,
|
||||
std::random_access_iterator_tag) {
|
||||
hash256_one_by_one hasher;
|
||||
// hasher.init();
|
||||
hasher.process(first, last);
|
||||
hasher.finish();
|
||||
hasher.get_hash_bytes(first2, last2);
|
||||
}
|
||||
|
||||
template <typename InputIter, typename OutIter>
|
||||
void hash256_impl(InputIter first, InputIter last, OutIter first2,
|
||||
OutIter last2, int buffer_size, std::input_iterator_tag) {
|
||||
std::vector<byte_t> buffer(buffer_size);
|
||||
hash256_one_by_one hasher;
|
||||
// hasher.init();
|
||||
while (first != last) {
|
||||
int size = buffer_size;
|
||||
for (int i = 0; i != buffer_size; ++i, ++first) {
|
||||
if (first == last) {
|
||||
size = i;
|
||||
break;
|
||||
}
|
||||
buffer[i] = *first;
|
||||
}
|
||||
hasher.process(buffer.begin(), buffer.begin() + size);
|
||||
}
|
||||
hasher.finish();
|
||||
hasher.get_hash_bytes(first2, last2);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename InIter, typename OutIter>
|
||||
void hash256(InIter first, InIter last, OutIter first2, OutIter last2,
|
||||
int buffer_size = PICOSHA2_BUFFER_SIZE_FOR_INPUT_ITERATOR) {
|
||||
picosha2::impl::hash256_impl(
|
||||
first, last, first2, last2, buffer_size,
|
||||
typename std::iterator_traits<InIter>::iterator_category());
|
||||
}
|
||||
|
||||
template <typename InIter, typename OutContainer>
|
||||
void hash256(InIter first, InIter last, OutContainer& dst) {
|
||||
hash256(first, last, dst.begin(), dst.end());
|
||||
}
|
||||
|
||||
template <typename InContainer, typename OutIter>
|
||||
void hash256(const InContainer& src, OutIter first, OutIter last) {
|
||||
hash256(src.begin(), src.end(), first, last);
|
||||
}
|
||||
|
||||
template <typename InContainer, typename OutContainer>
|
||||
void hash256(const InContainer& src, OutContainer& dst) {
|
||||
hash256(src.begin(), src.end(), dst.begin(), dst.end());
|
||||
}
|
||||
|
||||
template <typename InIter>
|
||||
void hash256_hex_string(InIter first, InIter last, std::string& hex_str) {
|
||||
byte_t hashed[k_digest_size];
|
||||
hash256(first, last, hashed, hashed + k_digest_size);
|
||||
std::ostringstream oss;
|
||||
output_hex(hashed, hashed + k_digest_size, oss);
|
||||
hex_str.assign(oss.str());
|
||||
}
|
||||
|
||||
template <typename InIter>
|
||||
std::string hash256_hex_string(InIter first, InIter last) {
|
||||
std::string hex_str;
|
||||
hash256_hex_string(first, last, hex_str);
|
||||
return hex_str;
|
||||
}
|
||||
|
||||
inline void hash256_hex_string(const std::string& src, std::string& hex_str) {
|
||||
hash256_hex_string(src.begin(), src.end(), hex_str);
|
||||
}
|
||||
|
||||
template <typename InContainer>
|
||||
void hash256_hex_string(const InContainer& src, std::string& hex_str) {
|
||||
hash256_hex_string(src.begin(), src.end(), hex_str);
|
||||
}
|
||||
|
||||
template <typename InContainer>
|
||||
std::string hash256_hex_string(const InContainer& src) {
|
||||
return hash256_hex_string(src.begin(), src.end());
|
||||
}
|
||||
template<typename OutIter>void hash256(std::ifstream& f, OutIter first, OutIter last){
|
||||
hash256(std::istreambuf_iterator<char>(f), std::istreambuf_iterator<char>(), first,last);
|
||||
|
||||
}
|
||||
}// namespace picosha2
|
||||
#endif // PICOSHA2_H
|
2
third_party/rlbox/README-mozilla
vendored
2
third_party/rlbox/README-mozilla
vendored
@ -1,7 +1,7 @@
|
||||
This directory contains the rlbox source from the upstream repo:
|
||||
https://github.com/PLSysSec/rlbox_sandboxing_api/
|
||||
|
||||
Current version: [commit 7c77f721507749e18269f05d70f3ae00ad3e0a22]
|
||||
Current version: [commit 358fb5bb02a326c631efaebdfb59b0df2ab9c602]
|
||||
|
||||
UPDATING:
|
||||
|
||||
|
142
third_party/rlbox/include/rlbox.hpp
vendored
142
third_party/rlbox/include/rlbox.hpp
vendored
@ -40,7 +40,6 @@ public:
|
||||
* @brief Unwrap a tainted value without verification. This is an unsafe
|
||||
* operation and should be used with care.
|
||||
*/
|
||||
inline auto UNSAFE_unverified() { return impl().get_raw_value(); }
|
||||
inline auto UNSAFE_unverified() const { return impl().get_raw_value(); }
|
||||
/**
|
||||
* @brief Like UNSAFE_unverified, but get the underlying sandbox
|
||||
@ -51,10 +50,6 @@ public:
|
||||
* For the Wasm-based sandbox, this function additionally validates the
|
||||
* unwrapped value against the machine model of the sandbox (LP32).
|
||||
*/
|
||||
inline auto UNSAFE_sandboxed(rlbox_sandbox<T_Sbx>& sandbox)
|
||||
{
|
||||
return impl().get_raw_sandbox_value(sandbox);
|
||||
}
|
||||
inline auto UNSAFE_sandboxed(rlbox_sandbox<T_Sbx>& sandbox) const
|
||||
{
|
||||
return impl().get_raw_sandbox_value(sandbox);
|
||||
@ -66,44 +61,41 @@ public:
|
||||
*
|
||||
* @param reason An explanation why the unverified unwrapping is safe.
|
||||
*/
|
||||
rlbox_detail_member_and_const(
|
||||
template<size_t N>
|
||||
inline auto unverified_safe_because(const char (&reason)[N]),
|
||||
template<size_t N>
|
||||
inline auto unverified_safe_because(const char (&reason)[N]) const
|
||||
{
|
||||
RLBOX_UNUSED(reason);
|
||||
static_assert(!std::is_pointer_v<T>,
|
||||
"unverified_safe_because does not support pointers. Use "
|
||||
"unverified_safe_pointer_because.");
|
||||
return UNSAFE_unverified();
|
||||
}
|
||||
|
||||
template<size_t N>
|
||||
inline auto unverified_safe_pointer_because(size_t count,
|
||||
const char (&reason)[N]) const
|
||||
{
|
||||
RLBOX_UNUSED(reason);
|
||||
|
||||
static_assert(std::is_pointer_v<T>, "Expected pointer type");
|
||||
using T_Pointed = std::remove_pointer_t<T>;
|
||||
if_constexpr_named(cond1, std::is_pointer_v<T_Pointed>)
|
||||
{
|
||||
RLBOX_UNUSED(reason);
|
||||
static_assert(!std::is_pointer_v<T>,
|
||||
"unverified_safe_because does not support pointers. Use "
|
||||
"unverified_safe_pointer_because.");
|
||||
return UNSAFE_unverified();
|
||||
});
|
||||
rlbox_detail_static_fail_because(
|
||||
cond1,
|
||||
"There is no way to use unverified_safe_pointer_because for "
|
||||
"'pointers to pointers' safely. Use copy_and_verify instead.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
rlbox_detail_member_and_const(
|
||||
template<size_t N>
|
||||
inline auto unverified_safe_pointer_because(size_t count,
|
||||
const char (&reason)[N]),
|
||||
{
|
||||
RLBOX_UNUSED(reason);
|
||||
auto ret = UNSAFE_unverified();
|
||||
if (ret != nullptr) {
|
||||
size_t bytes = sizeof(T) * count;
|
||||
detail::check_range_doesnt_cross_app_sbx_boundary<T_Sbx>(ret, bytes);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static_assert(std::is_pointer_v<T>, "Expected pointer type");
|
||||
using T_Pointed = std::remove_pointer_t<T>;
|
||||
if_constexpr_named(cond1, std::is_pointer_v<T_Pointed>)
|
||||
{
|
||||
rlbox_detail_static_fail_because(
|
||||
cond1,
|
||||
"There is no way to use unverified_safe_pointer_because for "
|
||||
"'pointers to pointers' safely. Use copy_and_verify instead.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto ret = UNSAFE_unverified();
|
||||
if (ret != nullptr) {
|
||||
size_t bytes = sizeof(T) * count;
|
||||
detail::check_range_doesnt_cross_app_sbx_boundary<T_Sbx>(ret, bytes);
|
||||
}
|
||||
return ret;
|
||||
});
|
||||
|
||||
inline auto INTERNAL_unverified_safe() { return UNSAFE_unverified(); }
|
||||
inline auto INTERNAL_unverified_safe() const { return UNSAFE_unverified(); }
|
||||
|
||||
#define BinaryOpValAndPtr(opSymbol) \
|
||||
@ -163,7 +155,8 @@ public:
|
||||
\
|
||||
auto raw = impl().get_raw_value(); \
|
||||
auto raw_rhs = detail::unwrap_value(rhs); \
|
||||
static_assert(std::is_integral_v<decltype(raw_rhs)>, \
|
||||
static_assert(std::is_integral_v<decltype(raw_rhs)> \
|
||||
|| std::is_floating_point_v<decltype(raw_rhs)>, \
|
||||
"Can only operate on numeric types"); \
|
||||
\
|
||||
auto ret = raw opSymbol raw_rhs; \
|
||||
@ -427,7 +420,7 @@ public:
|
||||
template<typename T_Rhs>
|
||||
inline T_OpSubscriptArrRet& operator[](T_Rhs&& rhs)
|
||||
{
|
||||
rlbox_detail_forward_to_const_a(operator[], T_OpSubscriptArrRet&, rhs);
|
||||
return const_cast<T_OpSubscriptArrRet&>(std::as_const(*this)[rhs]);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -446,29 +439,20 @@ public:
|
||||
return *ret_ptr;
|
||||
}
|
||||
|
||||
inline T_OpDerefRet& operator*()
|
||||
{
|
||||
rlbox_detail_forward_to_const(operator*, T_OpDerefRet&);
|
||||
}
|
||||
|
||||
// We need to implement the -> operator even if T is not a struct
|
||||
// So that we can support code patterns such as the below
|
||||
// tainted<T*> a;
|
||||
// a->UNSAFE_unverified();
|
||||
inline auto operator->() const
|
||||
inline const T_OpDerefRet* operator->() const
|
||||
{
|
||||
static_assert(std::is_pointer_v<T>,
|
||||
"Operator -> only supported for pointer types");
|
||||
auto ret = impl().get_raw_value();
|
||||
using T_Ret = std::remove_pointer_t<T>;
|
||||
using T_RetWrap = const tainted_volatile<T_Ret, T_Sbx>;
|
||||
return reinterpret_cast<T_RetWrap*>(ret);
|
||||
return reinterpret_cast<const T_OpDerefRet*>(impl().get_raw_value());
|
||||
}
|
||||
|
||||
inline auto operator->()
|
||||
inline T_OpDerefRet* operator->()
|
||||
{
|
||||
using T_Ret = tainted_volatile<std::remove_pointer_t<T>, T_Sbx>*;
|
||||
rlbox_detail_forward_to_const(operator->, T_Ret);
|
||||
return const_cast<T_OpDerefRet*>(std::as_const(*this).operator->());
|
||||
}
|
||||
|
||||
inline auto operator!()
|
||||
@ -495,7 +479,7 @@ public:
|
||||
/**
|
||||
* @brief Copy tainted value from sandbox and verify it.
|
||||
*
|
||||
* @param verifer Function used to verify the copied value.
|
||||
* @param verifier Function used to verify the copied value.
|
||||
* @tparam T_Func the type of the verifier.
|
||||
* @return Whatever the verifier function returns.
|
||||
*/
|
||||
@ -628,7 +612,7 @@ public:
|
||||
/**
|
||||
* @brief Copy a range of tainted values from sandbox and verify them.
|
||||
*
|
||||
* @param verifer Function used to verify the copied value.
|
||||
* @param verifier Function used to verify the copied value.
|
||||
* @param count Number of elements to copy.
|
||||
* @tparam T_Func the type of the verifier. If the tainted type is ``int*``
|
||||
* then ``T_Func = T_Ret(*)(unique_ptr<int[]>)``.
|
||||
@ -654,7 +638,7 @@ public:
|
||||
/**
|
||||
* @brief Copy a tainted string from sandbox and verify it.
|
||||
*
|
||||
* @param verifer Function used to verify the copied value.
|
||||
* @param verifier Function used to verify the copied value.
|
||||
* @tparam T_Func the type of the verifier either
|
||||
* ``T_Ret(*)(unique_ptr<char[]>)`` or ``T_Ret(*)(std::string)``
|
||||
* @return Whatever the verifier function returns.
|
||||
@ -737,7 +721,7 @@ public:
|
||||
* @return Whatever the verifier function returns.
|
||||
*/
|
||||
template<typename T_Func>
|
||||
inline auto copy_and_verify_address(T_Func verifier)
|
||||
inline auto copy_and_verify_address(T_Func verifier) const
|
||||
{
|
||||
static_assert(std::is_pointer_v<T>,
|
||||
"copy_and_verify_address must be used on pointers");
|
||||
@ -760,7 +744,8 @@ public:
|
||||
* @return Whatever the verifier function returns.
|
||||
*/
|
||||
template<typename T_Func>
|
||||
inline auto copy_and_verify_buffer_address(T_Func verifier, std::size_t size)
|
||||
inline auto copy_and_verify_buffer_address(T_Func verifier,
|
||||
std::size_t size) const
|
||||
{
|
||||
static_assert(std::is_pointer_v<T>,
|
||||
"copy_and_verify_address must be used on pointers");
|
||||
@ -929,18 +914,6 @@ private:
|
||||
return ret;
|
||||
};
|
||||
|
||||
inline std::remove_cv_t<T_AppType> get_raw_value() noexcept
|
||||
{
|
||||
rlbox_detail_forward_to_const(get_raw_value, std::remove_cv_t<T_AppType>);
|
||||
}
|
||||
|
||||
inline std::remove_cv_t<T_SandboxedType> get_raw_sandbox_value(
|
||||
rlbox_sandbox<T_Sbx>& sandbox)
|
||||
{
|
||||
rlbox_detail_forward_to_const_a(
|
||||
get_raw_sandbox_value, std::remove_cv_t<T_SandboxedType>, sandbox);
|
||||
};
|
||||
|
||||
inline const void* find_example_pointer_or_null() const noexcept
|
||||
{
|
||||
if constexpr (std::is_array_v<T>) {
|
||||
@ -1195,25 +1168,6 @@ private:
|
||||
return data;
|
||||
};
|
||||
|
||||
inline std::remove_cv_t<T_AppType> get_raw_value()
|
||||
{
|
||||
rlbox_detail_forward_to_const(get_raw_value, std::remove_cv_t<T_AppType>);
|
||||
}
|
||||
|
||||
inline std::remove_cv_t<T_SandboxedType> get_raw_sandbox_value() noexcept
|
||||
{
|
||||
rlbox_detail_forward_to_const(get_raw_sandbox_value,
|
||||
std::remove_cv_t<T_SandboxedType>);
|
||||
};
|
||||
|
||||
inline std::remove_cv_t<T_SandboxedType> get_raw_sandbox_value(
|
||||
rlbox_sandbox<T_Sbx>& sandbox) noexcept
|
||||
{
|
||||
RLBOX_UNUSED(sandbox);
|
||||
rlbox_detail_forward_to_const(get_raw_sandbox_value,
|
||||
std::remove_cv_t<T_SandboxedType>);
|
||||
};
|
||||
|
||||
tainted_volatile() = default;
|
||||
tainted_volatile(const tainted_volatile<T, T_Sbx>& p) = default;
|
||||
|
||||
@ -1223,14 +1177,12 @@ public:
|
||||
auto ref =
|
||||
detail::remove_volatile_from_ptr_cast(&this->get_sandbox_value_ref());
|
||||
auto ref_cast = reinterpret_cast<const T*>(ref);
|
||||
auto ret = tainted<const T*, T_Sbx>::internal_factory(ref_cast);
|
||||
return ret;
|
||||
return tainted<const T*, T_Sbx>::internal_factory(ref_cast);
|
||||
}
|
||||
|
||||
inline tainted<T*, T_Sbx> operator&() noexcept
|
||||
{
|
||||
using T_Ret = tainted<T*, T_Sbx>;
|
||||
rlbox_detail_forward_to_const(operator&, T_Ret);
|
||||
return sandbox_const_cast<T*>(&std::as_const(*this));
|
||||
}
|
||||
|
||||
// Needed as the definition of unary & above shadows the base's binary &
|
||||
|
42
third_party/rlbox/include/rlbox_helpers.hpp
vendored
42
third_party/rlbox/include/rlbox_helpers.hpp
vendored
@ -98,48 +98,6 @@ namespace detail {
|
||||
} \
|
||||
RLBOX_REQUIRE_SEMI_COLON
|
||||
|
||||
#define rlbox_detail_forward_to_const(func_name, result_type) \
|
||||
using T_ConstClassPtr = std::add_pointer_t< \
|
||||
std::add_const_t<std::remove_pointer_t<decltype(this)>>>; \
|
||||
if constexpr (detail::rlbox_is_tainted_v<result_type> && \
|
||||
!std::is_reference_v<result_type>) { \
|
||||
return sandbox_const_cast<detail::rlbox_remove_wrapper_t<result_type>>( \
|
||||
const_cast<T_ConstClassPtr>(this)->func_name()); \
|
||||
} else if constexpr (detail::is_fundamental_or_enum_v<result_type> || \
|
||||
detail::is_std_array_v<result_type> || \
|
||||
detail::is_func_ptr_v<result_type> || \
|
||||
std::is_class_v<result_type>) { \
|
||||
return const_cast<T_ConstClassPtr>(this)->func_name(); \
|
||||
} else { \
|
||||
return const_cast<result_type>( \
|
||||
const_cast<T_ConstClassPtr>(this)->func_name()); \
|
||||
}
|
||||
|
||||
#define rlbox_detail_forward_to_const_a(func_name, result_type, ...) \
|
||||
using T_ConstClassPtr = std::add_pointer_t< \
|
||||
std::add_const_t<std::remove_pointer_t<decltype(this)>>>; \
|
||||
if constexpr (detail::rlbox_is_tainted_v<result_type> && \
|
||||
!std::is_reference_v<result_type>) { \
|
||||
static_assert(detail::rlbox_is_tainted_v<result_type>); \
|
||||
return sandbox_const_cast<detail::rlbox_remove_wrapper_t<result_type>>( \
|
||||
const_cast<T_ConstClassPtr>(this)->func_name(__VA_ARGS__)); \
|
||||
} else if constexpr (detail::is_fundamental_or_enum_v<result_type> || \
|
||||
detail::is_std_array_v<result_type> || \
|
||||
detail::is_func_ptr_v<result_type> || \
|
||||
std::is_class_v<result_type>) { \
|
||||
return const_cast<T_ConstClassPtr>(this)->func_name(__VA_ARGS__); \
|
||||
} else { \
|
||||
return const_cast<result_type>( \
|
||||
const_cast<T_ConstClassPtr>(this)->func_name(__VA_ARGS__)); \
|
||||
}
|
||||
|
||||
#define rlbox_detail_member_and_const(sig, ...) \
|
||||
sig __VA_ARGS__ \
|
||||
\
|
||||
sig const __VA_ARGS__ \
|
||||
\
|
||||
static_assert(true)
|
||||
|
||||
template<typename T>
|
||||
inline auto remove_volatile_from_ptr_cast(T* ptr)
|
||||
{
|
||||
|
30
third_party/rlbox/include/rlbox_policy_types.hpp
vendored
30
third_party/rlbox/include/rlbox_policy_types.hpp
vendored
@ -100,11 +100,6 @@ private:
|
||||
{
|
||||
return callback_trampoline;
|
||||
}
|
||||
inline T_Callback get_raw_value() noexcept { return callback; }
|
||||
inline T_Trampoline get_raw_sandbox_value() noexcept
|
||||
{
|
||||
return callback_trampoline;
|
||||
}
|
||||
|
||||
// Keep constructor private as only rlbox_sandbox should be able to create
|
||||
// this object
|
||||
@ -177,12 +172,6 @@ public:
|
||||
RLBOX_UNUSED(sandbox);
|
||||
return get_raw_sandbox_value();
|
||||
}
|
||||
inline auto UNSAFE_unverified() noexcept { return get_raw_value(); }
|
||||
inline auto UNSAFE_sandboxed(rlbox_sandbox<T_Sbx>& sandbox) noexcept
|
||||
{
|
||||
RLBOX_UNUSED(sandbox);
|
||||
return get_raw_sandbox_value();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename T_Sbx>
|
||||
@ -213,11 +202,6 @@ private:
|
||||
{
|
||||
return idx;
|
||||
}
|
||||
inline T get_raw_value() noexcept { return to_tainted().get_raw_value(); }
|
||||
inline typename T_Sbx::T_PointerType get_raw_sandbox_value() noexcept
|
||||
{
|
||||
return idx;
|
||||
}
|
||||
|
||||
app_pointer(app_pointer_map<typename T_Sbx::T_PointerType>* a_map,
|
||||
typename T_Sbx::T_PointerType a_idx,
|
||||
@ -286,12 +270,6 @@ public:
|
||||
RLBOX_UNUSED(sandbox);
|
||||
return get_raw_sandbox_value();
|
||||
}
|
||||
inline auto UNSAFE_unverified() noexcept { return get_raw_value(); }
|
||||
inline auto UNSAFE_sandboxed(rlbox_sandbox<T_Sbx>& sandbox) noexcept
|
||||
{
|
||||
RLBOX_UNUSED(sandbox);
|
||||
return get_raw_sandbox_value();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@ -315,7 +293,7 @@ public:
|
||||
val = rhs;
|
||||
return *this;
|
||||
}
|
||||
inline tainted_boolean_hint operator!() { return tainted_boolean_hint(!val); }
|
||||
inline tainted_boolean_hint operator!() const { return tainted_boolean_hint(!val); }
|
||||
template<size_t N>
|
||||
inline bool unverified_safe_because(const char (&reason)[N]) const
|
||||
{
|
||||
@ -323,8 +301,6 @@ public:
|
||||
return val;
|
||||
}
|
||||
inline bool UNSAFE_unverified() const { return val; }
|
||||
inline bool UNSAFE_unverified() { return val; }
|
||||
inline auto INTERNAL_unverified_safe() { return UNSAFE_unverified(); }
|
||||
inline auto INTERNAL_unverified_safe() const { return UNSAFE_unverified(); }
|
||||
|
||||
// Add a template parameter to make sure the assert only fires when called
|
||||
@ -373,7 +349,7 @@ public:
|
||||
val = rhs;
|
||||
return *this;
|
||||
}
|
||||
inline tainted_boolean_hint operator!() { return tainted_boolean_hint(!val); }
|
||||
inline tainted_boolean_hint operator!() const { return tainted_boolean_hint(!val); }
|
||||
template<size_t N>
|
||||
inline int unverified_safe_because(const char (&reason)[N]) const
|
||||
{
|
||||
@ -381,8 +357,6 @@ public:
|
||||
return val;
|
||||
}
|
||||
inline int UNSAFE_unverified() const { return val; }
|
||||
inline int UNSAFE_unverified() { return val; }
|
||||
inline auto INTERNAL_unverified_safe() { return UNSAFE_unverified(); }
|
||||
inline auto INTERNAL_unverified_safe() const { return UNSAFE_unverified(); }
|
||||
|
||||
// Add a template parameter to make sure the assert only fires when called
|
||||
|
2
third_party/rlbox/include/rlbox_sandbox.hpp
vendored
2
third_party/rlbox/include/rlbox_sandbox.hpp
vendored
@ -368,7 +368,7 @@ public:
|
||||
/**
|
||||
* @brief Create a new sandbox.
|
||||
*
|
||||
* @tparam T_args Arguments passed to the underlying sandbox
|
||||
* @tparam T_Args Arguments passed to the underlying sandbox
|
||||
* implementation. For the null sandbox, no arguments are necessary.
|
||||
*/
|
||||
template<typename... T_Args>
|
||||
|
43
third_party/rlbox/include/rlbox_stdlib.hpp
vendored
43
third_party/rlbox/include/rlbox_stdlib.hpp
vendored
@ -227,30 +227,35 @@ tainted<T*, T_Sbx> copy_memory_or_grant_access(rlbox_sandbox<T_Sbx>& sandbox,
|
||||
{
|
||||
copied = false;
|
||||
|
||||
// Malloc in sandbox takes a uint32_t as the parameter, need a bounds check
|
||||
detail::dynamic_check(num <= std::numeric_limits<uint32_t>::max(),
|
||||
"Granting access too large a region");
|
||||
uint32_t num_trunc = num;
|
||||
// This function is meant for byte buffers only - so char and char16
|
||||
static_assert(sizeof(T) <= 2);
|
||||
|
||||
// overflow ok
|
||||
size_t source_size = num * sizeof(T);
|
||||
|
||||
// sandbox can grant access if it includes the following line
|
||||
// using can_grant_deny_access = void;
|
||||
if constexpr (detail::has_member_using_can_grant_deny_access_v<T_Sbx>) {
|
||||
detail::check_range_doesnt_cross_app_sbx_boundary<T_Sbx>(src, num_trunc);
|
||||
detail::check_range_doesnt_cross_app_sbx_boundary<T_Sbx>(src, source_size);
|
||||
|
||||
bool success;
|
||||
auto ret = sandbox.INTERNAL_grant_access(src, num_trunc, success);
|
||||
auto ret = sandbox.INTERNAL_grant_access(src, num, success);
|
||||
if (success) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
// Malloc in sandbox takes a uint32_t as the parameter, need a bounds check
|
||||
detail::dynamic_check(num <= std::numeric_limits<uint32_t>::max(),
|
||||
"Granting access too large a region");
|
||||
using T_nocv = std::remove_cv_t<T>;
|
||||
tainted<T_nocv*, T_Sbx> copy =
|
||||
sandbox.template malloc_in_sandbox<T_nocv>(num_trunc);
|
||||
sandbox.template malloc_in_sandbox<T_nocv>(static_cast<uint32_t>(num));
|
||||
if (!copy) {
|
||||
return nullptr;
|
||||
}
|
||||
rlbox::memcpy(sandbox, copy, src, num * sizeof(T));
|
||||
|
||||
rlbox::memcpy(sandbox, copy, src, source_size);
|
||||
if (free_source_on_copy) {
|
||||
free(const_cast<void*>(reinterpret_cast<const void*>(src)));
|
||||
}
|
||||
@ -267,9 +272,9 @@ tainted<T*, T_Sbx> copy_memory_or_grant_access(rlbox_sandbox<T_Sbx>& sandbox,
|
||||
* - if the sandbox allows, moves the buffer out of existing sandbox memory
|
||||
* @param sandbox Target sandbox
|
||||
* @param src Raw pointer to the buffer
|
||||
* @param num Number of bytes in the buffer
|
||||
* @param num Number of T-sized elements in the buffer
|
||||
* @param free_source_on_copy If the source buffer was copied, this variable
|
||||
* controls whether copy_memory_or_grant_access should call delete on the src.
|
||||
* controls whether copy_memory_or_deny_access should call delete on the src.
|
||||
* This calls delete[] if num > 1.
|
||||
* @param copied out parameter indicating if the source was copied or transfered
|
||||
*/
|
||||
@ -283,26 +288,36 @@ T* copy_memory_or_deny_access(rlbox_sandbox<T_Sbx>& sandbox,
|
||||
bool free_source_on_copy,
|
||||
bool& copied)
|
||||
{
|
||||
copied = false;
|
||||
|
||||
// This function is meant for byte buffers only - so char and char16
|
||||
static_assert(sizeof(T) <= 2);
|
||||
|
||||
// overflow ok
|
||||
size_t source_size = num * sizeof(T);
|
||||
|
||||
// sandbox can grant access if it includes the following line
|
||||
// using can_grant_deny_access = void;
|
||||
if constexpr (detail::has_member_using_can_grant_deny_access_v<T_Sbx>) {
|
||||
detail::check_range_doesnt_cross_app_sbx_boundary<T_Sbx>(
|
||||
src.INTERNAL_unverified_safe(), num);
|
||||
src.INTERNAL_unverified_safe(), source_size);
|
||||
|
||||
bool success;
|
||||
auto ret = sandbox.INTERNAL_deny_access(src, num, success);
|
||||
if (success) {
|
||||
copied = false;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
auto copy = static_cast<T*>(malloc(num));
|
||||
auto copy = static_cast<T*>(malloc(source_size));
|
||||
if (!copy) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
tainted<T*, T_Sbx> src_tainted = src;
|
||||
char* src_raw = src_tainted.copy_and_verify_buffer_address(
|
||||
[](uintptr_t val) { return reinterpret_cast<char*>(val); }, num);
|
||||
std::memcpy(copy, src_raw, num);
|
||||
std::memcpy(copy, src_raw, source_size);
|
||||
if (free_source_on_copy) {
|
||||
sandbox.free_in_sandbox(src);
|
||||
}
|
||||
|
@ -30,6 +30,9 @@ template<typename T, typename T_Sbx>
|
||||
using convert_to_sandbox_equivalent_t =
|
||||
typename convert_to_sandbox_equivalent_helper<T, T_Sbx>::type;
|
||||
|
||||
// This is used by rlbox_load_structs_from_library to test the current namespace
|
||||
struct markerStruct
|
||||
{};
|
||||
}
|
||||
|
||||
#define helper_create_converted_field(fieldType, fieldName, isFrozen) \
|
||||
@ -124,18 +127,6 @@ using convert_to_sandbox_equivalent_t =
|
||||
return *ret_ptr; \
|
||||
} \
|
||||
\
|
||||
inline std::remove_cv_t<T> get_raw_value() noexcept \
|
||||
{ \
|
||||
rlbox_detail_forward_to_const(get_raw_value, std::remove_cv_t<T>); \
|
||||
} \
|
||||
\
|
||||
inline std::remove_cv_t<Sbx_##libId##_##T<T_Sbx>> \
|
||||
get_raw_sandbox_value() noexcept \
|
||||
{ \
|
||||
rlbox_detail_forward_to_const( \
|
||||
get_raw_sandbox_value, std::remove_cv_t<Sbx_##libId##_##T<T_Sbx>>); \
|
||||
} \
|
||||
\
|
||||
tainted_volatile() = default; \
|
||||
tainted_volatile(const tainted_volatile<MaybeConst T, T_Sbx>& p) = \
|
||||
default; \
|
||||
@ -146,8 +137,7 @@ using convert_to_sandbox_equivalent_t =
|
||||
helper_no_op, \
|
||||
MaybeConst) \
|
||||
\
|
||||
inline tainted<MaybeConst T*, T_Sbx> \
|
||||
operator&() noexcept \
|
||||
inline tainted<MaybeConst T*, T_Sbx> operator&() const noexcept \
|
||||
{ \
|
||||
auto ref_cast = \
|
||||
reinterpret_cast<MaybeConst T*>(&get_sandbox_value_ref()); \
|
||||
@ -155,24 +145,13 @@ using convert_to_sandbox_equivalent_t =
|
||||
return ret; \
|
||||
} \
|
||||
\
|
||||
inline auto UNSAFE_unverified() { return get_raw_value(); } \
|
||||
inline auto UNSAFE_unverified() const { return get_raw_value(); } \
|
||||
inline auto UNSAFE_sandboxed(rlbox_sandbox<T_Sbx>& sandbox) \
|
||||
{ \
|
||||
return get_raw_sandbox_value(sandbox); \
|
||||
} \
|
||||
inline auto UNSAFE_sandboxed(rlbox_sandbox<T_Sbx>& sandbox) const \
|
||||
{ \
|
||||
return get_raw_sandbox_value(sandbox); \
|
||||
} \
|
||||
\
|
||||
template<size_t N> \
|
||||
inline auto unverified_safe_because(const char (&reason)[N]) \
|
||||
{ \
|
||||
RLBOX_UNUSED(reason); \
|
||||
return UNSAFE_unverified(); \
|
||||
} \
|
||||
template<size_t N> \
|
||||
inline auto unverified_safe_because(const char (&reason)[N]) const \
|
||||
{ \
|
||||
RLBOX_UNUSED(reason); \
|
||||
@ -231,20 +210,6 @@ using convert_to_sandbox_equivalent_t =
|
||||
return lhs; \
|
||||
} \
|
||||
\
|
||||
inline std::remove_cv_t<T> get_raw_value() noexcept \
|
||||
{ \
|
||||
rlbox_detail_forward_to_const(get_raw_value, std::remove_cv_t<T>); \
|
||||
} \
|
||||
\
|
||||
inline std::remove_cv_t<Sbx_##libId##_##T<T_Sbx>> get_raw_sandbox_value( \
|
||||
rlbox_sandbox<T_Sbx>& sandbox) noexcept \
|
||||
{ \
|
||||
rlbox_detail_forward_to_const_a( \
|
||||
get_raw_sandbox_value, \
|
||||
std::remove_cv_t<Sbx_##libId##_##T<T_Sbx>>, \
|
||||
sandbox); \
|
||||
} \
|
||||
\
|
||||
inline const void* find_example_pointer_or_null() const noexcept \
|
||||
{ \
|
||||
sandbox_fields_reflection_##libId##_class_##T( \
|
||||
@ -258,7 +223,7 @@ using convert_to_sandbox_equivalent_t =
|
||||
helper_no_op, \
|
||||
MaybeConst) \
|
||||
\
|
||||
tainted() = default; \
|
||||
tainted() = default; \
|
||||
tainted(const tainted<MaybeConst T, T_Sbx>& p) = default; \
|
||||
\
|
||||
tainted(const tainted_volatile<T, T_Sbx>& p) \
|
||||
@ -281,24 +246,13 @@ using convert_to_sandbox_equivalent_t =
|
||||
return *reinterpret_cast<tainted_opaque<MaybeConst T, T_Sbx>*>(this); \
|
||||
} \
|
||||
\
|
||||
inline auto UNSAFE_unverified() { return get_raw_value(); } \
|
||||
inline auto UNSAFE_unverified() const { return get_raw_value(); } \
|
||||
inline auto UNSAFE_sandboxed(rlbox_sandbox<T_Sbx>& sandbox) \
|
||||
{ \
|
||||
return get_raw_sandbox_value(sandbox); \
|
||||
} \
|
||||
inline auto UNSAFE_sandboxed(rlbox_sandbox<T_Sbx>& sandbox) const \
|
||||
{ \
|
||||
return get_raw_sandbox_value(sandbox); \
|
||||
} \
|
||||
\
|
||||
template<size_t N> \
|
||||
inline auto unverified_safe_because(const char (&reason)[N]) \
|
||||
{ \
|
||||
RLBOX_UNUSED(reason); \
|
||||
return UNSAFE_unverified(); \
|
||||
} \
|
||||
template<size_t N> \
|
||||
inline auto unverified_safe_because(const char (&reason)[N]) const \
|
||||
{ \
|
||||
RLBOX_UNUSED(reason); \
|
||||
@ -333,8 +287,8 @@ using convert_to_sandbox_equivalent_t =
|
||||
}
|
||||
|
||||
#define tainted_data_specialization(T, libId) \
|
||||
tainted_data_specialization_helper(, T, libId) \
|
||||
tainted_data_specialization_helper(const, T, libId)
|
||||
tainted_data_specialization_helper( , T, libId) \
|
||||
tainted_data_specialization_helper(const, T, libId)
|
||||
|
||||
#define convert_type_specialization(T, libId) \
|
||||
namespace detail { \
|
||||
@ -380,10 +334,6 @@ using convert_to_sandbox_equivalent_t =
|
||||
// clang-format off
|
||||
#define rlbox_load_structs_from_library(libId) \
|
||||
namespace rlbox { \
|
||||
namespace detail { \
|
||||
struct markerStruct \
|
||||
{}; \
|
||||
} \
|
||||
/* check that this macro is called in a global namespace */ \
|
||||
static_assert( \
|
||||
::rlbox::detail::is_member_of_rlbox_detail<detail::markerStruct>, \
|
||||
|
21
third_party/rlbox/include/rlbox_types.hpp
vendored
21
third_party/rlbox/include/rlbox_types.hpp
vendored
@ -64,3 +64,24 @@ class rlbox_dylib_sandbox;
|
||||
template<typename T> \
|
||||
using app_pointer_##SBXNAME = \
|
||||
rlbox::app_pointer<T, rlbox_##SBXNAME##_sandbox_type>;
|
||||
|
||||
// This is like RLBOX_DEFINE_BASE_TYPES_FOR but with an explicit sandbox type
|
||||
#define RLBOX_DEFINE_BASE_TYPES_FOR_TYPE(SBXNAME, SBXTYPE) \
|
||||
using rlbox_##SBXNAME##_sandbox_type = SBXTYPE; \
|
||||
using rlbox_sandbox_##SBXNAME = \
|
||||
rlbox::rlbox_sandbox<rlbox_##SBXNAME##_sandbox_type>; \
|
||||
template<typename T> \
|
||||
using sandbox_callback_##SBXNAME = \
|
||||
rlbox::sandbox_callback<T, rlbox_##SBXNAME##_sandbox_type>; \
|
||||
template<typename T> \
|
||||
using tainted_##SBXNAME = rlbox::tainted<T, rlbox_##SBXNAME##_sandbox_type>; \
|
||||
template<typename T> \
|
||||
using tainted_opaque_##SBXNAME = \
|
||||
rlbox::tainted_opaque<T, rlbox_##SBXNAME##_sandbox_type>; \
|
||||
template<typename T> \
|
||||
using tainted_volatile_##SBXNAME = \
|
||||
rlbox::tainted_volatile<T, rlbox_##SBXNAME##_sandbox_type>; \
|
||||
using rlbox::tainted_boolean_hint; \
|
||||
template<typename T> \
|
||||
using app_pointer_##SBXNAME = \
|
||||
rlbox::app_pointer<T, rlbox_##SBXNAME##_sandbox_type>;
|
||||
|
540
third_party/rlbox_wasm2c_sandbox/include/rlbox_wasm2c_sandbox.hpp
vendored
Executable file → Normal file
540
third_party/rlbox_wasm2c_sandbox/include/rlbox_wasm2c_sandbox.hpp
vendored
Executable file → Normal file
@ -1,6 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "rlbox_wasm2c_tls.hpp"
|
||||
#include "wasm-rt.h"
|
||||
#include "wasm2c_rt_mem.h"
|
||||
#include "wasm2c_rt_minwasi.h"
|
||||
|
||||
// Pull the helper header from the main repo for dynamic_check and scope_exit
|
||||
#include "rlbox_helpers.hpp"
|
||||
@ -21,13 +24,14 @@
|
||||
#include <vector>
|
||||
|
||||
#if defined(_WIN32)
|
||||
// Ensure the min/max macro in the header doesn't collide with functions in std::
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
#include <windows.h>
|
||||
// Ensure the min/max macro in the header doesn't collide with functions in
|
||||
// std::
|
||||
# ifndef NOMINMAX
|
||||
# define NOMINMAX
|
||||
# endif
|
||||
# include <windows.h>
|
||||
#else
|
||||
#include <dlfcn.h>
|
||||
# include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#define RLBOX_WASM2C_UNUSED(...) (void)__VA_ARGS__
|
||||
@ -48,6 +52,76 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define DEFINE_RLBOX_WASM2C_MODULE_TYPE(modname) \
|
||||
struct rlbox_wasm2c_module_type_##modname \
|
||||
{ \
|
||||
using instance_t = w2c_##modname; \
|
||||
\
|
||||
using create_instance_t = void (*)(instance_t*, \
|
||||
struct w2c_env*, \
|
||||
struct w2c_wasi__snapshot__preview1*); \
|
||||
static constexpr create_instance_t create_instance = \
|
||||
&wasm2c_##modname##_instantiate; \
|
||||
\
|
||||
using free_instance_t = void (*)(instance_t*); \
|
||||
static constexpr free_instance_t free_instance = &wasm2c_##modname##_free; \
|
||||
\
|
||||
using get_func_type_t = wasm_rt_func_type_t (*)(uint32_t, uint32_t, ...); \
|
||||
static constexpr get_func_type_t get_func_type = \
|
||||
&wasm2c_##modname##_get_func_type; \
|
||||
\
|
||||
static constexpr const uint64_t* initial_memory_pages = \
|
||||
&wasm2c_##modname##_min_env_memory; \
|
||||
static constexpr const uint8_t* is_memory_64 = \
|
||||
&wasm2c_##modname##_is64_env_memory; \
|
||||
static constexpr const uint32_t* initial_func_elements = \
|
||||
&wasm2c_##modname##_min_env_0x5F_indirect_function_table; \
|
||||
\
|
||||
static constexpr const char* prefix = #modname; \
|
||||
\
|
||||
/* A function that returns the address of the func specified as a \
|
||||
* constexpr string */ \
|
||||
/* Unfortunately, there is no way to implement the below in C++. */ \
|
||||
/* Implement this to fully support multiple static modules. */ \
|
||||
/* static constexpr void* dlsym_in_w2c_module(const char* func_name) { */ \
|
||||
/* return &w2c_##modname##_%func%; */ \
|
||||
/* } */ \
|
||||
\
|
||||
static constexpr auto malloc_address = &w2c_##modname##_malloc; \
|
||||
static constexpr auto free_address = &w2c_##modname##_free; \
|
||||
}
|
||||
|
||||
// wasm_module_name module name used when compiling with wasm2c
|
||||
#ifndef RLBOX_WASM2C_MODULE_NAME
|
||||
# error "Expected definition for RLBOX_WASM2C_MODULE_NAME"
|
||||
#endif
|
||||
|
||||
// Need an extra macro to expand RLBOX_WASM2C_MODULE_NAME
|
||||
#define INVOKE_DEFINE_RLBOX_WASM2C_MODULE_TYPE(modname) \
|
||||
DEFINE_RLBOX_WASM2C_MODULE_TYPE(modname)
|
||||
|
||||
INVOKE_DEFINE_RLBOX_WASM2C_MODULE_TYPE(RLBOX_WASM2C_MODULE_NAME);
|
||||
|
||||
// Concat after macro expansion
|
||||
#define RLBOX_WASM2C_CONCAT2(x, y) x##y
|
||||
#define RLBOX_WASM2C_CONCAT(x, y) RLBOX_WASM2C_CONCAT2(x, y)
|
||||
|
||||
#define RLBOX_WASM_MODULE_TYPE_CURR \
|
||||
RLBOX_WASM2C_CONCAT(rlbox_wasm2c_module_type_, RLBOX_WASM2C_MODULE_NAME)
|
||||
|
||||
#define RLBOX_WASM2C_STRINGIFY(x) RLBOX_WASM2C_STRINGIFY2(x)
|
||||
#define RLBOX_WASM2C_STRINGIFY2(x) #x
|
||||
|
||||
#define RLBOX_WASM2C_MODULE_NAME_STR \
|
||||
RLBOX_WASM2C_STRINGIFY(RLBOX_WASM2C_MODULE_NAME)
|
||||
|
||||
#define RLBOX_WASM2C_MODULE_FUNC_HELPER2(part1, part2, part3) \
|
||||
part1##part2##part3
|
||||
#define RLBOX_WASM2C_MODULE_FUNC_HELPER(part1, part2, part3) \
|
||||
RLBOX_WASM2C_MODULE_FUNC_HELPER2(part1, part2, part3)
|
||||
#define RLBOX_WASM2C_MODULE_FUNC(name) \
|
||||
RLBOX_WASM2C_MODULE_FUNC_HELPER(w2c_, RLBOX_WASM2C_MODULE_NAME, name)
|
||||
|
||||
namespace rlbox {
|
||||
|
||||
namespace wasm2c_detail {
|
||||
@ -211,29 +285,13 @@ namespace wasm2c_detail {
|
||||
|
||||
} // namespace wasm2c_detail
|
||||
|
||||
class rlbox_wasm2c_sandbox;
|
||||
|
||||
struct rlbox_wasm2c_sandbox_thread_data
|
||||
{
|
||||
rlbox_wasm2c_sandbox* sandbox;
|
||||
uint32_t last_callback_invoked;
|
||||
};
|
||||
|
||||
#ifdef RLBOX_EMBEDDER_PROVIDES_TLS_STATIC_VARIABLES
|
||||
|
||||
rlbox_wasm2c_sandbox_thread_data* get_rlbox_wasm2c_sandbox_thread_data();
|
||||
# define RLBOX_WASM2C_SANDBOX_STATIC_VARIABLES() \
|
||||
thread_local rlbox::rlbox_wasm2c_sandbox_thread_data \
|
||||
rlbox_wasm2c_sandbox_thread_info{ 0, 0 }; \
|
||||
namespace rlbox { \
|
||||
rlbox_wasm2c_sandbox_thread_data* get_rlbox_wasm2c_sandbox_thread_data() \
|
||||
{ \
|
||||
return &rlbox_wasm2c_sandbox_thread_info; \
|
||||
} \
|
||||
} \
|
||||
static_assert(true, "Enforce semi-colon")
|
||||
|
||||
// declare the static symbol with weak linkage to keep this header only
|
||||
#if defined(_MSC_VER)
|
||||
__declspec(selectany)
|
||||
#else
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
std::once_flag rlbox_wasm2c_initialized;
|
||||
|
||||
class rlbox_wasm2c_sandbox
|
||||
{
|
||||
@ -245,22 +303,16 @@ public:
|
||||
using T_ShortType = int16_t;
|
||||
|
||||
private:
|
||||
void* sandbox = nullptr;
|
||||
wasm2c_sandbox_funcs_t sandbox_info;
|
||||
#if !defined(_MSC_VER)
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
static std::once_flag wasm2c_runtime_initialized;
|
||||
wasm_rt_memory_t* sandbox_memory_info = nullptr;
|
||||
#ifndef RLBOX_USE_STATIC_CALLS
|
||||
void* library = nullptr;
|
||||
#endif
|
||||
mutable typename RLBOX_WASM_MODULE_TYPE_CURR::instance_t wasm2c_instance{ 0 };
|
||||
struct w2c_env sandbox_memory_env;
|
||||
struct w2c_wasi__snapshot__preview1 wasi_env;
|
||||
bool instance_initialized = false;
|
||||
wasm_rt_memory_t sandbox_memory_info;
|
||||
mutable wasm_rt_funcref_table_t sandbox_callback_table;
|
||||
uintptr_t heap_base;
|
||||
void* exec_env = 0;
|
||||
void* malloc_index = 0;
|
||||
void* free_index = 0;
|
||||
size_t return_slot_size = 0;
|
||||
T_PointerType return_slot = 0;
|
||||
mutable std::vector<T_PointerType> callback_free_list;
|
||||
|
||||
static const size_t MAX_CALLBACKS = 128;
|
||||
mutable RLBOX_SHARED_LOCK(callback_mutex);
|
||||
@ -271,7 +323,8 @@ __attribute__((weak))
|
||||
mutable std::map<uint32_t, const void*> slot_assignments;
|
||||
|
||||
#ifndef RLBOX_EMBEDDER_PROVIDES_TLS_STATIC_VARIABLES
|
||||
thread_local static inline rlbox_wasm2c_sandbox_thread_data thread_data{ 0, 0 };
|
||||
thread_local static inline rlbox_wasm2c_sandbox_thread_data thread_data{ 0,
|
||||
0 };
|
||||
#endif
|
||||
|
||||
template<typename T_FormalRet, typename T_ActualRet>
|
||||
@ -309,7 +362,8 @@ __attribute__((weak))
|
||||
// Callbacks are invoked through function pointers, cannot use std::forward
|
||||
// as we don't have caller context for T_Args, which means they are all
|
||||
// effectively passed by value
|
||||
return func(thread_data.sandbox->serialize_to_sandbox<T_Args>(params)...);
|
||||
return func(
|
||||
thread_data.sandbox->template serialize_to_sandbox<T_Args>(params)...);
|
||||
}
|
||||
|
||||
template<uint32_t N, typename T_Ret, typename... T_Args>
|
||||
@ -333,8 +387,8 @@ __attribute__((weak))
|
||||
// Callbacks are invoked through function pointers, cannot use std::forward
|
||||
// as we don't have caller context for T_Args, which means they are all
|
||||
// effectively passed by value
|
||||
auto ret_val =
|
||||
func(thread_data.sandbox->serialize_to_sandbox<T_Args>(params)...);
|
||||
auto ret_val = func(
|
||||
thread_data.sandbox->template serialize_to_sandbox<T_Args>(params)...);
|
||||
// Copy the return value back
|
||||
auto ret_ptr = reinterpret_cast<T_Ret*>(
|
||||
thread_data.sandbox->template impl_get_unsandboxed_pointer<T_Ret*>(ret));
|
||||
@ -342,35 +396,31 @@ __attribute__((weak))
|
||||
}
|
||||
|
||||
template<typename T_Ret, typename... T_Args>
|
||||
inline uint32_t get_wasm2c_func_index(
|
||||
inline wasm_rt_func_type_t get_wasm2c_func_index(
|
||||
// dummy for template inference
|
||||
T_Ret (*)(T_Args...) = nullptr
|
||||
) const
|
||||
T_Ret (*)(T_Args...) = nullptr) const
|
||||
{
|
||||
// Class return types as promoted to args
|
||||
constexpr bool promoted = std::is_class_v<T_Ret>;
|
||||
constexpr uint32_t param_count =
|
||||
promoted ? (sizeof...(T_Args) + 1) : (sizeof...(T_Args));
|
||||
constexpr uint32_t ret_count =
|
||||
promoted ? 0 : (std::is_void_v<T_Ret> ? 0 : 1);
|
||||
|
||||
// If return type is void, then there is no return type
|
||||
// But it is fine if we add it anyway as it as at the end of the array
|
||||
// and we pass in counts to lookup_wasm2c_func_index that would result in this
|
||||
// element not being accessed
|
||||
wasm_rt_type_t ret_param_types[] = {
|
||||
wasm2c_detail::convert_type_to_wasm_type<T_Args>::wasm2c_type...,
|
||||
wasm2c_detail::convert_type_to_wasm_type<T_Ret>::wasm2c_type
|
||||
};
|
||||
|
||||
uint32_t param_count = 0;
|
||||
uint32_t ret_count = 0;
|
||||
|
||||
if constexpr (promoted) {
|
||||
param_count = sizeof...(T_Args) + 1;
|
||||
ret_count = 0;
|
||||
wasm_rt_func_type_t ret = nullptr;
|
||||
if constexpr (ret_count == 0) {
|
||||
ret = RLBOX_WASM_MODULE_TYPE_CURR::get_func_type(
|
||||
param_count,
|
||||
ret_count,
|
||||
wasm2c_detail::convert_type_to_wasm_type<T_Args>::wasm2c_type...);
|
||||
} else {
|
||||
param_count = sizeof...(T_Args);
|
||||
ret_count = std::is_void_v<T_Ret>? 0 : 1;
|
||||
ret = RLBOX_WASM_MODULE_TYPE_CURR::get_func_type(
|
||||
param_count,
|
||||
ret_count,
|
||||
wasm2c_detail::convert_type_to_wasm_type<T_Args>::wasm2c_type...,
|
||||
wasm2c_detail::convert_type_to_wasm_type<T_Ret>::wasm2c_type);
|
||||
}
|
||||
|
||||
auto ret = sandbox_info.lookup_wasm2c_func_index(sandbox, param_count, ret_count, ret_param_types);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -388,78 +438,21 @@ __attribute__((weak))
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef RLBOX_USE_STATIC_CALLS
|
||||
inline void* symbol_lookup(std::string prefixed_name) {
|
||||
#if defined(_WIN32)
|
||||
void* ret = (void*) GetProcAddress((HMODULE) library, prefixed_name.c_str());
|
||||
#else
|
||||
void* ret = dlsym(library, prefixed_name.c_str());
|
||||
#endif
|
||||
if (ret == nullptr) {
|
||||
// Some lookups such as globals are not exposed as shared library symbols
|
||||
uint32_t* heap_index_pointer = (uint32_t*) sandbox_info.lookup_wasm2c_nonfunc_export(sandbox, prefixed_name.c_str());
|
||||
if (heap_index_pointer != nullptr) {
|
||||
uint32_t heap_index = *heap_index_pointer;
|
||||
ret = &(reinterpret_cast<char*>(heap_base)[heap_index]);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
// function takes a 32-bit value and returns the next power of 2
|
||||
// return is a 64-bit value as large 32-bit values will return 2^32
|
||||
static inline uint64_t next_power_of_two(uint32_t value) {
|
||||
static inline uint64_t next_power_of_two(uint32_t value)
|
||||
{
|
||||
uint64_t power = 1;
|
||||
while(power < value) {
|
||||
while (power < value) {
|
||||
power *= 2;
|
||||
}
|
||||
return power;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
#define WASM_PAGE_SIZE 65536
|
||||
#define WASM_HEAP_MAX_ALLOWED_PAGES 65536
|
||||
#define WASM_MAX_HEAP (static_cast<uint64_t>(1) << 32)
|
||||
static uint64_t rlbox_wasm2c_get_adjusted_heap_size(uint64_t heap_size)
|
||||
{
|
||||
if (heap_size == 0){
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(heap_size <= WASM_PAGE_SIZE) {
|
||||
return WASM_PAGE_SIZE;
|
||||
} else if (heap_size >= WASM_MAX_HEAP) {
|
||||
return WASM_MAX_HEAP;
|
||||
}
|
||||
|
||||
return next_power_of_two(static_cast<uint32_t>(heap_size));
|
||||
}
|
||||
|
||||
static uint64_t rlbox_wasm2c_get_heap_page_count(uint64_t heap_size)
|
||||
{
|
||||
const uint64_t pages = heap_size / WASM_PAGE_SIZE;
|
||||
return pages;
|
||||
}
|
||||
#undef WASM_MAX_HEAP
|
||||
#undef WASM_HEAP_MAX_ALLOWED_PAGES
|
||||
#undef WASM_PAGE_SIZE
|
||||
|
||||
protected:
|
||||
|
||||
#ifndef RLBOX_USE_STATIC_CALLS
|
||||
void* impl_lookup_symbol(const char* func_name)
|
||||
{
|
||||
std::string prefixed_name = "w2c_";
|
||||
prefixed_name += func_name;
|
||||
void* ret = symbol_lookup(prefixed_name);
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
|
||||
#define rlbox_wasm2c_sandbox_lookup_symbol(func_name) \
|
||||
reinterpret_cast<void*>(&w2c_##func_name) /* NOLINT */
|
||||
#define rlbox_wasm2c_sandbox_lookup_symbol(func_name) \
|
||||
reinterpret_cast<void*>(&RLBOX_WASM2C_MODULE_FUNC(_##func_name)) /* NOLINT \
|
||||
*/
|
||||
|
||||
// adding a template so that we can use static_assert to fire only if this
|
||||
// function is invoked
|
||||
@ -474,116 +467,90 @@ protected:
|
||||
"to their code, to ensure that static calls are handled correctly.");
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
using path_buf = const LPCWSTR;
|
||||
#else
|
||||
using path_buf = const char*;
|
||||
#endif
|
||||
|
||||
#define FALLIBLE_DYNAMIC_CHECK(infallible, cond, msg) \
|
||||
if (infallible) { \
|
||||
detail::dynamic_check(cond, msg); \
|
||||
} else if(!(cond)) { \
|
||||
impl_destroy_sandbox(); \
|
||||
return false; \
|
||||
public:
|
||||
#define FALLIBLE_DYNAMIC_CHECK(infallible, cond, msg) \
|
||||
if (infallible) { \
|
||||
detail::dynamic_check(cond, msg); \
|
||||
} else if (!(cond)) { \
|
||||
impl_destroy_sandbox(); \
|
||||
return false; \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief creates the Wasm sandbox from the given shared library
|
||||
*
|
||||
* @param wasm2c_module_path path to shared library compiled with wasm2c. This param is not specified if you are creating a statically linked sandbox.
|
||||
* @param infallible if set to true, the sandbox aborts on failure. If false, the sandbox returns creation status as a return value
|
||||
* @param override_max_heap_size optional override of the maximum size of the wasm heap allowed for this sandbox instance. When the value is zero, platform defaults are used. Non-zero values are rounded to max(64k, next power of 2).
|
||||
* @param wasm_module_name optional module name used when compiling with wasm2c
|
||||
* @return true when sandbox is successfully created
|
||||
* @return false when infallible if set to false and sandbox was not successfully created. If infallible is set to true, this function will never return false.
|
||||
* @param infallible if set to true, the sandbox aborts on failure. If false,
|
||||
* the sandbox returns creation status as a return value
|
||||
* @param custom_capacity allows optionally overriding the platform-specified
|
||||
* maximum size of the wasm heap allowed for this sandbox instance.
|
||||
* @return true when sandbox is successfully created. false when infallible is
|
||||
* set to false and sandbox was not successfully created. If infallible is set
|
||||
* to true, this function will never return false.
|
||||
*/
|
||||
inline bool impl_create_sandbox(
|
||||
#ifndef RLBOX_USE_STATIC_CALLS
|
||||
path_buf wasm2c_module_path,
|
||||
#endif
|
||||
bool infallible = true, uint64_t override_max_heap_size = 0, const char* wasm_module_name = "")
|
||||
bool infallible = true,
|
||||
const w2c_mem_capacity* custom_capacity = nullptr)
|
||||
{
|
||||
FALLIBLE_DYNAMIC_CHECK(infallible, sandbox == nullptr, "Sandbox already initialized");
|
||||
FALLIBLE_DYNAMIC_CHECK(
|
||||
infallible, instance_initialized == false, "Sandbox already initialized");
|
||||
|
||||
#ifndef RLBOX_USE_STATIC_CALLS
|
||||
#if defined(_WIN32)
|
||||
library = (void*) LoadLibraryW(wasm2c_module_path);
|
||||
#else
|
||||
library = dlopen(wasm2c_module_path, RTLD_LAZY);
|
||||
#endif
|
||||
bool minwasi_init_succeeded = true;
|
||||
|
||||
if (!library) {
|
||||
std::string error_msg = "Could not load wasm2c dynamic library: ";
|
||||
#if defined(_WIN32)
|
||||
DWORD errorMessageID = GetLastError();
|
||||
if (errorMessageID != 0) {
|
||||
LPSTR messageBuffer = nullptr;
|
||||
//The api creates the buffer that holds the message
|
||||
size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);
|
||||
//Copy the error message into a std::string.
|
||||
std::string message(messageBuffer, size);
|
||||
error_msg += message;
|
||||
LocalFree(messageBuffer);
|
||||
}
|
||||
#else
|
||||
error_msg += dlerror();
|
||||
#endif
|
||||
FALLIBLE_DYNAMIC_CHECK(infallible, false, error_msg.c_str());
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef RLBOX_USE_STATIC_CALLS
|
||||
std::string info_func_name = wasm_module_name;
|
||||
info_func_name += "get_wasm2c_sandbox_info";
|
||||
auto get_info_func = reinterpret_cast<wasm2c_sandbox_funcs_t(*)()>(symbol_lookup(info_func_name));
|
||||
#else
|
||||
// only permitted if there is no custom module name
|
||||
std::string wasm_module_name_str = wasm_module_name;
|
||||
FALLIBLE_DYNAMIC_CHECK(infallible, wasm_module_name_str.empty(), "Static calls not supported with non empty module names");
|
||||
auto get_info_func = reinterpret_cast<wasm2c_sandbox_funcs_t(*)()>(get_wasm2c_sandbox_info);
|
||||
#endif
|
||||
FALLIBLE_DYNAMIC_CHECK(infallible, get_info_func != nullptr, "wasm2c could not find <MODULE_NAME>get_wasm2c_sandbox_info");
|
||||
sandbox_info = get_info_func();
|
||||
|
||||
std::call_once(wasm2c_runtime_initialized, [&](){
|
||||
sandbox_info.wasm_rt_sys_init();
|
||||
std::call_once(rlbox_wasm2c_initialized, [&]() {
|
||||
wasm_rt_init();
|
||||
minwasi_init_succeeded = minwasi_init();
|
||||
});
|
||||
|
||||
override_max_heap_size = rlbox_wasm2c_get_adjusted_heap_size(override_max_heap_size);
|
||||
const uint64_t override_max_wasm_pages = rlbox_wasm2c_get_heap_page_count(override_max_heap_size);
|
||||
FALLIBLE_DYNAMIC_CHECK(infallible, override_max_wasm_pages <= 65536, "Wasm allows a max heap size of 4GB");
|
||||
FALLIBLE_DYNAMIC_CHECK(
|
||||
infallible, minwasi_init_succeeded, "Could not initialize min wasi");
|
||||
|
||||
sandbox = sandbox_info.create_wasm2c_sandbox(static_cast<uint32_t>(override_max_wasm_pages));
|
||||
FALLIBLE_DYNAMIC_CHECK(infallible, sandbox != nullptr, "Sandbox could not be created");
|
||||
const bool minwasi_init_inst_succeeded = minwasi_init_instance(&wasi_env);
|
||||
FALLIBLE_DYNAMIC_CHECK(
|
||||
infallible, minwasi_init_inst_succeeded, "Could not initialize min wasi instance");
|
||||
|
||||
sandbox_memory_info = (wasm_rt_memory_t*) sandbox_info.lookup_wasm2c_nonfunc_export(sandbox, "w2c_memory");
|
||||
FALLIBLE_DYNAMIC_CHECK(infallible, sandbox_memory_info != nullptr, "Could not get wasm2c sandbox memory info");
|
||||
if (custom_capacity) {
|
||||
FALLIBLE_DYNAMIC_CHECK(
|
||||
infallible, custom_capacity->is_valid, "Invalid capacity");
|
||||
}
|
||||
|
||||
sandbox_memory_info = create_wasm2c_memory(
|
||||
*RLBOX_WASM_MODULE_TYPE_CURR::initial_memory_pages, custom_capacity);
|
||||
FALLIBLE_DYNAMIC_CHECK(infallible,
|
||||
sandbox_memory_info.data != nullptr,
|
||||
"Could not allocate a heap for the wasm2c sandbox");
|
||||
|
||||
FALLIBLE_DYNAMIC_CHECK(infallible,
|
||||
*RLBOX_WASM_MODULE_TYPE_CURR::is_memory_64 == 0,
|
||||
"Does not support Wasm with memory64");
|
||||
|
||||
const uint32_t max_table_size = 0xffffffffu; /* this means unlimited */
|
||||
wasm_rt_allocate_funcref_table(
|
||||
&sandbox_callback_table,
|
||||
*RLBOX_WASM_MODULE_TYPE_CURR::initial_func_elements,
|
||||
max_table_size);
|
||||
|
||||
sandbox_memory_env.sandbox_memory_info = &sandbox_memory_info;
|
||||
sandbox_memory_env.sandbox_callback_table = &sandbox_callback_table;
|
||||
wasi_env.instance_memory = &sandbox_memory_info;
|
||||
RLBOX_WASM_MODULE_TYPE_CURR::create_instance(
|
||||
&wasm2c_instance, &sandbox_memory_env, &wasi_env);
|
||||
|
||||
heap_base = reinterpret_cast<uintptr_t>(impl_get_memory_location());
|
||||
|
||||
if constexpr (sizeof(uintptr_t) != sizeof(uint32_t)) {
|
||||
// On larger platforms, check that the heap is aligned to the pointer size
|
||||
// i.e. 32-bit pointer => aligned to 4GB. The implementations of
|
||||
// impl_get_unsandboxed_pointer_no_ctx and impl_get_sandboxed_pointer_no_ctx
|
||||
// below rely on this.
|
||||
// impl_get_unsandboxed_pointer_no_ctx and
|
||||
// impl_get_sandboxed_pointer_no_ctx below rely on this.
|
||||
uintptr_t heap_offset_mask = std::numeric_limits<T_PointerType>::max();
|
||||
FALLIBLE_DYNAMIC_CHECK(infallible, (heap_base & heap_offset_mask) == 0,
|
||||
"Sandbox heap not aligned to 4GB");
|
||||
FALLIBLE_DYNAMIC_CHECK(infallible,
|
||||
(heap_base & heap_offset_mask) == 0,
|
||||
"Sandbox heap not aligned to 4GB");
|
||||
}
|
||||
|
||||
// cache these for performance
|
||||
exec_env = sandbox;
|
||||
#ifndef RLBOX_USE_STATIC_CALLS
|
||||
malloc_index = impl_lookup_symbol("malloc");
|
||||
free_index = impl_lookup_symbol("free");
|
||||
#else
|
||||
malloc_index = rlbox_wasm2c_sandbox_lookup_symbol(malloc);
|
||||
free_index = rlbox_wasm2c_sandbox_lookup_symbol(free);
|
||||
#endif
|
||||
instance_initialized = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -595,21 +562,14 @@ protected:
|
||||
impl_free_in_sandbox(return_slot);
|
||||
}
|
||||
|
||||
if (sandbox != nullptr) {
|
||||
sandbox_info.destroy_wasm2c_sandbox(sandbox);
|
||||
sandbox = nullptr;
|
||||
if (instance_initialized) {
|
||||
instance_initialized = false;
|
||||
RLBOX_WASM_MODULE_TYPE_CURR::free_instance(&wasm2c_instance);
|
||||
}
|
||||
|
||||
#ifndef RLBOX_USE_STATIC_CALLS
|
||||
if (library != nullptr) {
|
||||
#if defined(_WIN32)
|
||||
FreeLibrary((HMODULE) library);
|
||||
#else
|
||||
dlclose(library);
|
||||
#endif
|
||||
library = nullptr;
|
||||
}
|
||||
#endif
|
||||
destroy_wasm2c_memory(&sandbox_memory_info);
|
||||
wasm_rt_free_funcref_table(&sandbox_callback_table);
|
||||
minwasi_cleanup_instance(&wasi_env);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@ -641,16 +601,22 @@ protected:
|
||||
slot_number = found->second;
|
||||
} else {
|
||||
|
||||
auto func_type_idx = get_wasm2c_func_index(static_cast<T>(nullptr));
|
||||
slot_number =
|
||||
sandbox_info.add_wasm2c_callback(sandbox, func_type_idx, const_cast<void*>(p), WASM_RT_INTERNAL_FUNCTION);
|
||||
slot_number = new_callback_slot();
|
||||
wasm_rt_funcref_t func_val;
|
||||
func_val.func_type = get_wasm2c_func_index(static_cast<T>(nullptr));
|
||||
func_val.func =
|
||||
reinterpret_cast<wasm_rt_function_ptr_t>(const_cast<void*>(p));
|
||||
func_val.module_instance = &wasm2c_instance;
|
||||
|
||||
sandbox_callback_table.data[slot_number] = func_val;
|
||||
internal_callbacks[p] = slot_number;
|
||||
slot_assignments[slot_number] = p;
|
||||
}
|
||||
return static_cast<T_PointerType>(slot_number);
|
||||
} else {
|
||||
if constexpr (sizeof(uintptr_t) == sizeof(uint32_t)) {
|
||||
return static_cast<T_PointerType>(reinterpret_cast<uintptr_t>(p) - heap_base);
|
||||
return static_cast<T_PointerType>(reinterpret_cast<uintptr_t>(p) -
|
||||
heap_base);
|
||||
} else {
|
||||
return static_cast<T_PointerType>(reinterpret_cast<uintptr_t>(p));
|
||||
}
|
||||
@ -667,13 +633,13 @@ protected:
|
||||
// on 32-bit platforms we don't assume the heap is aligned
|
||||
if constexpr (sizeof(uintptr_t) == sizeof(uint32_t)) {
|
||||
auto sandbox = expensive_sandbox_finder(example_unsandboxed_ptr);
|
||||
return sandbox->impl_get_unsandboxed_pointer<T>(p);
|
||||
return sandbox->template impl_get_unsandboxed_pointer<T>(p);
|
||||
} else {
|
||||
if constexpr (std::is_function_v<std::remove_pointer_t<T>>) {
|
||||
// swizzling function pointers needs access to the function pointer tables
|
||||
// and thus cannot be done without context
|
||||
// swizzling function pointers needs access to the function pointer
|
||||
// tables and thus cannot be done without context
|
||||
auto sandbox = expensive_sandbox_finder(example_unsandboxed_ptr);
|
||||
return sandbox->impl_get_unsandboxed_pointer<T>(p);
|
||||
return sandbox->template impl_get_unsandboxed_pointer<T>(p);
|
||||
} else {
|
||||
// grab the memory base from the example_unsandboxed_ptr
|
||||
uintptr_t heap_base_mask =
|
||||
@ -697,13 +663,13 @@ protected:
|
||||
// on 32-bit platforms we don't assume the heap is aligned
|
||||
if constexpr (sizeof(uintptr_t) == sizeof(uint32_t)) {
|
||||
auto sandbox = expensive_sandbox_finder(example_unsandboxed_ptr);
|
||||
return sandbox->impl_get_sandboxed_pointer<T>(p);
|
||||
return sandbox->template impl_get_sandboxed_pointer<T>(p);
|
||||
} else {
|
||||
if constexpr (std::is_function_v<std::remove_pointer_t<T>>) {
|
||||
// swizzling function pointers needs access to the function pointer tables
|
||||
// and thus cannot be done without context
|
||||
// swizzling function pointers needs access to the function pointer
|
||||
// tables and thus cannot be done without context
|
||||
auto sandbox = expensive_sandbox_finder(example_unsandboxed_ptr);
|
||||
return sandbox->impl_get_sandboxed_pointer<T>(p);
|
||||
return sandbox->template impl_get_sandboxed_pointer<T>(p);
|
||||
} else {
|
||||
// Just clear the memory base to leave the offset
|
||||
RLBOX_WASM2C_UNUSED(example_unsandboxed_ptr);
|
||||
@ -734,11 +700,11 @@ protected:
|
||||
return !(impl_is_pointer_in_sandbox_memory(p));
|
||||
}
|
||||
|
||||
inline size_t impl_get_total_memory() { return sandbox_memory_info->size; }
|
||||
inline size_t impl_get_total_memory() { return sandbox_memory_info.size; }
|
||||
|
||||
inline void* impl_get_memory_location() const
|
||||
{
|
||||
return sandbox_memory_info->data;
|
||||
return sandbox_memory_info.data;
|
||||
}
|
||||
|
||||
template<typename T, typename T_Converted, typename... T_Args>
|
||||
@ -749,9 +715,8 @@ protected:
|
||||
#endif
|
||||
auto old_sandbox = thread_data.sandbox;
|
||||
thread_data.sandbox = this;
|
||||
auto on_exit = detail::make_scope_exit([&] {
|
||||
thread_data.sandbox = old_sandbox;
|
||||
});
|
||||
auto on_exit =
|
||||
detail::make_scope_exit([&] { thread_data.sandbox = old_sandbox; });
|
||||
|
||||
// WASM functions are mangled in the following manner
|
||||
// 1. All primitive types are left as is and follow an LP32 machine model
|
||||
@ -819,7 +784,9 @@ protected:
|
||||
wasm2c_detail::change_class_arg_types<T_Converted, T_PointerType>;
|
||||
|
||||
// Handle Point 5
|
||||
using T_ConvHeap = wasm2c_detail::prepend_arg_type<T_ConvNoClass, void*>;
|
||||
using T_ConvHeap = wasm2c_detail::prepend_arg_type<
|
||||
T_ConvNoClass,
|
||||
typename RLBOX_WASM_MODULE_TYPE_CURR::instance_t*>;
|
||||
|
||||
// Function invocation
|
||||
auto func_ptr_conv =
|
||||
@ -831,9 +798,9 @@ protected:
|
||||
|
||||
if constexpr (std::is_void_v<T_Ret>) {
|
||||
RLBOX_WASM2C_UNUSED(ret);
|
||||
func_ptr_conv(exec_env, serialize_class_arg(params)...);
|
||||
func_ptr_conv(&wasm2c_instance, serialize_class_arg(params)...);
|
||||
} else {
|
||||
ret = func_ptr_conv(exec_env, serialize_class_arg(params)...);
|
||||
ret = func_ptr_conv(&wasm2c_instance, serialize_class_arg(params)...);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < alloc_length; i++) {
|
||||
@ -847,14 +814,15 @@ protected:
|
||||
|
||||
inline T_PointerType impl_malloc_in_sandbox(size_t size)
|
||||
{
|
||||
if constexpr(sizeof(size) > sizeof(uint32_t)) {
|
||||
if constexpr (sizeof(size) > sizeof(uint32_t)) {
|
||||
detail::dynamic_check(size <= std::numeric_limits<uint32_t>::max(),
|
||||
"Attempting to malloc more than the heap size");
|
||||
}
|
||||
using T_Func = void*(size_t);
|
||||
using T_Converted = T_PointerType(uint32_t);
|
||||
T_PointerType ret = impl_invoke_with_func_ptr<T_Func, T_Converted>(
|
||||
reinterpret_cast<T_Converted*>(malloc_index),
|
||||
reinterpret_cast<T_Converted*>(
|
||||
RLBOX_WASM_MODULE_TYPE_CURR::malloc_address),
|
||||
static_cast<uint32_t>(size));
|
||||
return ret;
|
||||
}
|
||||
@ -864,15 +832,56 @@ protected:
|
||||
using T_Func = void(void*);
|
||||
using T_Converted = void(T_PointerType);
|
||||
impl_invoke_with_func_ptr<T_Func, T_Converted>(
|
||||
reinterpret_cast<T_Converted*>(free_index), p);
|
||||
reinterpret_cast<T_Converted*>(RLBOX_WASM_MODULE_TYPE_CURR::free_address),
|
||||
p);
|
||||
}
|
||||
|
||||
private:
|
||||
// Should be called with callback_mutex held
|
||||
uint32_t new_callback_slot() const
|
||||
{
|
||||
if (callback_free_list.size() > 0) {
|
||||
uint32_t ret = callback_free_list.back();
|
||||
callback_free_list.pop_back();
|
||||
return ret;
|
||||
}
|
||||
|
||||
const uint32_t curr_size = sandbox_callback_table.size;
|
||||
|
||||
detail::dynamic_check(
|
||||
curr_size < sandbox_callback_table.max_size,
|
||||
"Could not find an empty row in Wasm instance table. This would "
|
||||
"happen if you have registered too many callbacks, or unsandboxed "
|
||||
"too many function pointers.");
|
||||
|
||||
wasm_rt_funcref_t func_val{ 0 };
|
||||
// on success, this returns the previous number of elements in the table
|
||||
const uint32_t ret =
|
||||
wasm_rt_grow_funcref_table(&sandbox_callback_table, 1, func_val);
|
||||
|
||||
detail::dynamic_check(
|
||||
ret != 0 && ret != (uint32_t)-1,
|
||||
"Adding a new callback slot to the wasm instance failed.");
|
||||
|
||||
// We have expanded the number of slots
|
||||
// Previous slots size: ret
|
||||
// New slot is at index: ret
|
||||
const uint32_t slot_number = ret;
|
||||
return slot_number;
|
||||
}
|
||||
|
||||
void free_callback_slot(uint32_t slot) const
|
||||
{
|
||||
callback_free_list.push_back(slot);
|
||||
}
|
||||
|
||||
public:
|
||||
template<typename T_Ret, typename... T_Args>
|
||||
inline T_PointerType impl_register_callback(void* key, void* callback)
|
||||
{
|
||||
bool found = false;
|
||||
uint32_t found_loc = 0;
|
||||
void* chosen_interceptor = nullptr;
|
||||
wasm_rt_function_ptr_t chosen_interceptor = nullptr;
|
||||
|
||||
RLBOX_ACQUIRE_UNIQUE_GUARD(lock, callback_mutex);
|
||||
|
||||
@ -885,11 +894,11 @@ protected:
|
||||
found_loc = i;
|
||||
|
||||
if constexpr (std::is_class_v<T_Ret>) {
|
||||
chosen_interceptor = reinterpret_cast<void*>(
|
||||
chosen_interceptor = (wasm_rt_function_ptr_t)(
|
||||
callback_interceptor_promoted<i, T_Ret, T_Args...>);
|
||||
} else {
|
||||
chosen_interceptor =
|
||||
reinterpret_cast<void*>(callback_interceptor<i, T_Ret, T_Args...>);
|
||||
(wasm_rt_function_ptr_t)(callback_interceptor<i, T_Ret, T_Args...>);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -902,9 +911,13 @@ protected:
|
||||
"increase the maximum allowed callbacks or unsadnboxed functions "
|
||||
"pointers");
|
||||
|
||||
auto func_type_idx = get_wasm2c_func_index<T_Ret, T_Args...>();
|
||||
uint32_t slot_number =
|
||||
sandbox_info.add_wasm2c_callback(sandbox, func_type_idx, chosen_interceptor, WASM_RT_EXTERNAL_FUNCTION);
|
||||
wasm_rt_funcref_t func_val;
|
||||
func_val.func_type = get_wasm2c_func_index<T_Ret, T_Args...>();
|
||||
func_val.func = chosen_interceptor;
|
||||
func_val.module_instance = &wasm2c_instance;
|
||||
|
||||
const uint32_t slot_number = new_callback_slot();
|
||||
sandbox_callback_table.data[slot_number] = func_val;
|
||||
|
||||
callback_unique_keys[found_loc] = key;
|
||||
callbacks[found_loc] = callback;
|
||||
@ -935,7 +948,10 @@ protected:
|
||||
RLBOX_ACQUIRE_UNIQUE_GUARD(lock, callback_mutex);
|
||||
for (; i < MAX_CALLBACKS; i++) {
|
||||
if (callback_unique_keys[i] == key) {
|
||||
sandbox_info.remove_wasm2c_callback(sandbox, callback_slot_assignment[i]);
|
||||
const uint32_t slot_number = callback_slot_assignment[i];
|
||||
wasm_rt_funcref_t func_val{ 0 };
|
||||
sandbox_callback_table.data[slot_number] = func_val;
|
||||
|
||||
callback_unique_keys[i] = nullptr;
|
||||
callbacks[i] = nullptr;
|
||||
callback_slot_assignment[i] = 0;
|
||||
@ -952,12 +968,4 @@ protected:
|
||||
}
|
||||
};
|
||||
|
||||
// declare the static symbol with weak linkage to keep this header only
|
||||
#if defined(_MSC_VER)
|
||||
__declspec(selectany)
|
||||
#else
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
std::once_flag rlbox_wasm2c_sandbox::wasm2c_runtime_initialized;
|
||||
|
||||
} // namespace rlbox
|
||||
|
33
third_party/rlbox_wasm2c_sandbox/include/rlbox_wasm2c_tls.hpp
vendored
Normal file
33
third_party/rlbox_wasm2c_sandbox/include/rlbox_wasm2c_tls.hpp
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace rlbox {
|
||||
|
||||
class rlbox_wasm2c_sandbox;
|
||||
|
||||
struct rlbox_wasm2c_sandbox_thread_data
|
||||
{
|
||||
rlbox_wasm2c_sandbox* sandbox;
|
||||
uint32_t last_callback_invoked;
|
||||
};
|
||||
|
||||
#ifdef RLBOX_EMBEDDER_PROVIDES_TLS_STATIC_VARIABLES
|
||||
|
||||
rlbox_wasm2c_sandbox_thread_data* get_rlbox_wasm2c_sandbox_thread_data();
|
||||
|
||||
# define RLBOX_WASM2C_SANDBOX_STATIC_VARIABLES() \
|
||||
thread_local rlbox::rlbox_wasm2c_sandbox_thread_data \
|
||||
rlbox_wasm2c_sandbox_thread_info{ 0, 0 }; \
|
||||
\
|
||||
namespace rlbox { \
|
||||
rlbox_wasm2c_sandbox_thread_data* get_rlbox_wasm2c_sandbox_thread_data() \
|
||||
{ \
|
||||
return &rlbox_wasm2c_sandbox_thread_info; \
|
||||
} \
|
||||
} \
|
||||
static_assert(true, "Enforce semi-colon")
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace rlbox
|
46
third_party/rlbox_wasm2c_sandbox/include/wasm2c_rt_mem.h
vendored
Normal file
46
third_party/rlbox_wasm2c_sandbox/include/wasm2c_rt_mem.h
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
#ifndef WASM_RT_OS_H_
|
||||
#define WASM_RT_OS_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "wasm-rt.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
typedef struct w2c_env
|
||||
{
|
||||
wasm_rt_memory_t* sandbox_memory_info;
|
||||
wasm_rt_funcref_table_t* sandbox_callback_table;
|
||||
} w2c_env;
|
||||
|
||||
wasm_rt_memory_t* w2c_env_memory(struct w2c_env* instance);
|
||||
wasm_rt_funcref_table_t* w2c_env_0x5F_indirect_function_table(
|
||||
struct w2c_env*);
|
||||
|
||||
typedef struct w2c_mem_capacity
|
||||
{
|
||||
bool is_valid;
|
||||
bool is_mem_32;
|
||||
uint64_t max_pages;
|
||||
uint64_t max_size;
|
||||
} w2c_mem_capacity;
|
||||
|
||||
w2c_mem_capacity get_valid_wasm2c_memory_capacity(uint64_t min_capacity,
|
||||
bool is_mem_32);
|
||||
|
||||
wasm_rt_memory_t create_wasm2c_memory(
|
||||
uint32_t initial_pages,
|
||||
const w2c_mem_capacity* custom_capacity);
|
||||
void destroy_wasm2c_memory(wasm_rt_memory_t* memory);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
38
third_party/rlbox_wasm2c_sandbox/include/wasm2c_rt_minwasi.h
vendored
Normal file
38
third_party/rlbox_wasm2c_sandbox/include/wasm2c_rt_minwasi.h
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
#ifndef WASM_RT_MINWASI_H_
|
||||
#define WASM_RT_MINWASI_H_
|
||||
|
||||
/* A minimum wasi implementation supporting only stdin, stdout, stderr, argv
|
||||
* (upto 100 args) and clock functions. */
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "wasm-rt.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
typedef struct w2c_wasi__snapshot__preview1
|
||||
{
|
||||
wasm_rt_memory_t* instance_memory;
|
||||
|
||||
uint32_t main_argc;
|
||||
const char** main_argv;
|
||||
|
||||
uint32_t env_count;
|
||||
const char** env;
|
||||
|
||||
void* clock_data;
|
||||
} w2c_wasi__snapshot__preview1;
|
||||
|
||||
bool minwasi_init();
|
||||
bool minwasi_init_instance(w2c_wasi__snapshot__preview1* wasi_data);
|
||||
void minwasi_cleanup_instance(w2c_wasi__snapshot__preview1* wasi_data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
454
third_party/rlbox_wasm2c_sandbox/src/wasm2c_rt_mem.c
vendored
Normal file
454
third_party/rlbox_wasm2c_sandbox/src/wasm2c_rt_mem.c
vendored
Normal file
@ -0,0 +1,454 @@
|
||||
#include "wasm2c_rt_mem.h"
|
||||
#include "wasm-rt.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
enum
|
||||
{
|
||||
MMAP_PROT_NONE = 0,
|
||||
MMAP_PROT_READ = 1,
|
||||
MMAP_PROT_WRITE = 2,
|
||||
MMAP_PROT_EXEC = 4
|
||||
};
|
||||
|
||||
/* Memory map flags */
|
||||
enum
|
||||
{
|
||||
MMAP_MAP_NONE = 0,
|
||||
/* Put the mapping into 0 to 2 G, supported only on x86_64 */
|
||||
MMAP_MAP_32BIT = 1,
|
||||
/* Don't interpret addr as a hint: place the mapping at exactly
|
||||
that address. */
|
||||
MMAP_MAP_FIXED = 2
|
||||
};
|
||||
|
||||
// Try reserving an aligned memory space.
|
||||
// Returns pointer to allocated space on success, 0 on failure.
|
||||
static void* os_mmap_aligned(void* addr,
|
||||
size_t requested_length,
|
||||
int prot,
|
||||
int flags,
|
||||
size_t alignment,
|
||||
size_t alignment_offset);
|
||||
// Unreserve the memory space
|
||||
static void os_munmap(void* addr, size_t size);
|
||||
// Allocates and sets the permissions on the previously reserved memory space
|
||||
// Returns 0 on success, non zero on failure.
|
||||
static int os_mmap_commit(void* curr_heap_end_pointer,
|
||||
size_t expanded_size,
|
||||
int prot);
|
||||
|
||||
wasm_rt_memory_t* w2c_env_memory(struct w2c_env* instance)
|
||||
{
|
||||
return instance->sandbox_memory_info;
|
||||
}
|
||||
|
||||
wasm_rt_funcref_table_t* w2c_env_0x5F_indirect_function_table(
|
||||
struct w2c_env* instance)
|
||||
{
|
||||
return instance->sandbox_callback_table;
|
||||
}
|
||||
|
||||
#define WASM_PAGE_SIZE 65536
|
||||
#define RLBOX_FOUR_GIG 0x100000000ull
|
||||
|
||||
#if UINTPTR_MAX == 0xffffffffffffffff
|
||||
// Guard page of 4GiB
|
||||
# define WASM_HEAP_GUARD_PAGE_SIZE 0x100000000ull
|
||||
// Heap aligned to 4GB
|
||||
# define WASM_HEAP_ALIGNMENT 0x100000000ull
|
||||
// By default max heap is 4GB
|
||||
# define WASM_HEAP_DEFAULT_MAX_PAGES 65536
|
||||
#elif UINTPTR_MAX == 0xffffffff
|
||||
// No guard pages
|
||||
# define WASM_HEAP_GUARD_PAGE_SIZE 0
|
||||
// Unaligned heap
|
||||
# define WASM_HEAP_ALIGNMENT 0
|
||||
// Default max heap is 16MB
|
||||
# define WASM_HEAP_DEFAULT_MAX_PAGES 256
|
||||
#else
|
||||
# error "Unknown pointer size"
|
||||
#endif
|
||||
|
||||
static uint64_t compute_heap_reserve_space(uint32_t chosen_max_pages)
|
||||
{
|
||||
const uint64_t heap_reserve_size =
|
||||
((uint64_t)chosen_max_pages) * WASM_PAGE_SIZE + WASM_HEAP_GUARD_PAGE_SIZE;
|
||||
return heap_reserve_size;
|
||||
}
|
||||
|
||||
w2c_mem_capacity get_valid_wasm2c_memory_capacity(uint64_t min_capacity,
|
||||
bool is_mem_32)
|
||||
{
|
||||
const w2c_mem_capacity err_val = { false /* is_valid */,
|
||||
false /* is_mem_32 */,
|
||||
0 /* max_pages */,
|
||||
0 /* max_size */ };
|
||||
|
||||
// We do not handle memory 64
|
||||
if (!is_mem_32) {
|
||||
return err_val;
|
||||
}
|
||||
|
||||
const uint64_t default_capacity =
|
||||
((uint64_t)WASM_HEAP_DEFAULT_MAX_PAGES) * WASM_PAGE_SIZE;
|
||||
|
||||
if (min_capacity <= default_capacity) {
|
||||
// Handle 0 case and small values
|
||||
const w2c_mem_capacity ret = { true /* is_valid */,
|
||||
true /* is_mem_32 */,
|
||||
WASM_HEAP_DEFAULT_MAX_PAGES /* max_pages */,
|
||||
default_capacity /* max_size */ };
|
||||
return ret;
|
||||
} else if (min_capacity > UINT32_MAX) {
|
||||
// Handle out of range values
|
||||
return err_val;
|
||||
}
|
||||
|
||||
const uint64_t page_size_minus_1 = WASM_PAGE_SIZE - 1;
|
||||
// Get number of pages greater than min_capacity
|
||||
const uint64_t capacity_pages = ((min_capacity - 1) / page_size_minus_1) + 1;
|
||||
|
||||
const w2c_mem_capacity ret = { true /* is_valid */,
|
||||
true /* is_mem_32 */,
|
||||
capacity_pages /* max_pages */,
|
||||
capacity_pages *
|
||||
WASM_PAGE_SIZE /* max_size */ };
|
||||
return ret;
|
||||
}
|
||||
|
||||
wasm_rt_memory_t create_wasm2c_memory(uint32_t initial_pages,
|
||||
const w2c_mem_capacity* custom_capacity)
|
||||
{
|
||||
|
||||
if (custom_capacity && !custom_capacity->is_valid) {
|
||||
wasm_rt_memory_t ret = { 0 };
|
||||
return ret;
|
||||
}
|
||||
|
||||
const uint32_t byte_length = initial_pages * WASM_PAGE_SIZE;
|
||||
const uint64_t chosen_max_pages =
|
||||
custom_capacity ? custom_capacity->max_pages : WASM_HEAP_DEFAULT_MAX_PAGES;
|
||||
const uint64_t heap_reserve_size =
|
||||
compute_heap_reserve_space(chosen_max_pages);
|
||||
|
||||
uint8_t* data = 0;
|
||||
const uint64_t retries = 10;
|
||||
for (uint64_t i = 0; i < retries; i++) {
|
||||
data = (uint8_t*)os_mmap_aligned(0,
|
||||
heap_reserve_size,
|
||||
MMAP_PROT_NONE,
|
||||
MMAP_MAP_NONE,
|
||||
WASM_HEAP_ALIGNMENT,
|
||||
0 /* alignment_offset */);
|
||||
if (data) {
|
||||
int ret =
|
||||
os_mmap_commit(data, byte_length, MMAP_PROT_READ | MMAP_PROT_WRITE);
|
||||
if (ret != 0) {
|
||||
// failed to set permissions
|
||||
os_munmap(data, heap_reserve_size);
|
||||
data = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
wasm_rt_memory_t ret;
|
||||
ret.data = data;
|
||||
ret.max_pages = chosen_max_pages;
|
||||
ret.pages = initial_pages;
|
||||
ret.size = byte_length;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void destroy_wasm2c_memory(wasm_rt_memory_t* memory)
|
||||
{
|
||||
if (memory->data != 0) {
|
||||
const uint64_t heap_reserve_size =
|
||||
compute_heap_reserve_space(memory->max_pages);
|
||||
os_munmap(memory->data, heap_reserve_size);
|
||||
memory->data = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#undef WASM_HEAP_DEFAULT_MAX_PAGES
|
||||
#undef WASM_HEAP_ALIGNMENT
|
||||
#undef WASM_HEAP_GUARD_PAGE_SIZE
|
||||
#undef RLBOX_FOUR_GIG
|
||||
#undef WASM_PAGE_SIZE
|
||||
|
||||
// Based on
|
||||
// https://web.archive.org/web/20191012035921/http://nadeausoftware.com/articles/2012/01/c_c_tip_how_use_compiler_predefined_macros_detect_operating_system#BSD
|
||||
// Check for windows (non cygwin) environment
|
||||
#if defined(_WIN32)
|
||||
|
||||
# include <windows.h>
|
||||
|
||||
static size_t os_getpagesize()
|
||||
{
|
||||
SYSTEM_INFO S;
|
||||
GetNativeSystemInfo(&S);
|
||||
return S.dwPageSize;
|
||||
}
|
||||
|
||||
static void* win_mmap(void* hint,
|
||||
size_t size,
|
||||
int prot,
|
||||
int flags,
|
||||
DWORD alloc_flag)
|
||||
{
|
||||
DWORD flProtect = PAGE_NOACCESS;
|
||||
size_t request_size, page_size;
|
||||
void* addr;
|
||||
|
||||
page_size = os_getpagesize();
|
||||
request_size = (size + page_size - 1) & ~(page_size - 1);
|
||||
|
||||
if (request_size < size)
|
||||
/* integer overflow */
|
||||
return NULL;
|
||||
|
||||
if (request_size == 0)
|
||||
request_size = page_size;
|
||||
|
||||
if (prot & MMAP_PROT_EXEC) {
|
||||
if (prot & MMAP_PROT_WRITE)
|
||||
flProtect = PAGE_EXECUTE_READWRITE;
|
||||
else
|
||||
flProtect = PAGE_EXECUTE_READ;
|
||||
} else if (prot & MMAP_PROT_WRITE)
|
||||
flProtect = PAGE_READWRITE;
|
||||
else if (prot & MMAP_PROT_READ)
|
||||
flProtect = PAGE_READONLY;
|
||||
|
||||
addr = VirtualAlloc((LPVOID)hint, request_size, alloc_flag, flProtect);
|
||||
return addr;
|
||||
}
|
||||
|
||||
static void* os_mmap_aligned(void* addr,
|
||||
size_t requested_length,
|
||||
int prot,
|
||||
int flags,
|
||||
size_t alignment,
|
||||
size_t alignment_offset)
|
||||
{
|
||||
size_t padded_length = requested_length + alignment + alignment_offset;
|
||||
uintptr_t unaligned =
|
||||
(uintptr_t)win_mmap(addr, padded_length, prot, flags, MEM_RESERVE);
|
||||
|
||||
if (!unaligned) {
|
||||
return (void*)unaligned;
|
||||
}
|
||||
|
||||
// Round up the next address that has addr % alignment = 0
|
||||
const size_t alignment_corrected = alignment == 0 ? 1 : alignment;
|
||||
uintptr_t aligned_nonoffset =
|
||||
(unaligned + (alignment_corrected - 1)) & ~(alignment_corrected - 1);
|
||||
|
||||
// Currently offset 0 is aligned according to alignment
|
||||
// Alignment needs to be enforced at the given offset
|
||||
uintptr_t aligned = 0;
|
||||
if ((aligned_nonoffset - alignment_offset) >= unaligned) {
|
||||
aligned = aligned_nonoffset - alignment_offset;
|
||||
} else {
|
||||
aligned = aligned_nonoffset - alignment_offset + alignment;
|
||||
}
|
||||
|
||||
if (aligned == unaligned && padded_length == requested_length) {
|
||||
return (void*)aligned;
|
||||
}
|
||||
|
||||
// Sanity check
|
||||
if (aligned < unaligned ||
|
||||
(aligned + (requested_length - 1)) > (unaligned + (padded_length - 1)) ||
|
||||
(aligned + alignment_offset) % alignment_corrected != 0) {
|
||||
os_munmap((void*)unaligned, padded_length);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// windows does not support partial unmapping, so unmap and remap
|
||||
os_munmap((void*)unaligned, padded_length);
|
||||
aligned = (uintptr_t)win_mmap(
|
||||
(void*)aligned, requested_length, prot, flags, MEM_RESERVE);
|
||||
return (void*)aligned;
|
||||
}
|
||||
|
||||
static void os_munmap(void* addr, size_t size)
|
||||
{
|
||||
DWORD alloc_flag = MEM_RELEASE;
|
||||
if (addr) {
|
||||
if (VirtualFree(addr, 0, alloc_flag) == 0) {
|
||||
size_t page_size = os_getpagesize();
|
||||
size_t request_size = (size + page_size - 1) & ~(page_size - 1);
|
||||
int64_t curr_err = errno;
|
||||
printf("os_munmap error addr:%p, size:0x%zx, errno:%" PRId64 "\n",
|
||||
addr,
|
||||
request_size,
|
||||
curr_err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int os_mmap_commit(void* curr_heap_end_pointer,
|
||||
size_t expanded_size,
|
||||
int prot)
|
||||
{
|
||||
uintptr_t addr = (uintptr_t)win_mmap(
|
||||
curr_heap_end_pointer, expanded_size, prot, MMAP_MAP_NONE, MEM_COMMIT);
|
||||
int ret = addr ? 0 : -1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#elif !defined(_WIN32) && (defined(__unix__) || defined(__unix) || \
|
||||
(defined(__APPLE__) && defined(__MACH__)))
|
||||
|
||||
# include <sys/mman.h>
|
||||
# include <unistd.h>
|
||||
|
||||
static size_t os_getpagesize()
|
||||
{
|
||||
return getpagesize();
|
||||
}
|
||||
|
||||
static void* os_mmap(void* hint, size_t size, int prot, int flags)
|
||||
{
|
||||
int map_prot = PROT_NONE;
|
||||
int map_flags = MAP_ANONYMOUS | MAP_PRIVATE;
|
||||
uint64_t request_size, page_size;
|
||||
void* addr;
|
||||
|
||||
page_size = (uint64_t)os_getpagesize();
|
||||
request_size = (size + page_size - 1) & ~(page_size - 1);
|
||||
|
||||
if ((size_t)request_size < size)
|
||||
/* integer overflow */
|
||||
return NULL;
|
||||
|
||||
if (request_size > 16 * (uint64_t)UINT32_MAX)
|
||||
/* At most 16 G is allowed */
|
||||
return NULL;
|
||||
|
||||
if (prot & MMAP_PROT_READ)
|
||||
map_prot |= PROT_READ;
|
||||
|
||||
if (prot & MMAP_PROT_WRITE)
|
||||
map_prot |= PROT_WRITE;
|
||||
|
||||
if (prot & MMAP_PROT_EXEC)
|
||||
map_prot |= PROT_EXEC;
|
||||
|
||||
# if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)
|
||||
# ifndef __APPLE__
|
||||
if (flags & MMAP_MAP_32BIT)
|
||||
map_flags |= MAP_32BIT;
|
||||
# endif
|
||||
# endif
|
||||
|
||||
if (flags & MMAP_MAP_FIXED)
|
||||
map_flags |= MAP_FIXED;
|
||||
|
||||
addr = mmap(hint, request_size, map_prot, map_flags, -1, 0);
|
||||
|
||||
if (addr == MAP_FAILED)
|
||||
return NULL;
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
static void* os_mmap_aligned(void* addr,
|
||||
size_t requested_length,
|
||||
int prot,
|
||||
int flags,
|
||||
size_t alignment,
|
||||
size_t alignment_offset)
|
||||
{
|
||||
size_t padded_length = requested_length + alignment + alignment_offset;
|
||||
uintptr_t unaligned = (uintptr_t)os_mmap(addr, padded_length, prot, flags);
|
||||
|
||||
if (!unaligned) {
|
||||
return (void*)unaligned;
|
||||
}
|
||||
|
||||
// Round up the next address that has addr % alignment = 0
|
||||
const size_t alignment_corrected = alignment == 0 ? 1 : alignment;
|
||||
uintptr_t aligned_nonoffset =
|
||||
(unaligned + (alignment_corrected - 1)) & ~(alignment_corrected - 1);
|
||||
|
||||
// Currently offset 0 is aligned according to alignment
|
||||
// Alignment needs to be enforced at the given offset
|
||||
uintptr_t aligned = 0;
|
||||
if ((aligned_nonoffset - alignment_offset) >= unaligned) {
|
||||
aligned = aligned_nonoffset - alignment_offset;
|
||||
} else {
|
||||
aligned = aligned_nonoffset - alignment_offset + alignment;
|
||||
}
|
||||
|
||||
// Sanity check
|
||||
if (aligned < unaligned ||
|
||||
(aligned + (requested_length - 1)) > (unaligned + (padded_length - 1)) ||
|
||||
(aligned + alignment_offset) % alignment_corrected != 0) {
|
||||
os_munmap((void*)unaligned, padded_length);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
{
|
||||
size_t unused_front = aligned - unaligned;
|
||||
if (unused_front != 0) {
|
||||
os_munmap((void*)unaligned, unused_front);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
size_t unused_back =
|
||||
(unaligned + (padded_length - 1)) - (aligned + (requested_length - 1));
|
||||
if (unused_back != 0) {
|
||||
os_munmap((void*)(aligned + requested_length), unused_back);
|
||||
}
|
||||
}
|
||||
|
||||
return (void*)aligned;
|
||||
}
|
||||
|
||||
static void os_munmap(void* addr, size_t size)
|
||||
{
|
||||
uint64_t page_size = (uint64_t)os_getpagesize();
|
||||
uint64_t request_size = (size + page_size - 1) & ~(page_size - 1);
|
||||
|
||||
if (addr) {
|
||||
if (munmap(addr, request_size)) {
|
||||
printf("os_munmap error addr:%p, size:0x%" PRIx64 ", errno:%d\n",
|
||||
addr,
|
||||
request_size,
|
||||
errno);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int os_mmap_commit(void* addr, size_t size, int prot)
|
||||
{
|
||||
int map_prot = PROT_NONE;
|
||||
uint64_t page_size = (uint64_t)os_getpagesize();
|
||||
uint64_t request_size = (size + page_size - 1) & ~(page_size - 1);
|
||||
|
||||
if (!addr)
|
||||
return 0;
|
||||
|
||||
if (prot & MMAP_PROT_READ)
|
||||
map_prot |= PROT_READ;
|
||||
|
||||
if (prot & MMAP_PROT_WRITE)
|
||||
map_prot |= PROT_WRITE;
|
||||
|
||||
if (prot & MMAP_PROT_EXEC)
|
||||
map_prot |= PROT_EXEC;
|
||||
|
||||
return mprotect(addr, request_size, map_prot);
|
||||
}
|
||||
|
||||
#else
|
||||
# error "Unknown OS"
|
||||
#endif
|
799
third_party/rlbox_wasm2c_sandbox/src/wasm2c_rt_minwasi.c
vendored
Normal file
799
third_party/rlbox_wasm2c_sandbox/src/wasm2c_rt_minwasi.c
vendored
Normal file
@ -0,0 +1,799 @@
|
||||
/* A minimum wasi implementation supporting only stdin, stdout, stderr, argv
|
||||
* (upto 1000 args), env (upto 1000 env), and clock functions. */
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__) && defined(__MACH__)
|
||||
// Macs priors to OSX 10.12 don't have the clock functions. So we will use mac
|
||||
// specific options
|
||||
# include <mach/mach_time.h>
|
||||
# include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#include "wasm-rt.h"
|
||||
#include "wasm2c_rt_minwasi.h"
|
||||
|
||||
#ifndef WASM_RT_CORE_TYPES_DEFINED
|
||||
# define WASM_RT_CORE_TYPES_DEFINED
|
||||
typedef uint8_t u8;
|
||||
typedef int8_t s8;
|
||||
typedef uint16_t u16;
|
||||
typedef int16_t s16;
|
||||
typedef uint32_t u32;
|
||||
typedef int32_t s32;
|
||||
typedef uint64_t u64;
|
||||
typedef int64_t s64;
|
||||
typedef float f32;
|
||||
typedef double f64;
|
||||
#endif
|
||||
|
||||
#ifndef UNLIKELY
|
||||
# if defined(__GNUC__)
|
||||
# define UNLIKELY(x) __builtin_expect(!!(x), 0)
|
||||
# define LIKELY(x) __builtin_expect(!!(x), 1)
|
||||
# else
|
||||
# define UNLIKELY(x) (x)
|
||||
# define LIKELY(x) (x)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define TRAP(x) wasm_rt_trap(WASM_RT_TRAP_##x)
|
||||
|
||||
#define WASI_MEMACCESS(mem, a) ((void*)&(mem->data[a]))
|
||||
|
||||
#define WASI_MEMCHECK_SIZE(mem, a, sz) \
|
||||
if (UNLIKELY(((u64)(a)) + sz > mem->size)) \
|
||||
TRAP(OOB)
|
||||
|
||||
#define WASI_CHECK_COPY(mem, a, sz, src) \
|
||||
do { \
|
||||
WASI_MEMCHECK_SIZE(mem, a, sz); \
|
||||
memcpy(WASI_MEMACCESS(mem, a), src, sz); \
|
||||
} while (0)
|
||||
|
||||
#define WASI_MEMCHECK(mem, a, t) WASI_MEMCHECK_SIZE(mem, a, sizeof(t))
|
||||
|
||||
#define DEFINE_WASI_LOAD(name, t1, t2, t3) \
|
||||
static inline t3 name(wasm_rt_memory_t* mem, u64 addr) \
|
||||
{ \
|
||||
WASI_MEMCHECK(mem, addr, t1); \
|
||||
t1 result; \
|
||||
memcpy(&result, WASI_MEMACCESS(mem, addr), sizeof(t1)); \
|
||||
return (t3)(t2)result; \
|
||||
}
|
||||
|
||||
#define DEFINE_WASI_STORE(name, t1, t2) \
|
||||
static inline void name(wasm_rt_memory_t* mem, u64 addr, t2 value) \
|
||||
{ \
|
||||
WASI_MEMCHECK(mem, addr, t1); \
|
||||
t1 wrapped = (t1)value; \
|
||||
memcpy(WASI_MEMACCESS(mem, addr), &wrapped, sizeof(t1)); \
|
||||
}
|
||||
|
||||
DEFINE_WASI_LOAD(wasm_i32_load, u32, u32, u32);
|
||||
DEFINE_WASI_STORE(wasm_i32_store, u32, u32);
|
||||
DEFINE_WASI_STORE(wasm_i64_store, u64, u64);
|
||||
|
||||
static bool safe_add_u32(u32* ret, u32 a, u32 b)
|
||||
{
|
||||
if (UINT32_MAX - a < b) {
|
||||
*ret = 0;
|
||||
return false;
|
||||
}
|
||||
*ret = a + b;
|
||||
return true;
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
|
||||
////////////// Supported WASI APIs
|
||||
//
|
||||
// Clock operations
|
||||
// ----------------
|
||||
// errno_t clock_res_get(void* ctx, clockid_t clock_id, timestamp_t* resolution);
|
||||
// errno_t clock_time_get(void* ctx, clockid_t clock_id, timestamp_t precision, timestamp_t* time);
|
||||
//
|
||||
// File operations
|
||||
// ----------------
|
||||
// Only the default descriptors of STDIN, STDOUT, STDERR are allowed by the
|
||||
// runtime.
|
||||
//
|
||||
// errno_t fd_prestat_get(void* ctx, fd_t fd, prestat_t* buf);
|
||||
// errno_t fd_read(void* ctx, fd_t fd, const iovec_t* iovs, size_t iovs_len, size_t* nread);
|
||||
// errno_t fd_write(void* ctx, fd_t fd, const ciovec_t* iovs, size_t iovs_len, size_t* nwritten);
|
||||
|
||||
////////////// Partially supported WASI APIs
|
||||
//
|
||||
// App environment operations
|
||||
// --------------------------
|
||||
// These APIs work but return an empty buffer
|
||||
//
|
||||
// errno_t args_get(void* ctx, char** argv, char* argv_buf);
|
||||
// errno_t args_sizes_get(void* ctx, size_t* argc, size_t* argv_buf_size);
|
||||
// errno_t environ_get(void* ctx, char** environment, char* environ_buf);
|
||||
// errno_t environ_sizes_get(void* ctx, size_t* environ_count, size_t* environ_buf_size);
|
||||
//
|
||||
// Proc exit operation
|
||||
// -------------------
|
||||
// This is a no-op here in this runtime as the focus is on library
|
||||
// sandboxing
|
||||
//
|
||||
// errno_t proc_exit(void* ctx, exitcode_t rval);
|
||||
|
||||
////////////// Unsupported WASI APIs
|
||||
// errno_t fd_advise(void* ctx, fd_t fd, filesize_t offset, filesize_t len, advice_t advice);
|
||||
// errno_t fd_allocate(void* ctx, fd_t fd, filesize_t offset, filesize_t len);
|
||||
// errno_t fd_close(void* ctx, fd_t fd);
|
||||
// errno_t fd_datasync(void* ctx, fd_t fd);
|
||||
// errno_t fd_fdstat_get(void* ctx, fd_t fd, fdstat_t* buf);
|
||||
// errno_t fd_fdstat_set_flags(void* ctx, fd_t fd, fdflags_t flags);
|
||||
// errno_t fd_fdstat_set_rights(void* ctx, fd_t fd, rights_t fs_rights_base, rights_t fs_rights_inheriting);
|
||||
// errno_t fd_filestat_get(void* ctx, fd_t fd, filestat_t* buf);
|
||||
// errno_t fd_filestat_set_size(void* ctx, fd_t fd, filesize_t st_size);
|
||||
// errno_t fd_filestat_set_times(void* ctx, fd_t fd, timestamp_t st_atim, timestamp_t st_mtim, fstflags_t fst_flags);
|
||||
// errno_t fd_pread(void* ctx, fd_t fd, const iovec_t* iovs, size_t iovs_len, filesize_t offset, size_t* nread);
|
||||
// errno_t fd_prestat_dir_name(void* ctx, fd_t fd, char* path, size_t path_len);
|
||||
// errno_t fd_pwrite(void* ctx, fd_t fd, const ciovec_t* iovs, size_t iovs_len, filesize_t offset, size_t* nwritten);
|
||||
// errno_t fd_readdir(void* ctx, fd_t fd, void* buf, size_t buf_len, dircookie_t cookie, size_t* bufused);
|
||||
// errno_t fd_renumber(void* ctx, fd_t from, fd_t to);
|
||||
// errno_t fd_seek(void* ctx, fd_t fd, filedelta_t offset, whence_t whence, filesize_t* newoffset);
|
||||
// errno_t fd_sync(void* ctx, fd_t fd);
|
||||
// errno_t fd_tell(void* ctx, fd_t fd, filesize_t* offset);
|
||||
// errno_t path_create_directory(void* ctx, fd_t fd, const char* path, size_t path_len);
|
||||
// errno_t path_filestat_get(void* ctx, fd_t fd, lookupflags_t flags, const char* path, size_t path_len, filestat_t* buf);
|
||||
// errno_t path_filestat_set_times(void* ctx, fd_t fd, lookupflags_t flags, const char* path, size_t path_len, timestamp_t st_atim, timestamp_t st_mtim, fstflags_t fst_flags);
|
||||
// errno_t path_link(void* ctx, fd_t old_fd, lookupflags_t old_flags, const char* old_path, size_t old_path_len, fd_t new_fd, const char* new_path, size_t new_path_len);
|
||||
// errno_t path_open(void* ctx, fd_t dirfd, lookupflags_t dirflags, const char* path, size_t path_len, oflags_t o_flags, rights_t fs_rights_base, rights_t fs_rights_inheriting, fdflags_t fs_flags, fd_t* fd);
|
||||
// errno_t path_readlink(void* ctx, fd_t fd, const char* path, size_t path_len, char* buf, size_t buf_len, size_t* bufused);
|
||||
// errno_t path_remove_directory(void* ctx, fd_t fd, const char* path, size_t path_len);
|
||||
// errno_t path_rename(void* ctx, fd_t old_fd, const char* old_path, size_t old_path_len, fd_t new_fd, const char* new_path, size_t new_path_len);
|
||||
// errno_t path_symlink(void* ctx, const char* old_path, size_t old_path_len, fd_t fd, const char* new_path, size_t new_path_len);
|
||||
// errno_t path_unlink_file(void* ctx, fd_t fd, const char* path, size_t path_len);
|
||||
// errno_t poll_oneoff(void* ctx, const subscription_t* in, event_t* out, size_t nsubscriptions, size_t* nevents);
|
||||
// errno_t proc_raise(void* ctx, signal_t sig);
|
||||
// errno_t random_get(void* ctx, void* buf, size_t buf_len);
|
||||
// errno_t sched_yield(t* uvwasi);
|
||||
// errno_t sock_accept(void* ctx, fd_t sock, flags_t fdflags, fd* fd);
|
||||
// errno_t sock_recv(void* ctx, fd_t sock, const iovec_t* ri_data, size_t ri_data_len, riflags_t ri_flags, size_t* ro_datalen, roflags_t* ro_flags);
|
||||
// errno_t sock_send(void* ctx, fd_t sock, const ciovec_t* si_data, size_t si_data_len, siflags_t si_flags, size_t* so_datalen);
|
||||
// errno_t sock_shutdown(void* ctx, fd_t sock, sdflags_t how);
|
||||
|
||||
// clang-format on
|
||||
|
||||
// Success
|
||||
#define WASI_SUCCESS 0
|
||||
// Bad file descriptor.
|
||||
#define WASI_BADF_ERROR 8
|
||||
// Invalid argument
|
||||
#define WASI_INVAL_ERROR 28
|
||||
// Operation not permitted.
|
||||
#define WASI_PERM_ERROR 63
|
||||
// Syscall not implemented
|
||||
#define WASI_NOSYS_ERROR 53
|
||||
|
||||
#define WASI_RET_ERR_ON_FAIL(exp) \
|
||||
if (!(exp)) { \
|
||||
return WASI_INVAL_ERROR; \
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Clock operations
|
||||
/////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
LARGE_INTEGER counts_per_sec; /* conversion factor */
|
||||
} wasi_win_clock_info_t;
|
||||
|
||||
static wasi_win_clock_info_t g_wasi_win_clock_info;
|
||||
static int g_os_data_initialized = 0;
|
||||
|
||||
static bool os_clock_init()
|
||||
{
|
||||
// From here:
|
||||
// https://stackoverflow.com/questions/5404277/porting-clock-gettime-to-windows/38212960#38212960
|
||||
if (QueryPerformanceFrequency(&g_wasi_win_clock_info.counts_per_sec) == 0) {
|
||||
return false;
|
||||
}
|
||||
g_os_data_initialized = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool os_clock_init_instance(void** clock_data_pointer)
|
||||
{
|
||||
if (!g_os_data_initialized) {
|
||||
os_clock_init();
|
||||
}
|
||||
|
||||
wasi_win_clock_info_t* alloc =
|
||||
(wasi_win_clock_info_t*)malloc(sizeof(wasi_win_clock_info_t));
|
||||
if (!alloc) {
|
||||
return false;
|
||||
}
|
||||
memcpy(alloc, &g_wasi_win_clock_info, sizeof(wasi_win_clock_info_t));
|
||||
*clock_data_pointer = alloc;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void os_clock_cleanup_instance(void** clock_data_pointer)
|
||||
{
|
||||
if (*clock_data_pointer == 0) {
|
||||
free(*clock_data_pointer);
|
||||
*clock_data_pointer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int os_clock_gettime(void* clock_data,
|
||||
int clock_id,
|
||||
struct timespec* out_struct)
|
||||
{
|
||||
wasi_win_clock_info_t* alloc = (wasi_win_clock_info_t*)clock_data;
|
||||
|
||||
LARGE_INTEGER count;
|
||||
(void)clock_id;
|
||||
|
||||
if (alloc->counts_per_sec.QuadPart <= 0 ||
|
||||
QueryPerformanceCounter(&count) == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
# define BILLION 1000000000LL
|
||||
out_struct->tv_sec = count.QuadPart / alloc->counts_per_sec.QuadPart;
|
||||
out_struct->tv_nsec =
|
||||
((count.QuadPart % alloc->counts_per_sec.QuadPart) * BILLION) /
|
||||
alloc->counts_per_sec.QuadPart;
|
||||
# undef BILLION
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int os_clock_getres(void* clock_data,
|
||||
int clock_id,
|
||||
struct timespec* out_struct)
|
||||
{
|
||||
(void)clock_id;
|
||||
out_struct->tv_sec = 0;
|
||||
out_struct->tv_nsec = 1000;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#elif defined(__APPLE__) && defined(__MACH__)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
mach_timebase_info_data_t timebase; /* numer = 0, denom = 0 */
|
||||
struct timespec inittime; /* nanoseconds since 1-Jan-1970 to init() */
|
||||
uint64_t initclock; /* ticks since boot to init() */
|
||||
} wasi_mac_clock_info_t;
|
||||
|
||||
static wasi_mac_clock_info_t g_wasi_mac_clock_info;
|
||||
static int g_os_data_initialized = 0;
|
||||
|
||||
static bool os_clock_init()
|
||||
{
|
||||
// From here:
|
||||
// https://stackoverflow.com/questions/5167269/clock-gettime-alternative-in-mac-os-x/21352348#21352348
|
||||
if (mach_timebase_info(&g_wasi_mac_clock_info.timebase) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// microseconds since 1 Jan 1970
|
||||
struct timeval micro;
|
||||
if (gettimeofday(µ, NULL) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
g_wasi_mac_clock_info.initclock = mach_absolute_time();
|
||||
|
||||
g_wasi_mac_clock_info.inittime.tv_sec = micro.tv_sec;
|
||||
g_wasi_mac_clock_info.inittime.tv_nsec = micro.tv_usec * 1000;
|
||||
|
||||
g_os_data_initialized = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool os_clock_init_instance(void** clock_data_pointer)
|
||||
{
|
||||
if (!g_os_data_initialized) {
|
||||
os_clock_init();
|
||||
}
|
||||
|
||||
wasi_mac_clock_info_t* alloc =
|
||||
(wasi_mac_clock_info_t*)malloc(sizeof(wasi_mac_clock_info_t));
|
||||
if (!alloc) {
|
||||
return false;
|
||||
}
|
||||
memcpy(alloc, &g_wasi_mac_clock_info, sizeof(wasi_mac_clock_info_t));
|
||||
*clock_data_pointer = alloc;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void os_clock_cleanup_instance(void** clock_data_pointer)
|
||||
{
|
||||
if (*clock_data_pointer == 0) {
|
||||
free(*clock_data_pointer);
|
||||
*clock_data_pointer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int os_clock_gettime(void* clock_data,
|
||||
int clock_id,
|
||||
struct timespec* out_struct)
|
||||
{
|
||||
int ret = 0;
|
||||
wasi_mac_clock_info_t* alloc = (wasi_mac_clock_info_t*)clock_data;
|
||||
|
||||
// From here:
|
||||
// https://stackoverflow.com/questions/5167269/clock-gettime-alternative-in-mac-os-x/21352348#21352348
|
||||
|
||||
(void)clock_id;
|
||||
// ticks since init
|
||||
uint64_t clock = mach_absolute_time() - alloc->initclock;
|
||||
// nanoseconds since init
|
||||
uint64_t nano = clock * (uint64_t)(alloc->timebase.numer) /
|
||||
(uint64_t)(alloc->timebase.denom);
|
||||
*out_struct = alloc->inittime;
|
||||
|
||||
# define BILLION 1000000000L
|
||||
out_struct->tv_sec += nano / BILLION;
|
||||
out_struct->tv_nsec += nano % BILLION;
|
||||
// normalize
|
||||
out_struct->tv_sec += out_struct->tv_nsec / BILLION;
|
||||
out_struct->tv_nsec = out_struct->tv_nsec % BILLION;
|
||||
# undef BILLION
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int os_clock_getres(void* clock_data,
|
||||
int clock_id,
|
||||
struct timespec* out_struct)
|
||||
{
|
||||
int ret = 0;
|
||||
(void)clock_id;
|
||||
out_struct->tv_sec = 0;
|
||||
out_struct->tv_nsec = 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static bool os_clock_init()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool os_clock_init_instance(void** clock_data_pointer)
|
||||
{
|
||||
(void)clock_data_pointer;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void os_clock_cleanup_instance(void** clock_data_pointer)
|
||||
{
|
||||
(void)clock_data_pointer;
|
||||
}
|
||||
|
||||
static int os_clock_gettime(void* clock_data,
|
||||
int clock_id,
|
||||
struct timespec* out_struct)
|
||||
{
|
||||
(void)clock_data;
|
||||
int ret = clock_gettime(clock_id, out_struct);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int os_clock_getres(void* clock_data,
|
||||
int clock_id,
|
||||
struct timespec* out_struct)
|
||||
{
|
||||
(void)clock_data;
|
||||
int ret = clock_getres(clock_id, out_struct);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#define WASM_CLOCK_REALTIME 0
|
||||
#define WASM_CLOCK_MONOTONIC 1
|
||||
#define WASM_CLOCK_PROCESS_CPUTIME 2
|
||||
#define WASM_CLOCK_THREAD_CPUTIME_ID 3
|
||||
|
||||
static int check_clock(u32 clock_id)
|
||||
{
|
||||
return clock_id == WASM_CLOCK_REALTIME || clock_id == WASM_CLOCK_MONOTONIC ||
|
||||
clock_id == WASM_CLOCK_PROCESS_CPUTIME ||
|
||||
clock_id == WASM_CLOCK_THREAD_CPUTIME_ID;
|
||||
}
|
||||
|
||||
// out is a pointer to a u64 timestamp in nanoseconds
|
||||
// https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#-timestamp-u64
|
||||
u32 w2c_wasi__snapshot__preview1_clock_time_get(
|
||||
w2c_wasi__snapshot__preview1* wasi_data,
|
||||
u32 clock_id,
|
||||
u64 precision,
|
||||
u32 out)
|
||||
{
|
||||
if (!check_clock(clock_id)) {
|
||||
return WASI_INVAL_ERROR;
|
||||
}
|
||||
|
||||
struct timespec out_struct;
|
||||
int ret = os_clock_gettime(wasi_data->clock_data, clock_id, &out_struct);
|
||||
u64 result =
|
||||
((u64)out_struct.tv_sec) * 1000 * 1000 * 1000 + ((u64)out_struct.tv_nsec);
|
||||
wasm_i64_store(wasi_data->instance_memory, out, result);
|
||||
return ret;
|
||||
}
|
||||
|
||||
u32 w2c_wasi__snapshot__preview1_clock_res_get(
|
||||
w2c_wasi__snapshot__preview1* wasi_data,
|
||||
u32 clock_id,
|
||||
u32 out)
|
||||
{
|
||||
if (!check_clock(clock_id)) {
|
||||
return WASI_INVAL_ERROR;
|
||||
}
|
||||
|
||||
struct timespec out_struct;
|
||||
int ret = os_clock_getres(wasi_data->clock_data, clock_id, &out_struct);
|
||||
u64 result =
|
||||
((u64)out_struct.tv_sec) * 1000 * 1000 * 1000 + ((u64)out_struct.tv_nsec);
|
||||
wasm_i64_store(wasi_data->instance_memory, out, result);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
////////// File operations
|
||||
/////////////////////////////////////////////////////////////
|
||||
|
||||
// Only allow stdin (0), stdout (1), stderr(2)
|
||||
|
||||
#define WASM_STDIN 0
|
||||
#define WASM_STDOUT 1
|
||||
#define WASM_STDERR 2
|
||||
|
||||
u32 w2c_wasi__snapshot__preview1_fd_prestat_get(
|
||||
w2c_wasi__snapshot__preview1* wasi_data,
|
||||
u32 fd,
|
||||
u32 prestat)
|
||||
{
|
||||
if (fd == WASM_STDIN || fd == WASM_STDOUT || fd == WASM_STDERR) {
|
||||
return WASI_PERM_ERROR;
|
||||
}
|
||||
return WASI_BADF_ERROR;
|
||||
}
|
||||
|
||||
u32 w2c_wasi__snapshot__preview1_fd_write(
|
||||
w2c_wasi__snapshot__preview1* wasi_data,
|
||||
u32 fd,
|
||||
u32 iov,
|
||||
u32 iovcnt,
|
||||
u32 pnum)
|
||||
{
|
||||
if (fd != WASM_STDOUT && fd != WASM_STDERR) {
|
||||
return WASI_BADF_ERROR;
|
||||
}
|
||||
|
||||
u32 num = 0;
|
||||
for (u32 i = 0; i < iovcnt; i++) {
|
||||
u32 ptr = wasm_i32_load(wasi_data->instance_memory, iov + i * 8);
|
||||
u32 len = wasm_i32_load(wasi_data->instance_memory, iov + i * 8 + 4);
|
||||
|
||||
WASI_MEMCHECK_SIZE(wasi_data->instance_memory, ptr, len);
|
||||
|
||||
size_t result = fwrite(WASI_MEMACCESS(wasi_data->instance_memory, ptr),
|
||||
1 /* size */,
|
||||
len /* n */,
|
||||
fd == WASM_STDOUT ? stdout : stderr);
|
||||
|
||||
// Guaranteed by fwrite
|
||||
assert(result <= len);
|
||||
|
||||
WASI_RET_ERR_ON_FAIL(safe_add_u32(&num, num, (u32)result));
|
||||
|
||||
if (((u32)result) != len) {
|
||||
wasm_i32_store(wasi_data->instance_memory, pnum, num);
|
||||
return WASI_PERM_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
wasm_i32_store(wasi_data->instance_memory, pnum, num);
|
||||
return WASI_SUCCESS;
|
||||
}
|
||||
|
||||
u32 w2c_wasi__snapshot__preview1_fd_read(
|
||||
w2c_wasi__snapshot__preview1* wasi_data,
|
||||
u32 fd,
|
||||
u32 iov,
|
||||
u32 iovcnt,
|
||||
u32 pnum)
|
||||
{
|
||||
if (fd != WASM_STDIN) {
|
||||
return WASI_BADF_ERROR;
|
||||
}
|
||||
|
||||
u32 num = 0;
|
||||
for (u32 i = 0; i < iovcnt; i++) {
|
||||
u32 ptr = wasm_i32_load(wasi_data->instance_memory, iov + i * 8);
|
||||
u32 len = wasm_i32_load(wasi_data->instance_memory, iov + i * 8 + 4);
|
||||
|
||||
WASI_MEMCHECK_SIZE(wasi_data->instance_memory, ptr, len);
|
||||
size_t result = fread(WASI_MEMACCESS(wasi_data->instance_memory, ptr),
|
||||
1 /* size */,
|
||||
len /* n */,
|
||||
stdin);
|
||||
|
||||
// Guaranteed by fwrite
|
||||
assert(result <= len);
|
||||
|
||||
WASI_RET_ERR_ON_FAIL(safe_add_u32(&num, num, (u32)result));
|
||||
|
||||
if (((u32)result) != len) {
|
||||
break; // nothing more to read
|
||||
}
|
||||
}
|
||||
wasm_i32_store(wasi_data->instance_memory, pnum, num);
|
||||
return WASI_SUCCESS;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// App environment operations
|
||||
/////////////////////////////////////////////////////////////
|
||||
|
||||
#define ARGV_AND_ENV_LIMIT 1000
|
||||
|
||||
static u32 strings_sizes_get(wasm_rt_memory_t* instance_memory,
|
||||
const char* name,
|
||||
u32 p_str_count,
|
||||
u32 p_str_buff_size,
|
||||
u32 string_count,
|
||||
const char** strings)
|
||||
{
|
||||
u32 chosen_count = string_count;
|
||||
if (chosen_count > ARGV_AND_ENV_LIMIT) {
|
||||
chosen_count = ARGV_AND_ENV_LIMIT;
|
||||
printf("Truncated %s args to %d\n", name, ARGV_AND_ENV_LIMIT);
|
||||
}
|
||||
|
||||
u32 curr_buf_size = 0;
|
||||
for (u32 i = 0; i < chosen_count; i++) {
|
||||
size_t original_len = strlen(strings[i]);
|
||||
// len has to be at most u32 - 1
|
||||
WASI_RET_ERR_ON_FAIL(original_len < (size_t)UINT32_MAX);
|
||||
|
||||
u32 len = (u32)original_len;
|
||||
u32 len_plus_nullchar = len + 1;
|
||||
|
||||
WASI_RET_ERR_ON_FAIL(
|
||||
safe_add_u32(&curr_buf_size, curr_buf_size, len_plus_nullchar));
|
||||
}
|
||||
|
||||
wasm_i32_store(instance_memory, p_str_count, chosen_count);
|
||||
wasm_i32_store(instance_memory, p_str_buff_size, curr_buf_size);
|
||||
return WASI_SUCCESS;
|
||||
}
|
||||
|
||||
static u32 strings_get(wasm_rt_memory_t* instance_memory,
|
||||
const char* name,
|
||||
u32 p_str_arr,
|
||||
u32 p_str_buf,
|
||||
u32 string_count,
|
||||
const char** strings)
|
||||
{
|
||||
u32 chosen_count = string_count;
|
||||
if (chosen_count > ARGV_AND_ENV_LIMIT) {
|
||||
chosen_count = ARGV_AND_ENV_LIMIT;
|
||||
// Warning is already printed in get_size
|
||||
}
|
||||
|
||||
u32 curr_buf_loc = 0;
|
||||
|
||||
for (u32 i = 0; i < chosen_count; i++) {
|
||||
// Implement: p_str_arr[i] = p_str_buf[curr_buf_loc]
|
||||
u32 target_argv_i_ref;
|
||||
WASI_RET_ERR_ON_FAIL(safe_add_u32(&target_argv_i_ref, p_str_arr, i * 4));
|
||||
|
||||
u32 target_buf_curr_ref;
|
||||
WASI_RET_ERR_ON_FAIL(
|
||||
safe_add_u32(&target_buf_curr_ref, p_str_buf, curr_buf_loc));
|
||||
|
||||
wasm_i32_store(instance_memory, target_argv_i_ref, target_buf_curr_ref);
|
||||
|
||||
// Implement: strcpy(p_str_buf[curr_buf_loc], strings[i]);
|
||||
size_t original_len = strlen(strings[i]);
|
||||
// len has to be at most u32 - 1
|
||||
WASI_RET_ERR_ON_FAIL(original_len < (size_t)UINT32_MAX);
|
||||
|
||||
u32 len = (u32)original_len;
|
||||
u32 len_plus_nullchar = len + 1;
|
||||
|
||||
WASI_CHECK_COPY(
|
||||
instance_memory, target_buf_curr_ref, len_plus_nullchar, strings[i]);
|
||||
// Implement: curr_buf_loc += strlen(p_str_buf[curr_buf_loc])
|
||||
WASI_RET_ERR_ON_FAIL(
|
||||
safe_add_u32(&curr_buf_loc, curr_buf_loc, len_plus_nullchar));
|
||||
}
|
||||
return WASI_SUCCESS;
|
||||
}
|
||||
|
||||
u32 w2c_wasi__snapshot__preview1_args_sizes_get(
|
||||
w2c_wasi__snapshot__preview1* wasi_data,
|
||||
u32 p_argc,
|
||||
u32 p_argv_buf_size)
|
||||
{
|
||||
return strings_sizes_get(wasi_data->instance_memory,
|
||||
"main",
|
||||
p_argc,
|
||||
p_argv_buf_size,
|
||||
wasi_data->main_argc,
|
||||
wasi_data->main_argv);
|
||||
}
|
||||
|
||||
u32 w2c_wasi__snapshot__preview1_args_get(
|
||||
w2c_wasi__snapshot__preview1* wasi_data,
|
||||
u32 p_argv,
|
||||
u32 p_argv_buf)
|
||||
{
|
||||
return strings_get(wasi_data->instance_memory,
|
||||
"main",
|
||||
p_argv,
|
||||
p_argv_buf,
|
||||
wasi_data->main_argc,
|
||||
wasi_data->main_argv);
|
||||
}
|
||||
|
||||
u32 w2c_wasi__snapshot__preview1_environ_sizes_get(
|
||||
w2c_wasi__snapshot__preview1* wasi_data,
|
||||
u32 p_env_count,
|
||||
u32 p_env_buf_size)
|
||||
{
|
||||
return strings_sizes_get(wasi_data->instance_memory,
|
||||
"env",
|
||||
p_env_count,
|
||||
p_env_buf_size,
|
||||
wasi_data->env_count,
|
||||
wasi_data->env);
|
||||
}
|
||||
|
||||
u32 w2c_wasi__snapshot__preview1_environ_get(
|
||||
w2c_wasi__snapshot__preview1* wasi_data,
|
||||
u32 p_env,
|
||||
u32 p_env_buf)
|
||||
{
|
||||
return strings_get(wasi_data->instance_memory,
|
||||
"env",
|
||||
p_env,
|
||||
p_env_buf,
|
||||
wasi_data->env_count,
|
||||
wasi_data->env);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Proc exit operation
|
||||
/////////////////////////////////////////////////////////////
|
||||
|
||||
void w2c_wasi__snapshot__preview1_proc_exit(
|
||||
w2c_wasi__snapshot__preview1* wasi_data,
|
||||
u32 x)
|
||||
{
|
||||
#ifdef WASM2C_WASI_TRAP_ON_EXIT
|
||||
TRAP(WASI);
|
||||
#else
|
||||
exit(x);
|
||||
#endif
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
////////////// Unsupported WASI APIs
|
||||
/////////////////////////////////////////////////////////////
|
||||
|
||||
#define STUB_IMPORT_IMPL(ret, name, params) \
|
||||
ret name params { return WASI_NOSYS_ERROR; }
|
||||
|
||||
// clang-format off
|
||||
|
||||
STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_fd_advise,
|
||||
(w2c_wasi__snapshot__preview1* wasi_data, u32 a, u64 b, u64 c, u32 d));
|
||||
STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_fd_allocate,
|
||||
(w2c_wasi__snapshot__preview1* wasi_data, u32 a, u64 b, u64 c));
|
||||
STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_fd_close,
|
||||
(w2c_wasi__snapshot__preview1* wasi_data, u32 fd));
|
||||
STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_fd_datasync,
|
||||
(w2c_wasi__snapshot__preview1* wasi_data, u32 a));
|
||||
STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_fd_fdstat_get,
|
||||
(w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b));
|
||||
STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_fd_fdstat_set_flags,
|
||||
(w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b));
|
||||
STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_fd_fdstat_set_rights,
|
||||
(w2c_wasi__snapshot__preview1* wasi_data, u32 a, u64 b, u64 c));
|
||||
STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_fd_filestat_get,
|
||||
(w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b));
|
||||
STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_fd_filestat_set_size,
|
||||
(w2c_wasi__snapshot__preview1* wasi_data, u32 a, u64 b));
|
||||
STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_fd_filestat_set_times,
|
||||
(w2c_wasi__snapshot__preview1* wasi_data, u32 a, u64 b, u64 c, u32 d));
|
||||
STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_fd_pread,
|
||||
(w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b, u32 c, u64 d, u32 e));
|
||||
STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_fd_prestat_dir_name,
|
||||
(w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b, u32 c));
|
||||
STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_fd_pwrite,
|
||||
(w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b, u32 c, u64 d, u32 e));
|
||||
STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_fd_readdir,
|
||||
(w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b, u32 c, u64 d, u32 e));
|
||||
STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_fd_renumber,
|
||||
(w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b));
|
||||
STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_fd_seek,
|
||||
(w2c_wasi__snapshot__preview1* wasi_data, u32 fd, u64 offset, u32 whence, u32 new_offset));
|
||||
STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_fd_sync,
|
||||
(w2c_wasi__snapshot__preview1* wasi_data, u32 a));
|
||||
STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_fd_tell,
|
||||
(w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b));
|
||||
STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_path_create_directory,
|
||||
(w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b, u32 c));
|
||||
STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_path_filestat_get,
|
||||
(w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b, u32 c, u32 d, u32 e));
|
||||
STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_path_filestat_set_times,
|
||||
(w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b, u32 c, u32 d, u64 e, u64 f, u32 g));
|
||||
STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_path_link,
|
||||
(w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b, u32 c, u32 d, u32 e, u32 f, u32 g));
|
||||
STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_path_open,
|
||||
(w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b, u32 c, u32 d, u32 e, u64 f, u64 g, u32 h, u32 i));
|
||||
STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_path_readlink,
|
||||
(w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b, u32 c, u32 d, u32 e, u32 f));
|
||||
STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_path_remove_directory,
|
||||
(w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b, u32 c));
|
||||
STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_path_rename,
|
||||
(w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b, u32 c, u32 d, u32 e, u32 f));
|
||||
STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_path_symlink,
|
||||
(w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b, u32 c, u32 d, u32 e));
|
||||
STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_path_unlink_file,
|
||||
(w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b, u32 c));
|
||||
STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_poll_oneoff,
|
||||
(w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b, u32 c, u32 d));
|
||||
STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_proc_raise,
|
||||
(w2c_wasi__snapshot__preview1* wasi_data, u32 a));
|
||||
STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_random_get,
|
||||
(w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b));
|
||||
STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_sched_yield,
|
||||
(w2c_wasi__snapshot__preview1* wasi_data));
|
||||
STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_sock_accept,
|
||||
(w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b, u32 c));
|
||||
STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_sock_recv,
|
||||
(w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b, u32 c, u32 d, u32 e, u32 f));
|
||||
STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_sock_send,
|
||||
(w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b, u32 c, u32 d, u32 e));
|
||||
STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_sock_shutdown,
|
||||
(w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b));
|
||||
|
||||
// clang-format on
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
////////// Misc
|
||||
/////////////////////////////////////////////////////////////
|
||||
|
||||
bool minwasi_init()
|
||||
{
|
||||
return os_clock_init();
|
||||
}
|
||||
|
||||
bool minwasi_init_instance(w2c_wasi__snapshot__preview1* wasi_data)
|
||||
{
|
||||
return os_clock_init_instance(&(wasi_data->clock_data));
|
||||
}
|
||||
|
||||
void minwasi_cleanup_instance(w2c_wasi__snapshot__preview1* wasi_data)
|
||||
{
|
||||
os_clock_cleanup_instance(&(wasi_data->clock_data));
|
||||
}
|
@ -17,7 +17,7 @@
|
||||
#ifndef WABT_APPLY_NAMES_H_
|
||||
#define WABT_APPLY_NAMES_H_
|
||||
|
||||
#include "src/common.h"
|
||||
#include "wabt/common.h"
|
||||
|
||||
namespace wabt {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017 WebAssembly Community Group participants
|
||||
* Copyright 2021 WebAssembly Community Group participants
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -14,25 +14,22 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "src/hash-util.h"
|
||||
#ifndef WABT_BASE_TYPES_H_
|
||||
#define WABT_BASE_TYPES_H_
|
||||
|
||||
#include "config.h"
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
namespace wabt {
|
||||
|
||||
// Hash combiner from:
|
||||
// http://stackoverflow.com/questions/4948780/magic-number-in-boosthash-combine
|
||||
using Index = uint32_t; // An index into one of the many index spaces.
|
||||
using Address = uint64_t; // An address or size in linear memory.
|
||||
using Offset = size_t; // An offset into a host's file or memory buffer.
|
||||
|
||||
hash_code HashCombine(hash_code seed, hash_code y) {
|
||||
#if SIZEOF_SIZE_T == 4
|
||||
constexpr hash_code magic = 0x9e3779b9;
|
||||
#elif SIZEOF_SIZE_T == 8
|
||||
constexpr hash_code magic = 0x9e3779b97f4a7c16;
|
||||
#else
|
||||
#error "weird sizeof size_t"
|
||||
#endif
|
||||
seed ^= y + magic + (seed << 6) + (seed >> 2);
|
||||
return seed;
|
||||
}
|
||||
constexpr Address kInvalidAddress = ~0;
|
||||
constexpr Index kInvalidIndex = ~0;
|
||||
constexpr Offset kInvalidOffset = ~0;
|
||||
|
||||
} // namespace wabt
|
||||
|
||||
#endif // WABT_BASE_TYPES_H_
|
@ -17,8 +17,8 @@
|
||||
#ifndef WABT_BINARY_READER_IR_H_
|
||||
#define WABT_BINARY_READER_IR_H_
|
||||
|
||||
#include "src/common.h"
|
||||
#include "src/error.h"
|
||||
#include "wabt/common.h"
|
||||
#include "wabt/error.h"
|
||||
|
||||
namespace wabt {
|
||||
|
@ -17,7 +17,7 @@
|
||||
#ifndef WABT_BINARY_READER_LOGGING_H_
|
||||
#define WABT_BINARY_READER_LOGGING_H_
|
||||
|
||||
#include "src/binary-reader.h"
|
||||
#include "wabt/binary-reader.h"
|
||||
|
||||
namespace wabt {
|
||||
|
||||
@ -39,7 +39,7 @@ class BinaryReaderLogging : public BinaryReaderDelegate {
|
||||
|
||||
Result BeginCustomSection(Index section_index,
|
||||
Offset size,
|
||||
string_view section_name) override;
|
||||
std::string_view section_name) override;
|
||||
Result EndCustomSection() override;
|
||||
|
||||
Result BeginTypeSection(Offset size) override;
|
||||
@ -57,33 +57,33 @@ class BinaryReaderLogging : public BinaryReaderDelegate {
|
||||
Result OnImportCount(Index count) override;
|
||||
Result OnImport(Index index,
|
||||
ExternalKind kind,
|
||||
string_view module_name,
|
||||
string_view field_name) override;
|
||||
std::string_view module_name,
|
||||
std::string_view field_name) override;
|
||||
Result OnImportFunc(Index import_index,
|
||||
string_view module_name,
|
||||
string_view field_name,
|
||||
std::string_view module_name,
|
||||
std::string_view field_name,
|
||||
Index func_index,
|
||||
Index sig_index) override;
|
||||
Result OnImportTable(Index import_index,
|
||||
string_view module_name,
|
||||
string_view field_name,
|
||||
std::string_view module_name,
|
||||
std::string_view field_name,
|
||||
Index table_index,
|
||||
Type elem_type,
|
||||
const Limits* elem_limits) override;
|
||||
Result OnImportMemory(Index import_index,
|
||||
string_view module_name,
|
||||
string_view field_name,
|
||||
std::string_view module_name,
|
||||
std::string_view field_name,
|
||||
Index memory_index,
|
||||
const Limits* page_limits) override;
|
||||
Result OnImportGlobal(Index import_index,
|
||||
string_view module_name,
|
||||
string_view field_name,
|
||||
std::string_view module_name,
|
||||
std::string_view field_name,
|
||||
Index global_index,
|
||||
Type type,
|
||||
bool mutable_) override;
|
||||
Result OnImportTag(Index import_index,
|
||||
string_view module_name,
|
||||
string_view field_name,
|
||||
std::string_view module_name,
|
||||
std::string_view field_name,
|
||||
Index tag_index,
|
||||
Index sig_index) override;
|
||||
Result EndImportSection() override;
|
||||
@ -118,7 +118,7 @@ class BinaryReaderLogging : public BinaryReaderDelegate {
|
||||
Result OnExport(Index index,
|
||||
ExternalKind kind,
|
||||
Index item_index,
|
||||
string_view name) override;
|
||||
std::string_view name) override;
|
||||
Result EndExportSection() override;
|
||||
|
||||
Result BeginStartSection(Offset size) override;
|
||||
@ -140,6 +140,10 @@ class BinaryReaderLogging : public BinaryReaderDelegate {
|
||||
Result OnOpcodeUint32Uint32Uint32(uint32_t value,
|
||||
uint32_t value2,
|
||||
uint32_t value3) override;
|
||||
Result OnOpcodeUint32Uint32Uint32Uint32(uint32_t value,
|
||||
uint32_t value2,
|
||||
uint32_t value3,
|
||||
uint32_t value4) override;
|
||||
Result OnOpcodeUint64(uint64_t value) override;
|
||||
Result OnOpcodeF32(uint32_t value) override;
|
||||
Result OnOpcodeF64(uint64_t value) override;
|
||||
@ -147,15 +151,19 @@ class BinaryReaderLogging : public BinaryReaderDelegate {
|
||||
Result OnOpcodeBlockSig(Type sig_type) override;
|
||||
Result OnOpcodeType(Type type) override;
|
||||
Result OnAtomicLoadExpr(Opcode opcode,
|
||||
Index memidx,
|
||||
Address alignment_log2,
|
||||
Address offset) override;
|
||||
Result OnAtomicStoreExpr(Opcode opcode,
|
||||
Index memidx,
|
||||
Address alignment_log2,
|
||||
Address offset) override;
|
||||
Result OnAtomicRmwExpr(Opcode opcode,
|
||||
Index memidx,
|
||||
Address alignment_log2,
|
||||
Address offset) override;
|
||||
Result OnAtomicRmwCmpxchgExpr(Opcode opcode,
|
||||
Index memidx,
|
||||
Address alignment_log2,
|
||||
Address offset) override;
|
||||
Result OnBinaryExpr(Opcode opcode) override;
|
||||
@ -176,7 +184,6 @@ class BinaryReaderLogging : public BinaryReaderDelegate {
|
||||
Result OnDropExpr() override;
|
||||
Result OnElseExpr() override;
|
||||
Result OnEndExpr() override;
|
||||
Result OnEndFunc() override;
|
||||
Result OnF32ConstExpr(uint32_t value_bits) override;
|
||||
Result OnF64ConstExpr(uint64_t value_bits) override;
|
||||
Result OnV128ConstExpr(v128 value_bits) override;
|
||||
@ -186,18 +193,19 @@ class BinaryReaderLogging : public BinaryReaderDelegate {
|
||||
Result OnI64ConstExpr(uint64_t value) override;
|
||||
Result OnIfExpr(Type sig_type) override;
|
||||
Result OnLoadExpr(Opcode opcode,
|
||||
Index memidx,
|
||||
Address alignment_log2,
|
||||
Address offset) override;
|
||||
Result OnLocalGetExpr(Index local_index) override;
|
||||
Result OnLocalSetExpr(Index local_index) override;
|
||||
Result OnLocalTeeExpr(Index local_index) override;
|
||||
Result OnLoopExpr(Type sig_type) override;
|
||||
Result OnMemoryCopyExpr() override;
|
||||
Result OnMemoryCopyExpr(Index srcmemidx, Index destmemidx) override;
|
||||
Result OnDataDropExpr(Index segment_index) override;
|
||||
Result OnMemoryFillExpr() override;
|
||||
Result OnMemoryGrowExpr() override;
|
||||
Result OnMemoryInitExpr(Index segment_index) override;
|
||||
Result OnMemorySizeExpr() override;
|
||||
Result OnMemoryFillExpr(Index memidx) override;
|
||||
Result OnMemoryGrowExpr(Index memidx) override;
|
||||
Result OnMemoryInitExpr(Index segment_index, Index memidx) override;
|
||||
Result OnMemorySizeExpr(Index memidx) override;
|
||||
Result OnTableCopyExpr(Index dst_index, Index src_index) override;
|
||||
Result OnElemDropExpr(Index segment_index) override;
|
||||
Result OnTableInitExpr(Index segment_index, Index table_index) override;
|
||||
@ -216,6 +224,7 @@ class BinaryReaderLogging : public BinaryReaderDelegate {
|
||||
Result OnReturnExpr() override;
|
||||
Result OnSelectExpr(Index result_count, Type* result_types) override;
|
||||
Result OnStoreExpr(Opcode opcode,
|
||||
Index memidx,
|
||||
Address alignment_log2,
|
||||
Address offset) override;
|
||||
Result OnThrowExpr(Index tag_index) override;
|
||||
@ -224,28 +233,34 @@ class BinaryReaderLogging : public BinaryReaderDelegate {
|
||||
Result OnTernaryExpr(Opcode opcode) override;
|
||||
Result OnUnreachableExpr() override;
|
||||
Result OnAtomicWaitExpr(Opcode opcode,
|
||||
Index memidx,
|
||||
Address alignment_log2,
|
||||
Address offset) override;
|
||||
Result OnAtomicFenceExpr(uint32_t consistency_model) override;
|
||||
Result OnAtomicNotifyExpr(Opcode opcode,
|
||||
Index memidx,
|
||||
Address alignment_log2,
|
||||
Address offset) override;
|
||||
Result EndFunctionBody(Index index) override;
|
||||
Result EndCodeSection() override;
|
||||
Result OnSimdLaneOpExpr(Opcode opcode, uint64_t value) override;
|
||||
Result OnSimdLoadLaneExpr(Opcode opcode,
|
||||
Index memidx,
|
||||
Address alignment_log2,
|
||||
Address offset,
|
||||
uint64_t value) override;
|
||||
Result OnSimdStoreLaneExpr(Opcode opcode,
|
||||
Index memidx,
|
||||
Address alignment_log2,
|
||||
Address offset,
|
||||
uint64_t value) override;
|
||||
Result OnSimdShuffleOpExpr(Opcode opcode, v128 value) override;
|
||||
Result OnLoadSplatExpr(Opcode opcode,
|
||||
Index memidx,
|
||||
Address alignment_log2,
|
||||
Address offset) override;
|
||||
Result OnLoadZeroExpr(Opcode opcode,
|
||||
Index memidx,
|
||||
Address alignment_log2,
|
||||
Address offset) override;
|
||||
|
||||
@ -285,13 +300,13 @@ class BinaryReaderLogging : public BinaryReaderDelegate {
|
||||
Result OnModuleNameSubsection(Index index,
|
||||
uint32_t name_type,
|
||||
Offset subsection_size) override;
|
||||
Result OnModuleName(string_view name) override;
|
||||
Result OnModuleName(std::string_view name) override;
|
||||
Result OnFunctionNameSubsection(Index index,
|
||||
uint32_t name_type,
|
||||
Offset subsection_size) override;
|
||||
Result OnFunctionNamesCount(Index num_functions) override;
|
||||
Result OnFunctionName(Index function_index,
|
||||
string_view function_name) override;
|
||||
std::string_view function_name) override;
|
||||
Result OnLocalNameSubsection(Index index,
|
||||
uint32_t name_type,
|
||||
Offset subsection_size) override;
|
||||
@ -299,13 +314,13 @@ class BinaryReaderLogging : public BinaryReaderDelegate {
|
||||
Result OnLocalNameLocalCount(Index function_index, Index num_locals) override;
|
||||
Result OnLocalName(Index function_index,
|
||||
Index local_index,
|
||||
string_view local_name) override;
|
||||
std::string_view local_name) override;
|
||||
Result OnNameSubsection(Index index,
|
||||
NameSectionSubsection subsection_type,
|
||||
Offset subsection_size) override;
|
||||
Result OnNameEntry(NameSectionSubsection type,
|
||||
Index index,
|
||||
string_view name) override;
|
||||
std::string_view name) override;
|
||||
Result OnNameCount(Index num_names) override;
|
||||
Result EndNamesSection() override;
|
||||
|
||||
@ -323,45 +338,58 @@ class BinaryReaderLogging : public BinaryReaderDelegate {
|
||||
uint32_t table_size,
|
||||
uint32_t table_align) override;
|
||||
Result OnDylinkNeededCount(Index count) override;
|
||||
Result OnDylinkNeeded(string_view needed) override;
|
||||
Result OnDylinkNeeded(std::string_view needed) override;
|
||||
Result OnDylinkImportCount(Index count) override;
|
||||
Result OnDylinkExportCount(Index count) override;
|
||||
Result OnDylinkImport(std::string_view module,
|
||||
std::string_view name,
|
||||
uint32_t flags) override;
|
||||
Result OnDylinkExport(std::string_view name, uint32_t flags) override;
|
||||
Result EndDylinkSection() override;
|
||||
|
||||
Result BeginTargetFeaturesSection(Offset size) override;
|
||||
Result OnFeatureCount(Index count) override;
|
||||
Result OnFeature(uint8_t prefix, std::string_view name) override;
|
||||
Result EndTargetFeaturesSection() override;
|
||||
|
||||
Result BeginLinkingSection(Offset size) override;
|
||||
Result OnSymbolCount(Index count) override;
|
||||
Result OnDataSymbol(Index index,
|
||||
uint32_t flags,
|
||||
string_view name,
|
||||
std::string_view name,
|
||||
Index segment,
|
||||
uint32_t offset,
|
||||
uint32_t size) override;
|
||||
Result OnFunctionSymbol(Index index,
|
||||
uint32_t flags,
|
||||
string_view name,
|
||||
std::string_view name,
|
||||
Index func_index) override;
|
||||
Result OnGlobalSymbol(Index index,
|
||||
uint32_t flags,
|
||||
string_view name,
|
||||
std::string_view name,
|
||||
Index global_index) override;
|
||||
Result OnSectionSymbol(Index index,
|
||||
uint32_t flags,
|
||||
Index section_index) override;
|
||||
Result OnTagSymbol(Index index,
|
||||
uint32_t flags,
|
||||
string_view name,
|
||||
std::string_view name,
|
||||
Index tag_index) override;
|
||||
Result OnTableSymbol(Index index,
|
||||
uint32_t flags,
|
||||
string_view name,
|
||||
std::string_view name,
|
||||
Index tag_index) override;
|
||||
Result OnSegmentInfoCount(Index count) override;
|
||||
Result OnSegmentInfo(Index index,
|
||||
string_view name,
|
||||
std::string_view name,
|
||||
Address alignment,
|
||||
uint32_t flags) override;
|
||||
Result OnInitFunctionCount(Index count) override;
|
||||
Result OnInitFunction(uint32_t priority, Index function_index) override;
|
||||
Result OnComdatCount(Index count) override;
|
||||
Result OnComdatBegin(string_view name, uint32_t flags, Index count) override;
|
||||
Result OnComdatBegin(std::string_view name,
|
||||
uint32_t flags,
|
||||
Index count) override;
|
||||
Result OnComdatEntry(ComdatType kind, Index index) override;
|
||||
Result EndLinkingSection() override;
|
||||
|
||||
@ -370,14 +398,12 @@ class BinaryReaderLogging : public BinaryReaderDelegate {
|
||||
Result OnTagType(Index index, Index sig_index) override;
|
||||
Result EndTagSection() override;
|
||||
|
||||
Result OnInitExprF32ConstExpr(Index index, uint32_t value) override;
|
||||
Result OnInitExprF64ConstExpr(Index index, uint64_t value) override;
|
||||
Result OnInitExprV128ConstExpr(Index index, v128 value) override;
|
||||
Result OnInitExprGlobalGetExpr(Index index, Index global_index) override;
|
||||
Result OnInitExprI32ConstExpr(Index index, uint32_t value) override;
|
||||
Result OnInitExprI64ConstExpr(Index index, uint64_t value) override;
|
||||
Result OnInitExprRefNull(Index index, Type type) override;
|
||||
Result OnInitExprRefFunc(Index index, Index func_index) override;
|
||||
/* Code Metadata sections */
|
||||
Result BeginCodeMetadataSection(std::string_view name, Offset size) override;
|
||||
Result OnCodeMetadataFuncCount(Index count) override;
|
||||
Result OnCodeMetadataCount(Index function_index, Index count) override;
|
||||
Result OnCodeMetadata(Offset offset, const void* data, Address size) override;
|
||||
Result EndCodeMetadataSection() override;
|
||||
|
||||
private:
|
||||
void Indent();
|
@ -17,7 +17,7 @@
|
||||
#ifndef WABT_BINARY_READER_NOP_H_
|
||||
#define WABT_BINARY_READER_NOP_H_
|
||||
|
||||
#include "src/binary-reader.h"
|
||||
#include "wabt/binary-reader.h"
|
||||
|
||||
namespace wabt {
|
||||
|
||||
@ -38,7 +38,7 @@ class BinaryReaderNop : public BinaryReaderDelegate {
|
||||
/* Custom section */
|
||||
Result BeginCustomSection(Index section_index,
|
||||
Offset size,
|
||||
string_view section_name) override {
|
||||
std::string_view section_name) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result EndCustomSection() override { return Result::Ok; }
|
||||
@ -58,9 +58,7 @@ class BinaryReaderNop : public BinaryReaderDelegate {
|
||||
TypeMut* fields) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result OnArrayType(Index index, TypeMut field) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result OnArrayType(Index index, TypeMut field) override { return Result::Ok; }
|
||||
Result EndTypeSection() override { return Result::Ok; }
|
||||
|
||||
/* Import section */
|
||||
@ -68,43 +66,43 @@ class BinaryReaderNop : public BinaryReaderDelegate {
|
||||
Result OnImportCount(Index count) override { return Result::Ok; }
|
||||
Result OnImport(Index index,
|
||||
ExternalKind kind,
|
||||
string_view module_name,
|
||||
string_view field_name) override {
|
||||
std::string_view module_name,
|
||||
std::string_view field_name) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result OnImportFunc(Index import_index,
|
||||
string_view module_name,
|
||||
string_view field_name,
|
||||
std::string_view module_name,
|
||||
std::string_view field_name,
|
||||
Index func_index,
|
||||
Index sig_index) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result OnImportTable(Index import_index,
|
||||
string_view module_name,
|
||||
string_view field_name,
|
||||
std::string_view module_name,
|
||||
std::string_view field_name,
|
||||
Index table_index,
|
||||
Type elem_type,
|
||||
const Limits* elem_limits) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result OnImportMemory(Index import_index,
|
||||
string_view module_name,
|
||||
string_view field_name,
|
||||
std::string_view module_name,
|
||||
std::string_view field_name,
|
||||
Index memory_index,
|
||||
const Limits* page_limits) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result OnImportGlobal(Index import_index,
|
||||
string_view module_name,
|
||||
string_view field_name,
|
||||
std::string_view module_name,
|
||||
std::string_view field_name,
|
||||
Index global_index,
|
||||
Type type,
|
||||
bool mutable_) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result OnImportTag(Index import_index,
|
||||
string_view module_name,
|
||||
string_view field_name,
|
||||
std::string_view module_name,
|
||||
std::string_view field_name,
|
||||
Index tag_index,
|
||||
Index sig_index) override {
|
||||
return Result::Ok;
|
||||
@ -154,7 +152,7 @@ class BinaryReaderNop : public BinaryReaderDelegate {
|
||||
Result OnExport(Index index,
|
||||
ExternalKind kind,
|
||||
Index item_index,
|
||||
string_view name) override {
|
||||
std::string_view name) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result EndExportSection() override { return Result::Ok; }
|
||||
@ -192,6 +190,12 @@ class BinaryReaderNop : public BinaryReaderDelegate {
|
||||
uint32_t value3) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result OnOpcodeUint32Uint32Uint32Uint32(uint32_t value,
|
||||
uint32_t value2,
|
||||
uint32_t value3,
|
||||
uint32_t value4) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result OnOpcodeUint64(uint64_t value) override { return Result::Ok; }
|
||||
Result OnOpcodeF32(uint32_t value) override { return Result::Ok; }
|
||||
Result OnOpcodeF64(uint64_t value) override { return Result::Ok; }
|
||||
@ -199,32 +203,34 @@ class BinaryReaderNop : public BinaryReaderDelegate {
|
||||
Result OnOpcodeBlockSig(Type sig_type) override { return Result::Ok; }
|
||||
Result OnOpcodeType(Type type) override { return Result::Ok; }
|
||||
Result OnAtomicLoadExpr(Opcode opcode,
|
||||
Index memidx,
|
||||
Address alignment_log2,
|
||||
Address offset) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result OnAtomicStoreExpr(Opcode opcode,
|
||||
Index memidx,
|
||||
Address alignment_log2,
|
||||
Address offset) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result OnAtomicRmwExpr(Opcode opcode,
|
||||
Index memidx,
|
||||
Address alignment_log2,
|
||||
Address offset) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result OnAtomicRmwCmpxchgExpr(Opcode opcode,
|
||||
Index memidx,
|
||||
Address alignment_log2,
|
||||
Address offset) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result OnAtomicWaitExpr(Opcode, Address, Address) override {
|
||||
Result OnAtomicWaitExpr(Opcode, Index, Address, Address) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result OnAtomicFenceExpr(uint32_t) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result OnAtomicNotifyExpr(Opcode, Address, Address) override {
|
||||
Result OnAtomicFenceExpr(uint32_t) override { return Result::Ok; }
|
||||
Result OnAtomicNotifyExpr(Opcode, Index, Address, Address) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result OnBinaryExpr(Opcode opcode) override { return Result::Ok; }
|
||||
@ -237,7 +243,9 @@ class BinaryReaderNop : public BinaryReaderDelegate {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result OnCallExpr(Index func_index) override { return Result::Ok; }
|
||||
Result OnCallIndirectExpr(Index sig_index, Index table_index) override { return Result::Ok; }
|
||||
Result OnCallIndirectExpr(Index sig_index, Index table_index) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result OnCallRefExpr() override { return Result::Ok; }
|
||||
Result OnCatchExpr(Index tag_index) override { return Result::Ok; }
|
||||
Result OnCatchAllExpr() override { return Result::Ok; }
|
||||
@ -247,7 +255,6 @@ class BinaryReaderNop : public BinaryReaderDelegate {
|
||||
Result OnDropExpr() override { return Result::Ok; }
|
||||
Result OnElseExpr() override { return Result::Ok; }
|
||||
Result OnEndExpr() override { return Result::Ok; }
|
||||
Result OnEndFunc() override { return Result::Ok; }
|
||||
Result OnF32ConstExpr(uint32_t value_bits) override { return Result::Ok; }
|
||||
Result OnF64ConstExpr(uint64_t value_bits) override { return Result::Ok; }
|
||||
Result OnV128ConstExpr(v128 value_bits) override { return Result::Ok; }
|
||||
@ -257,6 +264,7 @@ class BinaryReaderNop : public BinaryReaderDelegate {
|
||||
Result OnI64ConstExpr(uint64_t value) override { return Result::Ok; }
|
||||
Result OnIfExpr(Type sig_type) override { return Result::Ok; }
|
||||
Result OnLoadExpr(Opcode opcode,
|
||||
Index memidx,
|
||||
Address alignment_log2,
|
||||
Address offset) override {
|
||||
return Result::Ok;
|
||||
@ -265,12 +273,16 @@ class BinaryReaderNop : public BinaryReaderDelegate {
|
||||
Result OnLocalSetExpr(Index local_index) override { return Result::Ok; }
|
||||
Result OnLocalTeeExpr(Index local_index) override { return Result::Ok; }
|
||||
Result OnLoopExpr(Type sig_type) override { return Result::Ok; }
|
||||
Result OnMemoryCopyExpr() override { return Result::Ok; }
|
||||
Result OnMemoryCopyExpr(Index srcmemidx, Index destmemidx) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result OnDataDropExpr(Index segment_index) override { return Result::Ok; }
|
||||
Result OnMemoryFillExpr() override { return Result::Ok; }
|
||||
Result OnMemoryGrowExpr() override { return Result::Ok; }
|
||||
Result OnMemoryInitExpr(Index segment_index) override { return Result::Ok; }
|
||||
Result OnMemorySizeExpr() override { return Result::Ok; }
|
||||
Result OnMemoryFillExpr(Index memidx) override { return Result::Ok; }
|
||||
Result OnMemoryGrowExpr(Index memidx) override { return Result::Ok; }
|
||||
Result OnMemoryInitExpr(Index segment_index, Index memidx) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result OnMemorySizeExpr(Index memidx) override { return Result::Ok; }
|
||||
Result OnTableCopyExpr(Index dst_index, Index src_index) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
@ -289,12 +301,15 @@ class BinaryReaderNop : public BinaryReaderDelegate {
|
||||
Result OnNopExpr() override { return Result::Ok; }
|
||||
Result OnRethrowExpr(Index depth) override { return Result::Ok; }
|
||||
Result OnReturnCallExpr(Index sig_index) override { return Result::Ok; }
|
||||
Result OnReturnCallIndirectExpr(Index sig_index, Index table_index) override { return Result::Ok; }
|
||||
Result OnReturnCallIndirectExpr(Index sig_index, Index table_index) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result OnReturnExpr() override { return Result::Ok; }
|
||||
Result OnSelectExpr(Index result_count, Type* result_types) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result OnStoreExpr(Opcode opcode,
|
||||
Index memidx,
|
||||
Address alignment_log2,
|
||||
Address offset) override {
|
||||
return Result::Ok;
|
||||
@ -310,12 +325,14 @@ class BinaryReaderNop : public BinaryReaderDelegate {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result OnSimdLoadLaneExpr(Opcode opcode,
|
||||
Index memidx,
|
||||
Address alignment_log2,
|
||||
Address offset,
|
||||
uint64_t value) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result OnSimdStoreLaneExpr(Opcode opcode,
|
||||
Index memidx,
|
||||
Address alignment_log2,
|
||||
Address offset,
|
||||
uint64_t value) override {
|
||||
@ -325,11 +342,13 @@ class BinaryReaderNop : public BinaryReaderDelegate {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result OnLoadSplatExpr(Opcode opcode,
|
||||
Index memidx,
|
||||
Address alignment_log2,
|
||||
Address offset) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result OnLoadZeroExpr(Opcode opcode,
|
||||
Index memidx,
|
||||
Address alignment_log2,
|
||||
Address offset) override {
|
||||
return Result::Ok;
|
||||
@ -392,7 +411,7 @@ class BinaryReaderNop : public BinaryReaderDelegate {
|
||||
Offset subsection_size) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result OnModuleName(string_view name) override { return Result::Ok; }
|
||||
Result OnModuleName(std::string_view name) override { return Result::Ok; }
|
||||
Result OnFunctionNameSubsection(Index index,
|
||||
uint32_t name_type,
|
||||
Offset subsection_size) override {
|
||||
@ -402,7 +421,7 @@ class BinaryReaderNop : public BinaryReaderDelegate {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result OnFunctionName(Index function_index,
|
||||
string_view function_name) override {
|
||||
std::string_view function_name) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result OnLocalNameSubsection(Index index,
|
||||
@ -419,7 +438,7 @@ class BinaryReaderNop : public BinaryReaderDelegate {
|
||||
}
|
||||
Result OnLocalName(Index function_index,
|
||||
Index local_index,
|
||||
string_view local_name) override {
|
||||
std::string_view local_name) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result EndNamesSection() override { return Result::Ok; }
|
||||
@ -432,7 +451,7 @@ class BinaryReaderNop : public BinaryReaderDelegate {
|
||||
Result OnNameCount(Index num_names) override { return Result::Ok; }
|
||||
Result OnNameEntry(NameSectionSubsection type,
|
||||
Index index,
|
||||
string_view name) override {
|
||||
std::string_view name) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
|
||||
@ -455,6 +474,21 @@ class BinaryReaderNop : public BinaryReaderDelegate {
|
||||
Result OnTagType(Index index, Index sig_index) override { return Result::Ok; }
|
||||
Result EndTagSection() override { return Result::Ok; }
|
||||
|
||||
/* Code Metadata sections */
|
||||
Result BeginCodeMetadataSection(std::string_view name, Offset size) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result OnCodeMetadataFuncCount(Index count) override { return Result::Ok; }
|
||||
Result OnCodeMetadataCount(Index function_index, Index count) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result OnCodeMetadata(Offset offset,
|
||||
const void* data,
|
||||
Address size) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result EndCodeMetadataSection() override { return Result::Ok; }
|
||||
|
||||
/* Dylink section */
|
||||
Result BeginDylinkSection(Offset size) override { return Result::Ok; }
|
||||
Result OnDylinkInfo(uint32_t mem_size,
|
||||
@ -464,15 +498,35 @@ class BinaryReaderNop : public BinaryReaderDelegate {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result OnDylinkNeededCount(Index count) override { return Result::Ok; }
|
||||
Result OnDylinkNeeded(string_view so_name) override { return Result::Ok; }
|
||||
Result OnDylinkNeeded(std::string_view so_name) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result OnDylinkImportCount(Index count) override { return Result::Ok; }
|
||||
Result OnDylinkExportCount(Index count) override { return Result::Ok; }
|
||||
Result OnDylinkImport(std::string_view module,
|
||||
std::string_view name,
|
||||
uint32_t flags) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result OnDylinkExport(std::string_view name, uint32_t flags) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result EndDylinkSection() override { return Result::Ok; }
|
||||
|
||||
/* target_features section */
|
||||
Result BeginTargetFeaturesSection(Offset size) override { return Result::Ok; }
|
||||
Result OnFeatureCount(Index count) override { return Result::Ok; }
|
||||
Result OnFeature(uint8_t prefix, std::string_view name) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result EndTargetFeaturesSection() override { return Result::Ok; }
|
||||
|
||||
/* Linking section */
|
||||
Result BeginLinkingSection(Offset size) override { return Result::Ok; }
|
||||
Result OnSymbolCount(Index count) override { return Result::Ok; }
|
||||
Result OnDataSymbol(Index index,
|
||||
uint32_t flags,
|
||||
string_view name,
|
||||
std::string_view name,
|
||||
Index segment,
|
||||
uint32_t offset,
|
||||
uint32_t size) override {
|
||||
@ -480,13 +534,13 @@ class BinaryReaderNop : public BinaryReaderDelegate {
|
||||
}
|
||||
Result OnFunctionSymbol(Index index,
|
||||
uint32_t flags,
|
||||
string_view name,
|
||||
std::string_view name,
|
||||
Index func_index) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result OnGlobalSymbol(Index index,
|
||||
uint32_t flags,
|
||||
string_view name,
|
||||
std::string_view name,
|
||||
Index global_index) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
@ -497,19 +551,19 @@ class BinaryReaderNop : public BinaryReaderDelegate {
|
||||
}
|
||||
Result OnTagSymbol(Index index,
|
||||
uint32_t flags,
|
||||
string_view name,
|
||||
std::string_view name,
|
||||
Index tag_index) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result OnTableSymbol(Index index,
|
||||
uint32_t flags,
|
||||
string_view name,
|
||||
std::string_view name,
|
||||
Index table_index) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result OnSegmentInfoCount(Index count) override { return Result::Ok; }
|
||||
Result OnSegmentInfo(Index index,
|
||||
string_view name,
|
||||
std::string_view name,
|
||||
Address alignment,
|
||||
uint32_t flags) override {
|
||||
return Result::Ok;
|
||||
@ -519,40 +573,15 @@ class BinaryReaderNop : public BinaryReaderDelegate {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result OnComdatCount(Index count) override { return Result::Ok; }
|
||||
Result OnComdatBegin(string_view name, uint32_t flags, Index count) override {
|
||||
Result OnComdatBegin(std::string_view name,
|
||||
uint32_t flags,
|
||||
Index count) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result OnComdatEntry(ComdatType kind, Index index) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result EndLinkingSection() override { return Result::Ok; }
|
||||
|
||||
/* InitExpr - used by elem, data and global sections; these functions are
|
||||
* only called between calls to Begin*InitExpr and End*InitExpr */
|
||||
Result OnInitExprF32ConstExpr(Index index, uint32_t value) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result OnInitExprF64ConstExpr(Index index, uint64_t value) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result OnInitExprV128ConstExpr(Index index, v128 value) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result OnInitExprGlobalGetExpr(Index index, Index global_index) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result OnInitExprI32ConstExpr(Index index, uint32_t value) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result OnInitExprI64ConstExpr(Index index, uint64_t value) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result OnInitExprRefNull(Index index, Type type) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
Result OnInitExprRefFunc(Index index, Index func_index) override {
|
||||
return Result::Ok;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace wabt
|
@ -20,9 +20,9 @@
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "src/common.h"
|
||||
#include "src/feature.h"
|
||||
#include "src/stream.h"
|
||||
#include "wabt/common.h"
|
||||
#include "wabt/feature.h"
|
||||
#include "wabt/stream.h"
|
||||
|
||||
namespace wabt {
|
||||
|
||||
@ -58,24 +58,34 @@ struct ObjdumpSymbol {
|
||||
};
|
||||
|
||||
struct ObjdumpNames {
|
||||
string_view Get(Index index) const;
|
||||
void Set(Index index, string_view name);
|
||||
std::string_view Get(Index index) const;
|
||||
void Set(Index index, std::string_view name);
|
||||
|
||||
std::map<Index, std::string> names;
|
||||
};
|
||||
|
||||
struct ObjdumpLocalNames {
|
||||
std::string_view Get(Index function_index, Index local_index) const;
|
||||
void Set(Index function_index, Index local_index, std::string_view name);
|
||||
|
||||
std::map<std::pair<Index, Index>, std::string> names;
|
||||
};
|
||||
|
||||
// read_binary_objdump uses this state to store information from previous runs
|
||||
// and use it to display more useful information.
|
||||
struct ObjdumpState {
|
||||
std::vector<Reloc> code_relocations;
|
||||
std::vector<Reloc> data_relocations;
|
||||
ObjdumpNames type_names;
|
||||
ObjdumpNames function_names;
|
||||
ObjdumpNames global_names;
|
||||
ObjdumpNames section_names;
|
||||
ObjdumpNames tag_names;
|
||||
ObjdumpNames segment_names;
|
||||
ObjdumpNames table_names;
|
||||
ObjdumpLocalNames local_names;
|
||||
std::vector<ObjdumpSymbol> symtab;
|
||||
std::map<Index, Index> function_param_counts;
|
||||
};
|
||||
|
||||
Result ReadBinaryObjdump(const uint8_t* data,
|
@ -20,8 +20,8 @@
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "src/common.h"
|
||||
#include "src/opcode.h"
|
||||
#include "wabt/common.h"
|
||||
#include "wabt/opcode.h"
|
||||
|
||||
namespace wabt {
|
||||
|
||||
@ -39,8 +39,11 @@ class OpcodeInfo {
|
||||
Float32,
|
||||
Float64,
|
||||
Uint32Uint32,
|
||||
Uint32Uint32Uint32,
|
||||
Uint32Uint32Uint32Uint32,
|
||||
BlockSig,
|
||||
BrTable,
|
||||
V128,
|
||||
};
|
||||
|
||||
explicit OpcodeInfo(Opcode, Kind);
|
||||
@ -81,7 +84,7 @@ bool operator<=(const OpcodeInfo&, const OpcodeInfo&);
|
||||
bool operator>(const OpcodeInfo&, const OpcodeInfo&);
|
||||
bool operator>=(const OpcodeInfo&, const OpcodeInfo&);
|
||||
|
||||
typedef std::map<OpcodeInfo, size_t> OpcodeInfoCounts;
|
||||
using OpcodeInfoCounts = std::map<OpcodeInfo, size_t>;
|
||||
|
||||
Result ReadBinaryOpcnt(const void* data,
|
||||
size_t size,
|
@ -17,15 +17,15 @@
|
||||
#ifndef WABT_BINARY_READER_H_
|
||||
#define WABT_BINARY_READER_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <string_view>
|
||||
|
||||
#include "src/binary.h"
|
||||
#include "src/common.h"
|
||||
#include "src/error.h"
|
||||
#include "src/feature.h"
|
||||
#include "src/opcode.h"
|
||||
#include "src/string-view.h"
|
||||
#include "wabt/binary.h"
|
||||
#include "wabt/common.h"
|
||||
#include "wabt/error.h"
|
||||
#include "wabt/feature.h"
|
||||
#include "wabt/opcode.h"
|
||||
|
||||
namespace wabt {
|
||||
|
||||
@ -49,6 +49,7 @@ struct ReadBinaryOptions {
|
||||
bool read_debug_names = false;
|
||||
bool stop_on_first_error = true;
|
||||
bool fail_on_custom_section_error = true;
|
||||
bool skip_function_bodies = false;
|
||||
};
|
||||
|
||||
// TODO: Move somewhere else?
|
||||
@ -85,7 +86,7 @@ class BinaryReaderDelegate {
|
||||
/* Custom section */
|
||||
virtual Result BeginCustomSection(Index section_index,
|
||||
Offset size,
|
||||
string_view section_name) = 0;
|
||||
std::string_view section_name) = 0;
|
||||
virtual Result EndCustomSection() = 0;
|
||||
|
||||
/* Type section */
|
||||
@ -107,33 +108,33 @@ class BinaryReaderDelegate {
|
||||
virtual Result OnImportCount(Index count) = 0;
|
||||
virtual Result OnImport(Index index,
|
||||
ExternalKind kind,
|
||||
string_view module_name,
|
||||
string_view field_name) = 0;
|
||||
std::string_view module_name,
|
||||
std::string_view field_name) = 0;
|
||||
virtual Result OnImportFunc(Index import_index,
|
||||
string_view module_name,
|
||||
string_view field_name,
|
||||
std::string_view module_name,
|
||||
std::string_view field_name,
|
||||
Index func_index,
|
||||
Index sig_index) = 0;
|
||||
virtual Result OnImportTable(Index import_index,
|
||||
string_view module_name,
|
||||
string_view field_name,
|
||||
std::string_view module_name,
|
||||
std::string_view field_name,
|
||||
Index table_index,
|
||||
Type elem_type,
|
||||
const Limits* elem_limits) = 0;
|
||||
virtual Result OnImportMemory(Index import_index,
|
||||
string_view module_name,
|
||||
string_view field_name,
|
||||
std::string_view module_name,
|
||||
std::string_view field_name,
|
||||
Index memory_index,
|
||||
const Limits* page_limits) = 0;
|
||||
virtual Result OnImportGlobal(Index import_index,
|
||||
string_view module_name,
|
||||
string_view field_name,
|
||||
std::string_view module_name,
|
||||
std::string_view field_name,
|
||||
Index global_index,
|
||||
Type type,
|
||||
bool mutable_) = 0;
|
||||
virtual Result OnImportTag(Index import_index,
|
||||
string_view module_name,
|
||||
string_view field_name,
|
||||
std::string_view module_name,
|
||||
std::string_view field_name,
|
||||
Index tag_index,
|
||||
Index sig_index) = 0;
|
||||
virtual Result EndImportSection() = 0;
|
||||
@ -173,7 +174,7 @@ class BinaryReaderDelegate {
|
||||
virtual Result OnExport(Index index,
|
||||
ExternalKind kind,
|
||||
Index item_index,
|
||||
string_view name) = 0;
|
||||
std::string_view name) = 0;
|
||||
virtual Result EndExportSection() = 0;
|
||||
|
||||
/* Start section */
|
||||
@ -199,6 +200,10 @@ class BinaryReaderDelegate {
|
||||
virtual Result OnOpcodeUint32Uint32Uint32(uint32_t value,
|
||||
uint32_t value2,
|
||||
uint32_t value3) = 0;
|
||||
virtual Result OnOpcodeUint32Uint32Uint32Uint32(uint32_t value,
|
||||
uint32_t value2,
|
||||
uint32_t value3,
|
||||
uint32_t value4) = 0;
|
||||
virtual Result OnOpcodeUint64(uint64_t value) = 0;
|
||||
virtual Result OnOpcodeF32(uint32_t value) = 0;
|
||||
virtual Result OnOpcodeF64(uint64_t value) = 0;
|
||||
@ -206,22 +211,28 @@ class BinaryReaderDelegate {
|
||||
virtual Result OnOpcodeBlockSig(Type sig_type) = 0;
|
||||
virtual Result OnOpcodeType(Type type) = 0;
|
||||
virtual Result OnAtomicLoadExpr(Opcode opcode,
|
||||
Index memidx,
|
||||
Address alignment_log2,
|
||||
Address offset) = 0;
|
||||
virtual Result OnAtomicStoreExpr(Opcode opcode,
|
||||
Index memidx,
|
||||
Address alignment_log2,
|
||||
Address offset) = 0;
|
||||
virtual Result OnAtomicRmwExpr(Opcode opcode,
|
||||
Index memidx,
|
||||
Address alignment_log2,
|
||||
Address offset) = 0;
|
||||
virtual Result OnAtomicRmwCmpxchgExpr(Opcode opcode,
|
||||
Index memidx,
|
||||
Address alignment_log2,
|
||||
Address offset) = 0;
|
||||
virtual Result OnAtomicWaitExpr(Opcode opcode,
|
||||
Index memidx,
|
||||
Address alignment_log2,
|
||||
Address offset) = 0;
|
||||
virtual Result OnAtomicFenceExpr(uint32_t consistency_model) = 0;
|
||||
virtual Result OnAtomicNotifyExpr(Opcode opcode,
|
||||
Index memidx,
|
||||
Address alignment_log2,
|
||||
Address offset) = 0;
|
||||
virtual Result OnBinaryExpr(Opcode opcode) = 0;
|
||||
@ -242,7 +253,6 @@ class BinaryReaderDelegate {
|
||||
virtual Result OnDropExpr() = 0;
|
||||
virtual Result OnElseExpr() = 0;
|
||||
virtual Result OnEndExpr() = 0;
|
||||
virtual Result OnEndFunc() = 0;
|
||||
virtual Result OnF32ConstExpr(uint32_t value_bits) = 0;
|
||||
virtual Result OnF64ConstExpr(uint64_t value_bits) = 0;
|
||||
virtual Result OnV128ConstExpr(v128 value_bits) = 0;
|
||||
@ -252,18 +262,19 @@ class BinaryReaderDelegate {
|
||||
virtual Result OnI64ConstExpr(uint64_t value) = 0;
|
||||
virtual Result OnIfExpr(Type sig_type) = 0;
|
||||
virtual Result OnLoadExpr(Opcode opcode,
|
||||
Index memidx,
|
||||
Address alignment_log2,
|
||||
Address offset) = 0;
|
||||
virtual Result OnLocalGetExpr(Index local_index) = 0;
|
||||
virtual Result OnLocalSetExpr(Index local_index) = 0;
|
||||
virtual Result OnLocalTeeExpr(Index local_index) = 0;
|
||||
virtual Result OnLoopExpr(Type sig_type) = 0;
|
||||
virtual Result OnMemoryCopyExpr() = 0;
|
||||
virtual Result OnMemoryCopyExpr(Index srcmemidx, Index destmemidx) = 0;
|
||||
virtual Result OnDataDropExpr(Index segment_index) = 0;
|
||||
virtual Result OnMemoryFillExpr() = 0;
|
||||
virtual Result OnMemoryGrowExpr() = 0;
|
||||
virtual Result OnMemoryInitExpr(Index segment_index) = 0;
|
||||
virtual Result OnMemorySizeExpr() = 0;
|
||||
virtual Result OnMemoryFillExpr(Index memidx) = 0;
|
||||
virtual Result OnMemoryGrowExpr(Index memidx) = 0;
|
||||
virtual Result OnMemoryInitExpr(Index segment_index, Index memidx) = 0;
|
||||
virtual Result OnMemorySizeExpr(Index memidx) = 0;
|
||||
virtual Result OnTableCopyExpr(Index dst_index, Index src_index) = 0;
|
||||
virtual Result OnElemDropExpr(Index segment_index) = 0;
|
||||
virtual Result OnTableInitExpr(Index segment_index, Index table_index) = 0;
|
||||
@ -283,6 +294,7 @@ class BinaryReaderDelegate {
|
||||
Index table_index) = 0;
|
||||
virtual Result OnSelectExpr(Index result_count, Type* result_types) = 0;
|
||||
virtual Result OnStoreExpr(Opcode opcode,
|
||||
Index memidx,
|
||||
Address alignment_log2,
|
||||
Address offset) = 0;
|
||||
virtual Result OnThrowExpr(Index tag_index) = 0;
|
||||
@ -298,18 +310,22 @@ class BinaryReaderDelegate {
|
||||
virtual Result OnSimdLaneOpExpr(Opcode opcode, uint64_t value) = 0;
|
||||
virtual Result OnSimdShuffleOpExpr(Opcode opcode, v128 value) = 0;
|
||||
virtual Result OnSimdLoadLaneExpr(Opcode opcode,
|
||||
Index memidx,
|
||||
Address alignment_log2,
|
||||
Address offset,
|
||||
uint64_t value) = 0;
|
||||
virtual Result OnSimdStoreLaneExpr(Opcode opcode,
|
||||
Index memidx,
|
||||
Address alignment_log2,
|
||||
Address offset,
|
||||
uint64_t value) = 0;
|
||||
|
||||
virtual Result OnLoadSplatExpr(Opcode opcode,
|
||||
Index memidx,
|
||||
Address alignment_log2,
|
||||
Address offset) = 0;
|
||||
virtual Result OnLoadZeroExpr(Opcode opcode,
|
||||
Index memidx,
|
||||
Address alignment_log2,
|
||||
Address offset) = 0;
|
||||
|
||||
@ -354,13 +370,13 @@ class BinaryReaderDelegate {
|
||||
virtual Result OnModuleNameSubsection(Index index,
|
||||
uint32_t name_type,
|
||||
Offset subsection_size) = 0;
|
||||
virtual Result OnModuleName(string_view name) = 0;
|
||||
virtual Result OnModuleName(std::string_view name) = 0;
|
||||
virtual Result OnFunctionNameSubsection(Index index,
|
||||
uint32_t name_type,
|
||||
Offset subsection_size) = 0;
|
||||
virtual Result OnFunctionNamesCount(Index num_functions) = 0;
|
||||
virtual Result OnFunctionName(Index function_index,
|
||||
string_view function_name) = 0;
|
||||
std::string_view function_name) = 0;
|
||||
virtual Result OnLocalNameSubsection(Index index,
|
||||
uint32_t name_type,
|
||||
Offset subsection_size) = 0;
|
||||
@ -369,20 +385,19 @@ class BinaryReaderDelegate {
|
||||
Index num_locals) = 0;
|
||||
virtual Result OnLocalName(Index function_index,
|
||||
Index local_index,
|
||||
string_view local_name) = 0;
|
||||
std::string_view local_name) = 0;
|
||||
virtual Result OnNameSubsection(Index index,
|
||||
NameSectionSubsection subsection_type,
|
||||
Offset subsection_size) = 0;
|
||||
virtual Result OnNameCount(Index num_names) = 0;
|
||||
virtual Result OnNameEntry(NameSectionSubsection type,
|
||||
Index index,
|
||||
string_view name) = 0;
|
||||
std::string_view name) = 0;
|
||||
virtual Result EndNamesSection() = 0;
|
||||
|
||||
/* Reloc section */
|
||||
virtual Result BeginRelocSection(Offset size) = 0;
|
||||
virtual Result OnRelocCount(Index count,
|
||||
Index section_index) = 0;
|
||||
virtual Result OnRelocCount(Index count, Index section_index) = 0;
|
||||
virtual Result OnReloc(RelocType type,
|
||||
Offset offset,
|
||||
Index index,
|
||||
@ -395,47 +410,59 @@ class BinaryReaderDelegate {
|
||||
uint32_t mem_align_log2,
|
||||
uint32_t table_size,
|
||||
uint32_t table_align_log2) = 0;
|
||||
virtual Result OnDylinkImportCount(Index count) = 0;
|
||||
virtual Result OnDylinkExportCount(Index count) = 0;
|
||||
virtual Result OnDylinkImport(std::string_view module,
|
||||
std::string_view name,
|
||||
uint32_t flags) = 0;
|
||||
virtual Result OnDylinkExport(std::string_view name, uint32_t flags) = 0;
|
||||
virtual Result OnDylinkNeededCount(Index count) = 0;
|
||||
virtual Result OnDylinkNeeded(string_view so_name) = 0;
|
||||
virtual Result OnDylinkNeeded(std::string_view so_name) = 0;
|
||||
virtual Result EndDylinkSection() = 0;
|
||||
|
||||
/* target_features section */
|
||||
virtual Result BeginTargetFeaturesSection(Offset size) = 0;
|
||||
virtual Result OnFeatureCount(Index count) = 0;
|
||||
virtual Result OnFeature(uint8_t prefix, std::string_view name) = 0;
|
||||
virtual Result EndTargetFeaturesSection() = 0;
|
||||
|
||||
/* Linking section */
|
||||
virtual Result BeginLinkingSection(Offset size) = 0;
|
||||
virtual Result OnSymbolCount(Index count) = 0;
|
||||
virtual Result OnDataSymbol(Index index,
|
||||
uint32_t flags,
|
||||
string_view name,
|
||||
std::string_view name,
|
||||
Index segment,
|
||||
uint32_t offset,
|
||||
uint32_t size) = 0;
|
||||
virtual Result OnFunctionSymbol(Index index,
|
||||
uint32_t flags,
|
||||
string_view name,
|
||||
std::string_view name,
|
||||
Index function_index) = 0;
|
||||
virtual Result OnGlobalSymbol(Index index,
|
||||
uint32_t flags,
|
||||
string_view name,
|
||||
std::string_view name,
|
||||
Index global_index) = 0;
|
||||
virtual Result OnSectionSymbol(Index index,
|
||||
uint32_t flags,
|
||||
Index section_index) = 0;
|
||||
virtual Result OnTagSymbol(Index index,
|
||||
uint32_t flags,
|
||||
string_view name,
|
||||
std::string_view name,
|
||||
Index tag_index) = 0;
|
||||
virtual Result OnTableSymbol(Index index,
|
||||
uint32_t flags,
|
||||
string_view name,
|
||||
std::string_view name,
|
||||
Index table_index) = 0;
|
||||
virtual Result OnSegmentInfoCount(Index count) = 0;
|
||||
virtual Result OnSegmentInfo(Index index,
|
||||
string_view name,
|
||||
std::string_view name,
|
||||
Address alignment_log2,
|
||||
uint32_t flags) = 0;
|
||||
virtual Result OnInitFunctionCount(Index count) = 0;
|
||||
virtual Result OnInitFunction(uint32_t priority, Index function_index) = 0;
|
||||
virtual Result OnComdatCount(Index count) = 0;
|
||||
virtual Result OnComdatBegin(string_view name,
|
||||
virtual Result OnComdatBegin(std::string_view name,
|
||||
uint32_t flags,
|
||||
Index count) = 0;
|
||||
virtual Result OnComdatEntry(ComdatType kind, Index index) = 0;
|
||||
@ -447,16 +474,15 @@ class BinaryReaderDelegate {
|
||||
virtual Result OnTagType(Index index, Index sig_index) = 0;
|
||||
virtual Result EndTagSection() = 0;
|
||||
|
||||
/* InitExpr - used by elem, data and global sections; these functions are
|
||||
* only called between calls to Begin*InitExpr and End*InitExpr */
|
||||
virtual Result OnInitExprF32ConstExpr(Index index, uint32_t value) = 0;
|
||||
virtual Result OnInitExprF64ConstExpr(Index index, uint64_t value) = 0;
|
||||
virtual Result OnInitExprV128ConstExpr(Index index, v128 value) = 0;
|
||||
virtual Result OnInitExprGlobalGetExpr(Index index, Index global_index) = 0;
|
||||
virtual Result OnInitExprI32ConstExpr(Index index, uint32_t value) = 0;
|
||||
virtual Result OnInitExprI64ConstExpr(Index index, uint64_t value) = 0;
|
||||
virtual Result OnInitExprRefNull(Index index, Type type) = 0;
|
||||
virtual Result OnInitExprRefFunc(Index index, Index func_index) = 0;
|
||||
/* Code Metadata sections */
|
||||
virtual Result BeginCodeMetadataSection(std::string_view name,
|
||||
Offset size) = 0;
|
||||
virtual Result OnCodeMetadataFuncCount(Index count) = 0;
|
||||
virtual Result OnCodeMetadataCount(Index function_index, Index count) = 0;
|
||||
virtual Result OnCodeMetadata(Offset offset,
|
||||
const void* data,
|
||||
Address size) = 0;
|
||||
virtual Result EndCodeMetadataSection() = 0;
|
||||
|
||||
const State* state = nullptr;
|
||||
};
|
@ -21,36 +21,36 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "src/binary-writer.h"
|
||||
#include "src/common.h"
|
||||
#include "src/ir.h"
|
||||
#include "wabt/binary-writer.h"
|
||||
#include "wabt/common.h"
|
||||
#include "wabt/ir.h"
|
||||
|
||||
namespace wabt {
|
||||
|
||||
struct FilenameMemoryStreamPair {
|
||||
FilenameMemoryStreamPair(string_view filename,
|
||||
FilenameMemoryStreamPair(std::string_view filename,
|
||||
std::unique_ptr<MemoryStream> stream)
|
||||
: filename(filename), stream(std::move(stream)) {}
|
||||
std::string filename;
|
||||
std::unique_ptr<MemoryStream> stream;
|
||||
};
|
||||
|
||||
typedef std::function<Stream*(string_view filename)>
|
||||
WriteBinarySpecStreamFactory;
|
||||
using WriteBinarySpecStreamFactory =
|
||||
std::function<Stream*(std::string_view filename)>;
|
||||
|
||||
Result WriteBinarySpecScript(Stream* json_stream,
|
||||
WriteBinarySpecStreamFactory module_stream_factory,
|
||||
Script*,
|
||||
string_view source_filename,
|
||||
string_view module_filename_noext,
|
||||
std::string_view source_filename,
|
||||
std::string_view module_filename_noext,
|
||||
const WriteBinaryOptions&);
|
||||
|
||||
// Convenience function for producing MemoryStream outputs all modules.
|
||||
Result WriteBinarySpecScript(
|
||||
Stream* json_stream,
|
||||
Script*,
|
||||
string_view source_filename,
|
||||
string_view module_filename_noext,
|
||||
std::string_view source_filename,
|
||||
std::string_view module_filename_noext,
|
||||
const WriteBinaryOptions&,
|
||||
std::vector<FilenameMemoryStreamPair>* out_module_streams,
|
||||
Stream* log_stream = nullptr);
|
@ -17,10 +17,10 @@
|
||||
#ifndef WABT_BINARY_WRITER_H_
|
||||
#define WABT_BINARY_WRITER_H_
|
||||
|
||||
#include "src/common.h"
|
||||
#include "src/feature.h"
|
||||
#include "src/opcode.h"
|
||||
#include "src/stream.h"
|
||||
#include "wabt/common.h"
|
||||
#include "wabt/feature.h"
|
||||
#include "wabt/opcode.h"
|
||||
#include "wabt/stream.h"
|
||||
|
||||
namespace wabt {
|
||||
|
||||
@ -49,7 +49,7 @@ Result WriteBinaryModule(Stream*, const Module*, const WriteBinaryOptions&);
|
||||
void WriteType(Stream* stream, Type type, const char* desc = nullptr);
|
||||
|
||||
void WriteStr(Stream* stream,
|
||||
string_view s,
|
||||
std::string_view s,
|
||||
const char* desc,
|
||||
PrintChars print_chars = PrintChars::No);
|
||||
|
@ -17,7 +17,7 @@
|
||||
#ifndef WABT_BINARY_H_
|
||||
#define WABT_BINARY_H_
|
||||
|
||||
#include "src/common.h"
|
||||
#include "wabt/common.h"
|
||||
|
||||
#define WABT_BINARY_MAGIC 0x6d736100
|
||||
#define WABT_BINARY_VERSION 1
|
||||
@ -31,8 +31,10 @@
|
||||
#define WABT_BINARY_SECTION_NAME "name"
|
||||
#define WABT_BINARY_SECTION_RELOC "reloc"
|
||||
#define WABT_BINARY_SECTION_LINKING "linking"
|
||||
#define WABT_BINARY_SECTION_TARGET_FEATURES "target_features"
|
||||
#define WABT_BINARY_SECTION_DYLINK "dylink"
|
||||
#define WABT_BINARY_SECTION_DYLINK0 "dylink.0"
|
||||
#define WABT_BINARY_SECTION_CODE_METADATA "metadata.code."
|
||||
|
||||
#define WABT_FOREACH_BINARY_SECTION(V) \
|
||||
V(Custom, custom, 0) \
|
||||
@ -63,7 +65,7 @@ enum class BinarySection {
|
||||
Last = Tag,
|
||||
};
|
||||
/* clang-format on */
|
||||
static const int kBinarySectionCount = WABT_ENUM_COUNT(BinarySection);
|
||||
constexpr int kBinarySectionCount = WABT_ENUM_COUNT(BinarySection);
|
||||
|
||||
enum class BinarySectionOrder {
|
||||
#define V(Name, name, code) Name,
|
||||
@ -74,6 +76,8 @@ enum class BinarySectionOrder {
|
||||
BinarySectionOrder GetSectionOrder(BinarySection);
|
||||
const char* GetSectionName(BinarySection);
|
||||
|
||||
// See
|
||||
// https://github.com/WebAssembly/extended-name-section/blob/main/proposals/extended-name-section/Overview.md
|
||||
enum class NameSectionSubsection {
|
||||
Module = 0,
|
||||
Function = 1,
|
||||
@ -85,7 +89,15 @@ enum class NameSectionSubsection {
|
||||
Global = 7,
|
||||
ElemSegment = 8,
|
||||
DataSegment = 9,
|
||||
Last = DataSegment,
|
||||
// tag names are yet part of the extended-name-section proposal (because it
|
||||
// only deals with naming things that are in the spec already). However, we
|
||||
// include names for Tags in wabt using this enum value on the basis that tags
|
||||
// can only exist when exceptions are enabled and that engines should ignore
|
||||
// unknown name types.
|
||||
Tag = 10,
|
||||
|
||||
First = Module,
|
||||
Last = Tag,
|
||||
};
|
||||
const char* GetNameSectionSubsectionName(NameSectionSubsection subsec);
|
||||
|
@ -19,11 +19,11 @@
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "src/common.h"
|
||||
#include "src/string-view.h"
|
||||
#include "wabt/common.h"
|
||||
|
||||
namespace wabt {
|
||||
|
||||
@ -42,8 +42,8 @@ struct Binding {
|
||||
// object through a pointer to std::unordered_multimap.
|
||||
class BindingHash : public std::unordered_multimap<std::string, Binding> {
|
||||
public:
|
||||
typedef std::function<void(const value_type&, const value_type&)>
|
||||
DuplicateCallback;
|
||||
using DuplicateCallback =
|
||||
std::function<void(const value_type&, const value_type&)>;
|
||||
|
||||
void FindDuplicates(DuplicateCallback callback) const;
|
||||
|
||||
@ -54,12 +54,12 @@ class BindingHash : public std::unordered_multimap<std::string, Binding> {
|
||||
return iter != end() ? iter->second.index : kInvalidIndex;
|
||||
}
|
||||
|
||||
Index FindIndex(string_view name) const {
|
||||
return FindIndex(name.to_string());
|
||||
Index FindIndex(std::string_view name) const {
|
||||
return FindIndex(std::string(name));
|
||||
}
|
||||
|
||||
private:
|
||||
typedef std::vector<const value_type*> ValueTypeVector;
|
||||
using ValueTypeVector = std::vector<const value_type*>;
|
||||
|
||||
void CreateDuplicatesVector(ValueTypeVector* out_duplicates) const;
|
||||
void SortDuplicatesVectorByLocation(ValueTypeVector* duplicates) const;
|
56
third_party/wasm2c/include/wabt/c-writer.h
vendored
Normal file
56
third_party/wasm2c/include/wabt/c-writer.h
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2017 WebAssembly Community Group participants
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef WABT_C_WRITER_H_
|
||||
#define WABT_C_WRITER_H_
|
||||
|
||||
#include <functional>
|
||||
#include "wabt/common.h"
|
||||
#include "wabt/ir.h"
|
||||
|
||||
namespace wabt {
|
||||
|
||||
struct Module;
|
||||
class Stream;
|
||||
|
||||
struct WriteCOptions {
|
||||
std::string_view module_name;
|
||||
/*
|
||||
* name_to_output_file_index takes const iterators to begin and end of a list
|
||||
* of all functions in the module, number of imported functions, and number of
|
||||
* .c outputs as argument, returns a vector where vector[i] the index of the
|
||||
* .c output that funcs_begin + i goes into. Only called when --num-outputs is
|
||||
* used.
|
||||
*/
|
||||
std::function<std::vector<size_t>(
|
||||
std::vector<Func*>::const_iterator funcs_begin,
|
||||
std::vector<Func*>::const_iterator funcs_end,
|
||||
size_t num_imported_functions,
|
||||
size_t num_outputs)>
|
||||
name_to_output_file_index;
|
||||
};
|
||||
|
||||
Result WriteC(std::vector<Stream*>&& c_streams,
|
||||
Stream* h_stream,
|
||||
Stream* h_impl_stream,
|
||||
const char* header_name,
|
||||
const char* header_impl_name,
|
||||
const Module*,
|
||||
const WriteCOptions&);
|
||||
|
||||
} // namespace wabt
|
||||
|
||||
#endif /* WABT_C_WRITER_H_ */
|
@ -20,7 +20,7 @@
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
#include "src/common.h"
|
||||
#include "wabt/common.h"
|
||||
|
||||
// Modeled after LLVM's dynamic casts:
|
||||
// http://llvm.org/docs/ProgrammersManual.html#the-isa-cast-and-dyn-cast-templates
|
@ -29,11 +29,11 @@ namespace wabt {
|
||||
template <class T, size_t kCapacity>
|
||||
class CircularArray {
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef value_type& reference;
|
||||
typedef const value_type& const_reference;
|
||||
typedef size_t size_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
using value_type = T;
|
||||
using reference = value_type&;
|
||||
using const_reference = const value_type&;
|
||||
using size_type = size_t;
|
||||
using difference_type = ptrdiff_t;
|
||||
|
||||
CircularArray() {
|
||||
static_assert(kCapacity && ((kCapacity & (kCapacity - 1)) == 0),
|
||||
@ -103,7 +103,7 @@ class CircularArray {
|
||||
}
|
||||
|
||||
private:
|
||||
static const size_type kMask = kCapacity - 1;
|
||||
static constexpr size_type kMask = kCapacity - 1;
|
||||
|
||||
size_t position(size_t index) const { return (front_ + index) & kMask; }
|
||||
|
@ -27,54 +27,32 @@
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#include "config.h"
|
||||
#include "wabt/config.h"
|
||||
|
||||
#include "src/make-unique.h"
|
||||
#include "src/result.h"
|
||||
#include "src/string-view.h"
|
||||
#include "src/type.h"
|
||||
#include "wabt/base-types.h"
|
||||
#include "wabt/result.h"
|
||||
#include "wabt/string-format.h"
|
||||
#include "wabt/type.h"
|
||||
|
||||
#define WABT_FATAL(...) fprintf(stderr, __VA_ARGS__), exit(1)
|
||||
#define WABT_ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
|
||||
|
||||
#define WABT_USE(x) static_cast<void>(x)
|
||||
|
||||
#define WABT_PAGE_SIZE 0x10000 /* 64k */
|
||||
#define WABT_MAX_PAGES32 0x10000 /* # of pages that fit in 32-bit address \
|
||||
space */
|
||||
#define WABT_MAX_PAGES64 0x1000000000000 /* # of pages that fit in 64-bit \
|
||||
address space */
|
||||
// 64k
|
||||
#define WABT_PAGE_SIZE 0x10000
|
||||
// # of pages that fit in 32-bit address space
|
||||
#define WABT_MAX_PAGES32 0x10000
|
||||
// # of pages that fit in 64-bit address space
|
||||
#define WABT_MAX_PAGES64 0x1000000000000
|
||||
#define WABT_BYTES_TO_PAGES(x) ((x) >> 16)
|
||||
#define WABT_ALIGN_UP_TO_PAGE(x) \
|
||||
(((x) + WABT_PAGE_SIZE - 1) & ~(WABT_PAGE_SIZE - 1))
|
||||
|
||||
#define PRIstringview "%.*s"
|
||||
#define WABT_PRINTF_STRING_VIEW_ARG(x) \
|
||||
static_cast<int>((x).length()), (x).data()
|
||||
|
||||
#define PRItypecode "%s%#x"
|
||||
#define WABT_PRINTF_TYPE_CODE(x) \
|
||||
(static_cast<int32_t>(x) < 0 ? "-" : ""), std::abs(static_cast<int32_t>(x))
|
||||
|
||||
#define WABT_DEFAULT_SNPRINTF_ALLOCA_BUFSIZE 128
|
||||
#define WABT_SNPRINTF_ALLOCA(buffer, len, format) \
|
||||
va_list args; \
|
||||
va_list args_copy; \
|
||||
va_start(args, format); \
|
||||
va_copy(args_copy, args); \
|
||||
char fixed_buf[WABT_DEFAULT_SNPRINTF_ALLOCA_BUFSIZE]; \
|
||||
char* buffer = fixed_buf; \
|
||||
size_t len = wabt_vsnprintf(fixed_buf, sizeof(fixed_buf), format, args); \
|
||||
va_end(args); \
|
||||
if (len + 1 > sizeof(fixed_buf)) { \
|
||||
buffer = static_cast<char*>(alloca(len + 1)); \
|
||||
len = wabt_vsnprintf(buffer, len + 1, format, args_copy); \
|
||||
} \
|
||||
va_end(args_copy)
|
||||
|
||||
#define WABT_ENUM_COUNT(name) \
|
||||
(static_cast<int>(name::Last) - static_cast<int>(name::First) + 1)
|
||||
|
||||
@ -104,20 +82,22 @@
|
||||
#define PRIoffset PRIzx
|
||||
|
||||
namespace wabt {
|
||||
inline void MemcpyEndianAware(void* dst,
|
||||
const void* src,
|
||||
size_t dsize,
|
||||
size_t ssize,
|
||||
size_t doff,
|
||||
size_t soff,
|
||||
size_t len) {
|
||||
#if WABT_BIG_ENDIAN
|
||||
inline void MemcpyEndianAware(void *dst, const void *src, size_t dsize, size_t ssize, size_t doff, size_t soff, size_t len) {
|
||||
memcpy(static_cast<char*>(dst) + (dsize) - (len) - (doff),
|
||||
static_cast<const char*>(src) + (ssize) - (len) - (soff),
|
||||
(len));
|
||||
}
|
||||
memcpy(static_cast<char*>(dst) + (dsize) - (len) - (doff),
|
||||
static_cast<const char*>(src) + (ssize) - (len) - (soff), (len));
|
||||
#else
|
||||
inline void MemcpyEndianAware(void *dst, const void *src, size_t dsize, size_t ssize, size_t doff, size_t soff, size_t len) {
|
||||
memcpy(static_cast<char*>(dst) + (doff),
|
||||
static_cast<const char*>(src) + (soff),
|
||||
(len));
|
||||
}
|
||||
memcpy(static_cast<char*>(dst) + (doff),
|
||||
static_cast<const char*>(src) + (soff), (len));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
struct v128 {
|
||||
v128() = default;
|
||||
@ -158,7 +138,8 @@ struct v128 {
|
||||
static_assert(sizeof(T) <= sizeof(v), "Invalid cast!");
|
||||
assert((lane + 1) * sizeof(T) <= sizeof(v));
|
||||
T result;
|
||||
wabt::MemcpyEndianAware(&result, v, sizeof(result), sizeof(v), 0, lane * sizeof(T), sizeof(result));
|
||||
wabt::MemcpyEndianAware(&result, v, sizeof(result), sizeof(v), 0,
|
||||
lane * sizeof(T), sizeof(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -166,7 +147,8 @@ struct v128 {
|
||||
void From(int lane, T data) {
|
||||
static_assert(sizeof(T) <= sizeof(v), "Invalid cast!");
|
||||
assert((lane + 1) * sizeof(T) <= sizeof(v));
|
||||
wabt::MemcpyEndianAware(v, &data, sizeof(v), sizeof(data), lane * sizeof(T), 0, sizeof(data));
|
||||
wabt::MemcpyEndianAware(v, &data, sizeof(v), sizeof(data), lane * sizeof(T),
|
||||
0, sizeof(data));
|
||||
}
|
||||
|
||||
uint8_t v[16];
|
||||
@ -174,14 +156,6 @@ struct v128 {
|
||||
|
||||
namespace wabt {
|
||||
|
||||
typedef uint32_t Index; // An index into one of the many index spaces.
|
||||
typedef uint64_t Address; // An address or size in linear memory.
|
||||
typedef size_t Offset; // An offset into a host's file or memory buffer.
|
||||
|
||||
static const Address kInvalidAddress = ~0;
|
||||
static const Index kInvalidIndex = ~0;
|
||||
static const Offset kInvalidOffset = ~0;
|
||||
|
||||
template <typename Dst, typename Src>
|
||||
Dst WABT_VECTORCALL Bitcast(Src&& value) {
|
||||
static_assert(sizeof(Src) == sizeof(Dst), "Bitcast sizes must match.");
|
||||
@ -208,22 +182,9 @@ void Destruct(T& placement) {
|
||||
placement.~T();
|
||||
}
|
||||
|
||||
inline std::string WABT_PRINTF_FORMAT(1, 2)
|
||||
StringPrintf(const char* format, ...) {
|
||||
va_list args;
|
||||
va_list args_copy;
|
||||
va_start(args, format);
|
||||
va_copy(args_copy, args);
|
||||
size_t len = wabt_vsnprintf(nullptr, 0, format, args) + 1; // For \0.
|
||||
std::vector<char> buffer(len);
|
||||
va_end(args);
|
||||
wabt_vsnprintf(buffer.data(), len, format, args_copy);
|
||||
va_end(args_copy);
|
||||
return std::string(buffer.data(), len - 1);
|
||||
}
|
||||
|
||||
enum class LabelType {
|
||||
Func,
|
||||
InitExpr,
|
||||
Block,
|
||||
Loop,
|
||||
If,
|
||||
@ -234,7 +195,7 @@ enum class LabelType {
|
||||
First = Func,
|
||||
Last = Catch,
|
||||
};
|
||||
static const int kLabelTypeCount = WABT_ENUM_COUNT(LabelType);
|
||||
constexpr int kLabelTypeCount = WABT_ENUM_COUNT(LabelType);
|
||||
|
||||
struct Location {
|
||||
enum class Type {
|
||||
@ -243,14 +204,17 @@ struct Location {
|
||||
};
|
||||
|
||||
Location() : line(0), first_column(0), last_column(0) {}
|
||||
Location(string_view filename, int line, int first_column, int last_column)
|
||||
Location(std::string_view filename,
|
||||
int line,
|
||||
int first_column,
|
||||
int last_column)
|
||||
: filename(filename),
|
||||
line(line),
|
||||
first_column(first_column),
|
||||
last_column(last_column) {}
|
||||
explicit Location(size_t offset) : offset(offset) {}
|
||||
|
||||
string_view filename;
|
||||
std::string_view filename;
|
||||
union {
|
||||
// For text files.
|
||||
struct {
|
||||
@ -298,7 +262,7 @@ enum class RelocType {
|
||||
MemoryAddressSLEB = 4, // e.g. Memory address in i32.const
|
||||
MemoryAddressI32 = 5, // e.g. Memory address in DATA
|
||||
TypeIndexLEB = 6, // e.g. Immediate type in call_indirect
|
||||
GlobalIndexLEB = 7, // e.g. Immediate of get_global inst
|
||||
GlobalIndexLEB = 7, // e.g. Immediate of global.get inst
|
||||
FunctionOffsetI32 = 8, // e.g. Code offset in DWARF metadata
|
||||
SectionOffsetI32 = 9, // e.g. Section offset in DWARF metadata
|
||||
TagIndexLEB = 10, // Used in throw instructions
|
||||
@ -318,7 +282,7 @@ enum class RelocType {
|
||||
First = FuncIndexLEB,
|
||||
Last = MemoryAddressTLSI32,
|
||||
};
|
||||
static const int kRelocTypeCount = WABT_ENUM_COUNT(RelocType);
|
||||
constexpr int kRelocTypeCount = WABT_ENUM_COUNT(RelocType);
|
||||
|
||||
struct Reloc {
|
||||
Reloc(RelocType, size_t offset, Index index, int32_t addend = 0);
|
||||
@ -339,6 +303,8 @@ enum class LinkingEntryType {
|
||||
enum class DylinkEntryType {
|
||||
MemInfo = 1,
|
||||
Needed = 2,
|
||||
ExportInfo = 3,
|
||||
ImportInfo = 4,
|
||||
};
|
||||
|
||||
enum class SymbolType {
|
||||
@ -390,7 +356,7 @@ enum class ExternalKind {
|
||||
First = Func,
|
||||
Last = Tag,
|
||||
};
|
||||
static const int kExternalKindCount = WABT_ENUM_COUNT(ExternalKind);
|
||||
constexpr int kExternalKindCount = WABT_ENUM_COUNT(ExternalKind);
|
||||
|
||||
struct Limits {
|
||||
Limits() = default;
|
||||
@ -416,7 +382,7 @@ struct Limits {
|
||||
|
||||
enum { WABT_USE_NATURAL_ALIGNMENT = 0xFFFFFFFFFFFFFFFF };
|
||||
|
||||
Result ReadFile(string_view filename, std::vector<uint8_t>* out_data);
|
||||
Result ReadFile(std::string_view filename, std::vector<uint8_t>* out_data);
|
||||
|
||||
void InitStdio();
|
||||
|
||||
@ -424,25 +390,25 @@ void InitStdio();
|
||||
|
||||
extern const char* g_kind_name[];
|
||||
|
||||
static WABT_INLINE const char* GetKindName(ExternalKind kind) {
|
||||
static inline const char* GetKindName(ExternalKind kind) {
|
||||
return static_cast<size_t>(kind) < kExternalKindCount
|
||||
? g_kind_name[static_cast<size_t>(kind)]
|
||||
: "<error_kind>";
|
||||
? g_kind_name[static_cast<size_t>(kind)]
|
||||
: "<error_kind>";
|
||||
}
|
||||
|
||||
/* reloc */
|
||||
|
||||
extern const char* g_reloc_type_name[];
|
||||
|
||||
static WABT_INLINE const char* GetRelocTypeName(RelocType reloc) {
|
||||
static inline const char* GetRelocTypeName(RelocType reloc) {
|
||||
return static_cast<size_t>(reloc) < kRelocTypeCount
|
||||
? g_reloc_type_name[static_cast<size_t>(reloc)]
|
||||
: "<error_reloc_type>";
|
||||
? g_reloc_type_name[static_cast<size_t>(reloc)]
|
||||
: "<error_reloc_type>";
|
||||
}
|
||||
|
||||
/* symbol */
|
||||
|
||||
static WABT_INLINE const char* GetSymbolTypeName(SymbolType type) {
|
||||
static inline const char* GetSymbolTypeName(SymbolType type) {
|
||||
switch (type) {
|
||||
case SymbolType::Function:
|
||||
return "func";
|
||||
@ -478,10 +444,10 @@ inline void ConvertBackslashToSlash(std::string* s) {
|
||||
ConvertBackslashToSlash(s->begin(), s->end());
|
||||
}
|
||||
|
||||
inline void SwapBytesSized(void *addr, size_t size) {
|
||||
inline void SwapBytesSized(void* addr, size_t size) {
|
||||
auto bytes = static_cast<uint8_t*>(addr);
|
||||
for (size_t i = 0; i < size / 2; i++) {
|
||||
std::swap(bytes[i], bytes[size-1-i]);
|
||||
std::swap(bytes[i], bytes[size - 1 - i]);
|
||||
}
|
||||
}
|
||||
|
@ -17,10 +17,10 @@
|
||||
#ifndef WABT_DECOMPILER_AST_H_
|
||||
#define WABT_DECOMPILER_AST_H_
|
||||
|
||||
#include "src/cast.h"
|
||||
#include "src/generate-names.h"
|
||||
#include "src/ir.h"
|
||||
#include "src/ir-util.h"
|
||||
#include "wabt/cast.h"
|
||||
#include "wabt/generate-names.h"
|
||||
#include "wabt/ir-util.h"
|
||||
#include "wabt/ir.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
@ -45,15 +45,16 @@ struct Node {
|
||||
std::vector<Node> children;
|
||||
// Node specific annotations.
|
||||
union {
|
||||
struct { Index var_start, var_count; }; // FlushedVar/FlushToVars
|
||||
struct {
|
||||
Index var_start, var_count; // FlushedVar/FlushToVars
|
||||
};
|
||||
const Var* var; // Decl/DeclInit.
|
||||
LabelType lt; // br/br_if target.
|
||||
LabelType lt; // br/br_if target.
|
||||
} u;
|
||||
|
||||
Node() : ntype(NodeType::Uninitialized), etype(ExprType::Nop), e(nullptr) {
|
||||
}
|
||||
Node() : ntype(NodeType::Uninitialized), etype(ExprType::Nop), e(nullptr) {}
|
||||
Node(NodeType ntype, ExprType etype, const Expr* e, const Var* v)
|
||||
: ntype(ntype), etype(etype), e(e) {
|
||||
: ntype(ntype), etype(etype), e(e) {
|
||||
u.var = v;
|
||||
}
|
||||
|
||||
@ -76,24 +77,26 @@ struct Node {
|
||||
};
|
||||
|
||||
struct AST {
|
||||
AST(ModuleContext& mc, const Func *f) : mc(mc), f(f) {
|
||||
AST(ModuleContext& mc, const Func* f) : mc(mc), f(f) {
|
||||
if (f) {
|
||||
mc.BeginFunc(*f);
|
||||
for (Index i = 0; i < f->GetNumParams(); i++) {
|
||||
auto name = "$" + IndexToAlphaName(i);
|
||||
vars_defined.insert({ name, { 0, false }});
|
||||
vars_defined.insert({name, {0, false}});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~AST() {
|
||||
if (f) mc.EndFunc();
|
||||
if (f) {
|
||||
mc.EndFunc();
|
||||
}
|
||||
}
|
||||
|
||||
// Create a new node, take nargs existing nodes on the exp stack as children.
|
||||
Node& InsertNode(NodeType ntype, ExprType etype, const Expr* e, Index nargs) {
|
||||
assert(exp_stack.size() >= nargs);
|
||||
Node n { ntype, etype, e, nullptr };
|
||||
Node n{ntype, etype, e, nullptr};
|
||||
n.children.reserve(nargs);
|
||||
std::move(exp_stack.end() - nargs, exp_stack.end(),
|
||||
std::back_inserter(n.children));
|
||||
@ -102,7 +105,8 @@ struct AST {
|
||||
return exp_stack.back();
|
||||
}
|
||||
|
||||
template<ExprType T> void PreDecl(const VarExpr<T>& ve) {
|
||||
template <ExprType T>
|
||||
void PreDecl(const VarExpr<T>& ve) {
|
||||
// FIXME: this is slow, and would be better to avoid in callers.
|
||||
// See https://github.com/WebAssembly/wabt/issues/1565
|
||||
// And https://github.com/WebAssembly/wabt/issues/1665
|
||||
@ -114,9 +118,10 @@ struct AST {
|
||||
predecls.emplace_back(NodeType::Decl, ExprType::Nop, nullptr, &ve.var);
|
||||
}
|
||||
|
||||
template<ExprType T> void Get(const VarExpr<T>& ve, bool local) {
|
||||
template <ExprType T>
|
||||
void Get(const VarExpr<T>& ve, bool local) {
|
||||
if (local) {
|
||||
auto ret = vars_defined.insert({ ve.var.name(), { cur_block_id, false }});
|
||||
auto ret = vars_defined.insert({ve.var.name(), {cur_block_id, false}});
|
||||
if (ret.second) {
|
||||
// Use before def, may happen since locals are guaranteed 0.
|
||||
PreDecl(ve);
|
||||
@ -130,10 +135,11 @@ struct AST {
|
||||
InsertNode(NodeType::Expr, T, &ve, 0);
|
||||
}
|
||||
|
||||
template<ExprType T> void Set(const VarExpr<T>& ve, bool local) {
|
||||
template <ExprType T>
|
||||
void Set(const VarExpr<T>& ve, bool local) {
|
||||
// Seen this var before?
|
||||
if (local &&
|
||||
vars_defined.insert({ ve.var.name(), { cur_block_id, false }}).second) {
|
||||
vars_defined.insert({ve.var.name(), {cur_block_id, false}}).second) {
|
||||
if (value_stack_depth == 1) {
|
||||
// Top level, declare it here.
|
||||
InsertNode(NodeType::DeclInit, ExprType::Nop, nullptr, 1).u.var =
|
||||
@ -147,9 +153,11 @@ struct AST {
|
||||
InsertNode(NodeType::Expr, T, &ve, 1);
|
||||
}
|
||||
|
||||
template<ExprType T> void Block(const BlockExprBase<T>& be, LabelType label) {
|
||||
template <ExprType T>
|
||||
void Block(const BlockExprBase<T>& be, LabelType label) {
|
||||
mc.BeginBlock(label, be.block);
|
||||
Construct(be.block.exprs, be.block.decl.GetNumResults(), be.block.decl.GetNumParams(), false);
|
||||
Construct(be.block.exprs, be.block.decl.GetNumResults(),
|
||||
be.block.decl.GetNumParams(), false);
|
||||
mc.EndBlock();
|
||||
InsertNode(NodeType::Expr, T, &be, 1);
|
||||
}
|
||||
@ -177,7 +185,7 @@ struct AST {
|
||||
auto& lt = *cast<LocalTeeExpr>(&e);
|
||||
Set(lt, true);
|
||||
if (value_stack_depth == 1) { // Tee is the only thing on there.
|
||||
Get(lt, true); // Now Set + Get instead.
|
||||
Get(lt, true); // Now Set + Get instead.
|
||||
} else {
|
||||
// Things are above us on the stack so the Tee can't be eliminated.
|
||||
// The Set makes this work as a Tee when consumed by a parent.
|
||||
@ -188,13 +196,16 @@ struct AST {
|
||||
auto ife = cast<IfExpr>(&e);
|
||||
value_stack_depth--; // Condition.
|
||||
mc.BeginBlock(LabelType::Block, ife->true_);
|
||||
Construct(ife->true_.exprs, ife->true_.decl.GetNumResults(), ife->true_.decl.GetNumParams(), false);
|
||||
Construct(ife->true_.exprs, ife->true_.decl.GetNumResults(),
|
||||
ife->true_.decl.GetNumParams(), false);
|
||||
if (!ife->false_.empty()) {
|
||||
Construct(ife->false_, ife->true_.decl.GetNumResults(), ife->true_.decl.GetNumParams(), false);
|
||||
Construct(ife->false_, ife->true_.decl.GetNumResults(),
|
||||
ife->true_.decl.GetNumParams(), false);
|
||||
}
|
||||
mc.EndBlock();
|
||||
value_stack_depth++; // Put Condition back.
|
||||
InsertNode(NodeType::Expr, ExprType::If, &e, ife->false_.empty() ? 2 : 3);
|
||||
InsertNode(NodeType::Expr, ExprType::If, &e,
|
||||
ife->false_.empty() ? 2 : 3);
|
||||
return;
|
||||
}
|
||||
case ExprType::Block: {
|
||||
@ -215,6 +226,11 @@ struct AST {
|
||||
mc.GetLabel(cast<BrIfExpr>(&e)->var)->label_type;
|
||||
return;
|
||||
}
|
||||
case ExprType::BrTable: {
|
||||
InsertNode(NodeType::Expr, ExprType::BrTable, &e, 1).u.lt =
|
||||
mc.GetLabel(cast<BrTableExpr>(&e)->default_target)->label_type;
|
||||
return;
|
||||
}
|
||||
default: {
|
||||
InsertNode(NodeType::Expr, e.type(), &e, arity.nargs);
|
||||
return;
|
||||
@ -222,7 +238,10 @@ struct AST {
|
||||
}
|
||||
}
|
||||
|
||||
void Construct(const ExprList& es, Index nresults, Index nparams, bool is_function_body) {
|
||||
void Construct(const ExprList& es,
|
||||
Index nresults,
|
||||
Index nparams,
|
||||
bool is_function_body) {
|
||||
block_stack.push_back(cur_block_id);
|
||||
cur_block_id = blocks_closed.size();
|
||||
blocks_closed.push_back(false);
|
||||
@ -234,8 +253,8 @@ struct AST {
|
||||
Construct(e);
|
||||
auto arity = mc.GetExprArity(e);
|
||||
value_stack_depth -= arity.nargs;
|
||||
value_stack_in_variables = std::min(value_stack_in_variables,
|
||||
value_stack_depth);
|
||||
value_stack_in_variables =
|
||||
std::min(value_stack_in_variables, value_stack_depth);
|
||||
unreachable = unreachable || arity.unreachable;
|
||||
assert(unreachable || value_stack_depth >= value_stack_depth_start);
|
||||
value_stack_depth += arity.nreturns;
|
||||
@ -256,21 +275,20 @@ struct AST {
|
||||
auto num_vars = value_stack_in_variables - value_stack_depth_start;
|
||||
auto num_vals = value_stack_depth - value_stack_in_variables;
|
||||
auto GenFlushVars = [&](int nargs) {
|
||||
auto& ftv = InsertNode(NodeType::FlushToVars, ExprType::Nop, nullptr,
|
||||
nargs);
|
||||
auto& ftv =
|
||||
InsertNode(NodeType::FlushToVars, ExprType::Nop, nullptr, nargs);
|
||||
ftv.u.var_start = flushed_vars;
|
||||
ftv.u.var_count = num_vals;
|
||||
};
|
||||
auto MoveStatementsBelowVars = [&](size_t amount) {
|
||||
std::rotate(exp_stack.end() - num_vars - amount,
|
||||
exp_stack.end() - amount,
|
||||
exp_stack.end());
|
||||
exp_stack.end() - amount, exp_stack.end());
|
||||
};
|
||||
auto GenFlushedVars = [&]() {
|
||||
// Re-generate these values as vars.
|
||||
for (int i = 0; i < num_vals; i++) {
|
||||
auto& fv = InsertNode(NodeType::FlushedVar, ExprType::Nop, nullptr,
|
||||
0);
|
||||
auto& fv =
|
||||
InsertNode(NodeType::FlushedVar, ExprType::Nop, nullptr, 0);
|
||||
fv.u.var_start = flushed_vars++;
|
||||
fv.u.var_count = 1;
|
||||
}
|
||||
@ -316,8 +334,8 @@ struct AST {
|
||||
// Special optimisation: for constant instructions, we can mark these
|
||||
// as if they were variables, so they can be re-ordered for free with
|
||||
// the above code, without needing new variables!
|
||||
// TODO: this would be nice to also do for get_local and maybe others,
|
||||
// though that needs a way to ensure there's no set_local in between
|
||||
// TODO: this would be nice to also do for local.get and maybe others,
|
||||
// though that needs a way to ensure there's no local.set in between
|
||||
// when they get lifted, so complicates matters a bit.
|
||||
if (e.type() == ExprType::Const &&
|
||||
value_stack_in_variables == value_stack_depth - 1) {
|
||||
@ -325,9 +343,8 @@ struct AST {
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(unreachable ||
|
||||
value_stack_depth - value_stack_depth_start ==
|
||||
static_cast<int>(nresults));
|
||||
assert(unreachable || value_stack_depth - value_stack_depth_start ==
|
||||
static_cast<int>(nresults));
|
||||
// Undo any changes to value_stack_depth, since parent takes care of arity
|
||||
// changes.
|
||||
value_stack_depth = value_stack_depth_start;
|
||||
@ -371,9 +388,12 @@ struct AST {
|
||||
ModuleContext& mc;
|
||||
std::vector<Node> exp_stack;
|
||||
std::vector<Node> predecls;
|
||||
const Func *f;
|
||||
const Func* f;
|
||||
int value_stack_depth = 0;
|
||||
struct Variable { size_t block_id; bool defined; };
|
||||
struct Variable {
|
||||
size_t block_id;
|
||||
bool defined;
|
||||
};
|
||||
std::map<std::string, Variable> vars_defined;
|
||||
Index flushed_vars = 0;
|
||||
size_t cur_block_id = 0;
|
@ -17,14 +17,15 @@
|
||||
#ifndef WABT_DECOMPILER_LS_H_
|
||||
#define WABT_DECOMPILER_LS_H_
|
||||
|
||||
#include "src/decompiler-ast.h"
|
||||
#include "wabt/decompiler-ast.h"
|
||||
#include "wabt/string-util.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
namespace wabt {
|
||||
|
||||
// Names starting with "u" are unsigned, the rest are "signed or doesn't matter"
|
||||
inline const char *GetDecompTypeName(Type t) {
|
||||
inline const char* GetDecompTypeName(Type t) {
|
||||
switch (t) {
|
||||
case Type::I8: return "byte";
|
||||
case Type::I8U: return "ubyte";
|
||||
@ -51,7 +52,7 @@ inline Type GetMemoryType(Type operand_type, Opcode opc) {
|
||||
// from context, if not, we should probably represent that as a cast around
|
||||
// the access, since it should not be part of the field type.
|
||||
if (operand_type == Type::I32 || operand_type == Type::I64) {
|
||||
auto name = string_view(opc.GetName());
|
||||
auto name = std::string_view(opc.GetName());
|
||||
// FIXME: change into a new column in opcode.def instead?
|
||||
auto is_unsigned = name.substr(name.size() - 2) == "_u";
|
||||
switch (opc.GetMemorySize()) {
|
||||
@ -84,18 +85,20 @@ struct LoadStoreTracking {
|
||||
};
|
||||
|
||||
void Track(const Node& n) {
|
||||
for (auto& c : n.children) Track(c);
|
||||
for (auto& c : n.children) {
|
||||
Track(c);
|
||||
}
|
||||
switch (n.etype) {
|
||||
case ExprType::Load: {
|
||||
auto& le = *cast<LoadExpr>(n.e);
|
||||
LoadStore(le.offset, le.opcode, le.opcode.GetResultType(),
|
||||
le.align, n.children[0]);
|
||||
LoadStore(le.offset, le.opcode, le.opcode.GetResultType(), le.align,
|
||||
n.children[0]);
|
||||
break;
|
||||
}
|
||||
case ExprType::Store: {
|
||||
auto& se = *cast<StoreExpr>(n.e);
|
||||
LoadStore(se.offset, se.opcode, se.opcode.GetParamType2(),
|
||||
se.align, n.children[0]);
|
||||
LoadStore(se.offset, se.opcode, se.opcode.GetParamType2(), se.align,
|
||||
n.children[0]);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -117,7 +120,10 @@ struct LoadStoreTracking {
|
||||
}
|
||||
}
|
||||
|
||||
void LoadStore(uint64_t offset, Opcode opc, Type type, Address align,
|
||||
void LoadStore(uint64_t offset,
|
||||
Opcode opc,
|
||||
Type type,
|
||||
Address align,
|
||||
const Node& addr_exp) {
|
||||
auto byte_size = opc.GetMemorySize();
|
||||
type = GetMemoryType(type, opc);
|
||||
@ -131,10 +137,8 @@ struct LoadStoreTracking {
|
||||
auto& access = var.accesses[offset];
|
||||
// Check if previous access at this offset (if any) is of same size
|
||||
// and type (see Checklayouts below).
|
||||
if (access.byte_size &&
|
||||
((access.byte_size != byte_size) ||
|
||||
(access.type != type) ||
|
||||
(access.align != align)))
|
||||
if (access.byte_size && ((access.byte_size != byte_size) ||
|
||||
(access.type != type) || (access.align != align)))
|
||||
access.is_uniform = false;
|
||||
// Also exclude weird alignment accesses from structs.
|
||||
if (!opc.IsNaturallyAligned(align))
|
||||
@ -202,9 +206,7 @@ struct LoadStoreTracking {
|
||||
}
|
||||
|
||||
std::string GenAlign(Address align, Opcode opc) const {
|
||||
return opc.IsNaturallyAligned(align)
|
||||
? ""
|
||||
: cat("@", std::to_string(align));
|
||||
return opc.IsNaturallyAligned(align) ? "" : cat("@", std::to_string(align));
|
||||
}
|
||||
|
||||
std::string GenTypeDecl(const std::string& name) const {
|
||||
@ -215,7 +217,9 @@ struct LoadStoreTracking {
|
||||
if (it->second.struct_layout) {
|
||||
std::string s = "{ ";
|
||||
for (auto& access : it->second.accesses) {
|
||||
if (access.second.idx) s += ", ";
|
||||
if (access.second.idx) {
|
||||
s += ", ";
|
||||
}
|
||||
s += IdxToName(access.second.idx);
|
||||
s += ':';
|
||||
s += GetDecompTypeName(access.second.type);
|
||||
@ -243,7 +247,7 @@ struct LoadStoreTracking {
|
||||
}
|
||||
if (it->second.struct_layout) {
|
||||
auto ait = it->second.accesses.find(offset);
|
||||
assert (ait != it->second.accesses.end());
|
||||
assert(ait != it->second.accesses.end());
|
||||
return IdxToName(ait->second.idx);
|
||||
}
|
||||
// Not a struct, see if it is a typed pointer.
|
||||
@ -253,9 +257,7 @@ struct LoadStoreTracking {
|
||||
return "";
|
||||
}
|
||||
|
||||
void Clear() {
|
||||
vars.clear();
|
||||
}
|
||||
void Clear() { vars.clear(); }
|
||||
|
||||
std::map<std::string, LSVar> vars;
|
||||
};
|
@ -17,15 +17,16 @@
|
||||
#ifndef WABT_DECOMPILER_NAMING_H_
|
||||
#define WABT_DECOMPILER_NAMING_H_
|
||||
|
||||
#include "src/decompiler-ast.h"
|
||||
#include "wabt/decompiler-ast.h"
|
||||
|
||||
#include <set>
|
||||
|
||||
namespace wabt {
|
||||
|
||||
inline void RenameToIdentifier(std::string& name, Index i,
|
||||
inline void RenameToIdentifier(std::string& name,
|
||||
Index i,
|
||||
BindingHash& bh,
|
||||
const std::set<string_view>* filter) {
|
||||
const std::set<std::string_view>* filter) {
|
||||
// Filter out non-identifier characters, and try to reduce the size of
|
||||
// gigantic C++ signature names.
|
||||
std::string s;
|
||||
@ -66,7 +67,8 @@ inline void RenameToIdentifier(std::string& name, Index i,
|
||||
word_end--;
|
||||
}
|
||||
assert(word_end > word_start);
|
||||
auto word = string_view(s.c_str() + word_start, word_end - word_start);
|
||||
auto word =
|
||||
std::string_view(s.c_str() + word_start, word_end - word_start);
|
||||
if (filter->find(word) != filter->end()) {
|
||||
s.resize(word_start);
|
||||
}
|
||||
@ -83,6 +85,9 @@ inline void RenameToIdentifier(std::string& name, Index i,
|
||||
if (s.size() > max_identifier_length) {
|
||||
s.resize(max_identifier_length);
|
||||
}
|
||||
if (s.empty()) {
|
||||
s = "__empty";
|
||||
}
|
||||
// Remove original binding first, such that it doesn't match with our
|
||||
// new name.
|
||||
bh.erase(name);
|
||||
@ -103,9 +108,10 @@ inline void RenameToIdentifier(std::string& name, Index i,
|
||||
bh.emplace(s, Binding(i));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void RenameToIdentifiers(std::vector<T*>& things, BindingHash& bh,
|
||||
const std::set<string_view>* filter) {
|
||||
template <typename T>
|
||||
void RenameToIdentifiers(std::vector<T*>& things,
|
||||
BindingHash& bh,
|
||||
const std::set<std::string_view>* filter) {
|
||||
Index i = 0;
|
||||
for (auto thing : things) {
|
||||
RenameToIdentifier(thing->name, i++, bh, filter);
|
||||
@ -172,22 +178,10 @@ void RenameAll(Module& module) {
|
||||
// We also filter common C++ keywords/STL idents that make for huge
|
||||
// identifiers.
|
||||
// FIXME: this can obviously give bad results if the input is not C++..
|
||||
std::set<string_view> filter = {
|
||||
{ "const" },
|
||||
{ "std" },
|
||||
{ "allocator" },
|
||||
{ "char" },
|
||||
{ "basic" },
|
||||
{ "traits" },
|
||||
{ "wchar" },
|
||||
{ "t" },
|
||||
{ "void" },
|
||||
{ "int" },
|
||||
{ "unsigned" },
|
||||
{ "2" },
|
||||
{ "cxxabiv1" },
|
||||
{ "short" },
|
||||
{ "4096ul" },
|
||||
std::set<std::string_view> filter = {
|
||||
{"const"}, {"std"}, {"allocator"}, {"char"}, {"basic"},
|
||||
{"traits"}, {"wchar"}, {"t"}, {"void"}, {"int"},
|
||||
{"unsigned"}, {"2"}, {"cxxabiv1"}, {"short"}, {"4096ul"},
|
||||
};
|
||||
RenameToIdentifiers(module.funcs, module.func_bindings, &filter);
|
||||
// Also do this for some other kinds of names, but without the keyword
|
@ -17,15 +17,14 @@
|
||||
#ifndef WABT_DECOMPILER_H_
|
||||
#define WABT_DECOMPILER_H_
|
||||
|
||||
#include "src/common.h"
|
||||
#include "wabt/common.h"
|
||||
|
||||
namespace wabt {
|
||||
|
||||
struct Module;
|
||||
class Stream;
|
||||
|
||||
struct DecompileOptions {
|
||||
};
|
||||
struct DecompileOptions {};
|
||||
|
||||
void RenameAll(Module&);
|
||||
|
@ -18,12 +18,12 @@
|
||||
#define WABT_ERROR_FORMATTER_H_
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "src/color.h"
|
||||
#include "src/error.h"
|
||||
#include "src/lexer-source-line-finder.h"
|
||||
#include "wabt/color.h"
|
||||
#include "wabt/error.h"
|
||||
#include "wabt/lexer-source-line-finder.h"
|
||||
|
||||
namespace wabt {
|
||||
|
@ -18,10 +18,10 @@
|
||||
#define WABT_ERROR_H_
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include "src/common.h"
|
||||
#include "src/string-view.h"
|
||||
#include "wabt/common.h"
|
||||
|
||||
namespace wabt {
|
||||
|
||||
@ -30,7 +30,7 @@ enum class ErrorLevel {
|
||||
Error,
|
||||
};
|
||||
|
||||
static WABT_INLINE const char* GetErrorLevelName(ErrorLevel error_level) {
|
||||
static inline const char* GetErrorLevelName(ErrorLevel error_level) {
|
||||
switch (error_level) {
|
||||
case ErrorLevel::Warning:
|
||||
return "warning";
|
||||
@ -43,8 +43,8 @@ static WABT_INLINE const char* GetErrorLevelName(ErrorLevel error_level) {
|
||||
class Error {
|
||||
public:
|
||||
Error() : error_level(ErrorLevel::Error) {}
|
||||
Error(ErrorLevel error_level, Location loc, string_view message)
|
||||
: error_level(error_level), loc(loc), message(message.to_string()) {}
|
||||
Error(ErrorLevel error_level, Location loc, std::string_view message)
|
||||
: error_level(error_level), loc(loc), message(message) {}
|
||||
|
||||
ErrorLevel error_level;
|
||||
Location loc;
|
@ -17,8 +17,8 @@
|
||||
#ifndef WABT_EXPR_VISITOR_H_
|
||||
#define WABT_EXPR_VISITOR_H_
|
||||
|
||||
#include "src/common.h"
|
||||
#include "src/ir.h"
|
||||
#include "wabt/common.h"
|
||||
#include "wabt/ir.h"
|
||||
|
||||
namespace wabt {
|
||||
|
||||
@ -76,6 +76,7 @@ class ExprVisitor::Delegate {
|
||||
virtual Result OnCallExpr(CallExpr*) = 0;
|
||||
virtual Result OnCallIndirectExpr(CallIndirectExpr*) = 0;
|
||||
virtual Result OnCallRefExpr(CallRefExpr*) = 0;
|
||||
virtual Result OnCodeMetadataExpr(CodeMetadataExpr*) = 0;
|
||||
virtual Result OnCompareExpr(CompareExpr*) = 0;
|
||||
virtual Result OnConstExpr(ConstExpr*) = 0;
|
||||
virtual Result OnConvertExpr(ConvertExpr*) = 0;
|
||||
@ -149,6 +150,7 @@ class ExprVisitor::DelegateNop : public ExprVisitor::Delegate {
|
||||
Result OnCallExpr(CallExpr*) override { return Result::Ok; }
|
||||
Result OnCallIndirectExpr(CallIndirectExpr*) override { return Result::Ok; }
|
||||
Result OnCallRefExpr(CallRefExpr*) override { return Result::Ok; }
|
||||
Result OnCodeMetadataExpr(CodeMetadataExpr*) override { return Result::Ok; }
|
||||
Result OnCompareExpr(CompareExpr*) override { return Result::Ok; }
|
||||
Result OnConstExpr(ConstExpr*) override { return Result::Ok; }
|
||||
Result OnConvertExpr(ConvertExpr*) override { return Result::Ok; }
|
@ -26,13 +26,17 @@ WABT_FEATURE(exceptions, "exceptions", false, "Experimen
|
||||
WABT_FEATURE(mutable_globals, "mutable-globals", true, "Import/export mutable globals")
|
||||
WABT_FEATURE(sat_float_to_int, "saturating-float-to-int", true, "Saturating float-to-int operators")
|
||||
WABT_FEATURE(sign_extension, "sign-extension", true, "Sign-extension operators")
|
||||
WABT_FEATURE(simd, "simd", true, "SIMD support")
|
||||
WABT_FEATURE(simd, "simd", true, "SIMD support")
|
||||
WABT_FEATURE(threads, "threads", false, "Threading support")
|
||||
WABT_FEATURE(function_references, "function-references", false, "Typed function references")
|
||||
WABT_FEATURE(multi_value, "multi-value", true, "Multi-value")
|
||||
WABT_FEATURE(tail_call, "tail-call", false, "Tail-call support")
|
||||
WABT_FEATURE(bulk_memory, "bulk-memory", false, "Bulk-memory operations")
|
||||
WABT_FEATURE(reference_types, "reference-types", false, "Reference types (externref)")
|
||||
WABT_FEATURE(bulk_memory, "bulk-memory", true, "Bulk-memory operations")
|
||||
WABT_FEATURE(reference_types, "reference-types", true, "Reference types (externref)")
|
||||
WABT_FEATURE(annotations, "annotations", false, "Custom annotation syntax")
|
||||
WABT_FEATURE(code_metadata, "code-metadata", false, "Code metadata")
|
||||
WABT_FEATURE(gc, "gc", false, "Garbage collection")
|
||||
WABT_FEATURE(memory64, "memory64", false, "64-bit memory")
|
||||
WABT_FEATURE(multi_memory, "multi-memory", false, "Multi-memory")
|
||||
WABT_FEATURE(extended_const, "extended-const", false, "Extended constant expressions")
|
||||
WABT_FEATURE(relaxed_simd, "relaxed-simd", false, "Relaxed SIMD")
|
@ -17,7 +17,7 @@
|
||||
#ifndef WABT_FEATURE_H_
|
||||
#define WABT_FEATURE_H_
|
||||
|
||||
#include "src/common.h"
|
||||
#include "wabt/common.h"
|
||||
|
||||
namespace wabt {
|
||||
|
||||
@ -29,7 +29,7 @@ class Features {
|
||||
|
||||
void EnableAll() {
|
||||
#define WABT_FEATURE(variable, flag, default_, help) enable_##variable();
|
||||
#include "src/feature.def"
|
||||
#include "wabt/feature.def"
|
||||
#undef WABT_FEATURE
|
||||
}
|
||||
|
||||
@ -41,7 +41,7 @@ class Features {
|
||||
variable##_enabled_ = value; \
|
||||
UpdateDependencies(); \
|
||||
}
|
||||
#include "src/feature.def"
|
||||
#include "wabt/feature.def"
|
||||
#undef WABT_FEATURE
|
||||
|
||||
private:
|
||||
@ -49,7 +49,7 @@ class Features {
|
||||
|
||||
#define WABT_FEATURE(variable, flag, default_, help) \
|
||||
bool variable##_enabled_ = default_;
|
||||
#include "src/feature.def"
|
||||
#include "wabt/feature.def"
|
||||
#undef WABT_FEATURE
|
||||
};
|
||||
|
@ -17,7 +17,7 @@
|
||||
#ifndef WABT_FILENAMES_H_
|
||||
#define WABT_FILENAMES_H_
|
||||
|
||||
#include "src/common.h"
|
||||
#include "wabt/common.h"
|
||||
|
||||
namespace wabt {
|
||||
|
||||
@ -29,7 +29,7 @@ extern const char* kWatExtension;
|
||||
// "foo.txt", => ".txt"
|
||||
// "foo" => ""
|
||||
// "/foo/bar/foo.wasm" => ".wasm"
|
||||
string_view GetExtension(string_view filename);
|
||||
std::string_view GetExtension(std::string_view filename);
|
||||
|
||||
// Strip extension, e.g.:
|
||||
//
|
||||
@ -37,14 +37,14 @@ string_view GetExtension(string_view filename);
|
||||
// "foo.bar" => "foo"
|
||||
// "/path/to/foo.bar" => "/path/to/foo"
|
||||
// "\\path\\to\\foo.bar" => "\\path\\to\\foo"
|
||||
string_view StripExtension(string_view s);
|
||||
std::string_view StripExtension(std::string_view s);
|
||||
|
||||
// Strip everything up to and including the last slash, e.g.:
|
||||
//
|
||||
// "/foo/bar/baz", => "baz"
|
||||
// "/usr/local/include/stdio.h", => "stdio.h"
|
||||
// "foo.bar", => "foo.bar"
|
||||
string_view GetBasename(string_view filename);
|
||||
std::string_view GetBasename(std::string_view filename);
|
||||
|
||||
} // namespace wabt
|
||||
|
@ -17,7 +17,7 @@
|
||||
#ifndef WABT_GENERATE_NAMES_H_
|
||||
#define WABT_GENERATE_NAMES_H_
|
||||
|
||||
#include "src/common.h"
|
||||
#include "wabt/common.h"
|
||||
|
||||
namespace wabt {
|
||||
|
@ -21,8 +21,6 @@
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
|
||||
#include "src/make-unique.h"
|
||||
|
||||
// This uses a similar interface as std::list, but is missing the following
|
||||
// features:
|
||||
//
|
||||
@ -53,15 +51,15 @@ template <typename T>
|
||||
class intrusive_list {
|
||||
public:
|
||||
// types:
|
||||
typedef T value_type;
|
||||
typedef value_type& reference;
|
||||
typedef const value_type& const_reference;
|
||||
using value_type = T;
|
||||
using reference = value_type&;
|
||||
using const_reference = const value_type&;
|
||||
class iterator;
|
||||
class const_iterator;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef std::reverse_iterator<iterator> reverse_iterator;
|
||||
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
|
||||
using size_type = std::size_t;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||
|
||||
// construct/copy/destroy:
|
||||
intrusive_list();
|
||||
@ -142,11 +140,11 @@ class intrusive_list {
|
||||
template <typename T>
|
||||
class intrusive_list<T>::iterator {
|
||||
public:
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef std::bidirectional_iterator_tag iterator_category;
|
||||
typedef T value_type;
|
||||
typedef T* pointer;
|
||||
typedef T& reference;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using iterator_category = std::bidirectional_iterator_tag;
|
||||
using value_type = T;
|
||||
using pointer = T*;
|
||||
using reference = T&;
|
||||
|
||||
iterator(const intrusive_list<T>& list, T* node)
|
||||
: list_(&list), node_(node) {}
|
||||
@ -205,11 +203,11 @@ class intrusive_list<T>::iterator {
|
||||
template <typename T>
|
||||
class intrusive_list<T>::const_iterator {
|
||||
public:
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef std::bidirectional_iterator_tag iterator_category;
|
||||
typedef T value_type;
|
||||
typedef const T* pointer;
|
||||
typedef const T& reference;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using iterator_category = std::bidirectional_iterator_tag;
|
||||
using value_type = T;
|
||||
using pointer = const T*;
|
||||
using reference = const T&;
|
||||
|
||||
const_iterator(const intrusive_list<T>& list, T* node)
|
||||
: list_(&list), node_(node) {}
|
||||
@ -320,8 +318,8 @@ inline typename intrusive_list<T>::iterator intrusive_list<T>::end() noexcept {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline typename intrusive_list<T>::const_iterator intrusive_list<T>::end() const
|
||||
noexcept {
|
||||
inline typename intrusive_list<T>::const_iterator intrusive_list<T>::end()
|
||||
const noexcept {
|
||||
return const_iterator(*this, nullptr);
|
||||
}
|
||||
|
||||
@ -374,8 +372,8 @@ intrusive_list<T>::crend() const noexcept {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline typename intrusive_list<T>::size_type intrusive_list<T>::size() const
|
||||
noexcept {
|
||||
inline typename intrusive_list<T>::size_type intrusive_list<T>::size()
|
||||
const noexcept {
|
||||
return size_;
|
||||
}
|
||||
|
||||
@ -413,13 +411,13 @@ inline typename intrusive_list<T>::const_reference intrusive_list<T>::back()
|
||||
template <typename T>
|
||||
template <class... Args>
|
||||
inline void intrusive_list<T>::emplace_front(Args&&... args) {
|
||||
push_front(MakeUnique<T>(std::forward<Args>(args)...));
|
||||
push_front(std::make_unique<T>(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
template <class... Args>
|
||||
inline void intrusive_list<T>::emplace_back(Args&&... args) {
|
||||
push_back(MakeUnique<T>(std::forward<Args>(args)...));
|
||||
push_back(std::make_unique<T>(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@ -439,7 +437,7 @@ inline void intrusive_list<T>::push_front(std::unique_ptr<T> node) {
|
||||
|
||||
template <typename T>
|
||||
inline void intrusive_list<T>::push_front(T&& node) {
|
||||
push_front(MakeUnique<T>(std::move(node)));
|
||||
push_front(std::make_unique<T>(std::move(node)));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@ -459,7 +457,7 @@ inline void intrusive_list<T>::push_back(std::unique_ptr<T> node) {
|
||||
|
||||
template <typename T>
|
||||
inline void intrusive_list<T>::push_back(T&& node) {
|
||||
push_back(MakeUnique<T>(std::move(node)));
|
||||
push_back(std::make_unique<T>(std::move(node)));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@ -507,7 +505,7 @@ template <class... Args>
|
||||
inline typename intrusive_list<T>::iterator intrusive_list<T>::emplace(
|
||||
iterator pos,
|
||||
Args&&... args) {
|
||||
return insert(pos, MakeUnique<T>(std::forward<Args>(args)...));
|
||||
return insert(pos, std::make_unique<T>(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@ -539,7 +537,7 @@ template <typename T>
|
||||
inline typename intrusive_list<T>::iterator intrusive_list<T>::insert(
|
||||
iterator pos,
|
||||
T&& node) {
|
||||
return insert(pos, MakeUnique<T>(std::move(node)));
|
||||
return insert(pos, std::make_unique<T>(std::move(node)));
|
||||
}
|
||||
|
||||
template <typename T>
|
@ -17,8 +17,8 @@
|
||||
#ifndef WABT_IR_UTIL_H_
|
||||
#define WABT_IR_UTIL_H_
|
||||
|
||||
#include "src/common.h"
|
||||
#include "src/ir.h"
|
||||
#include "wabt/common.h"
|
||||
#include "wabt/ir.h"
|
||||
|
||||
namespace wabt {
|
||||
|
||||
@ -39,7 +39,7 @@ struct Label {
|
||||
};
|
||||
|
||||
struct ModuleContext {
|
||||
ModuleContext(const Module &module) : module(module) {}
|
||||
ModuleContext(const Module& module) : module(module) {}
|
||||
|
||||
Index GetLabelStackSize() const { return label_stack_.size(); }
|
||||
const Label* GetLabel(const Var& var) const;
|
||||
@ -61,11 +61,12 @@ struct ModuleContext {
|
||||
Index nreturns;
|
||||
bool unreachable;
|
||||
Arities(Index na, Index nr, bool ur = false)
|
||||
: nargs(na), nreturns(nr), unreachable(ur) {}
|
||||
: nargs(na), nreturns(nr), unreachable(ur) {}
|
||||
};
|
||||
Arities GetExprArity(const Expr& expr) const;
|
||||
|
||||
const Module &module;
|
||||
const Module& module;
|
||||
|
||||
private:
|
||||
const Func* current_func_ = nullptr;
|
||||
std::vector<Label> label_stack_;
|
@ -22,14 +22,14 @@
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#include "src/binding-hash.h"
|
||||
#include "src/common.h"
|
||||
#include "src/intrusive-list.h"
|
||||
#include "src/opcode.h"
|
||||
#include "src/string-view.h"
|
||||
#include "wabt/binding-hash.h"
|
||||
#include "wabt/common.h"
|
||||
#include "wabt/intrusive-list.h"
|
||||
#include "wabt/opcode.h"
|
||||
|
||||
namespace wabt {
|
||||
|
||||
@ -41,8 +41,9 @@ enum class VarType {
|
||||
};
|
||||
|
||||
struct Var {
|
||||
explicit Var(Index index = kInvalidIndex, const Location& loc = Location());
|
||||
explicit Var(string_view name, const Location& loc = Location());
|
||||
explicit Var();
|
||||
explicit Var(Index index, const Location& loc);
|
||||
explicit Var(std::string_view name, const Location& loc);
|
||||
Var(Var&&);
|
||||
Var(const Var&);
|
||||
Var& operator=(const Var&);
|
||||
@ -53,12 +54,18 @@ struct Var {
|
||||
bool is_index() const { return type_ == VarType::Index; }
|
||||
bool is_name() const { return type_ == VarType::Name; }
|
||||
|
||||
Index index() const { assert(is_index()); return index_; }
|
||||
const std::string& name() const { assert(is_name()); return name_; }
|
||||
Index index() const {
|
||||
assert(is_index());
|
||||
return index_;
|
||||
}
|
||||
const std::string& name() const {
|
||||
assert(is_name());
|
||||
return name_;
|
||||
}
|
||||
|
||||
void set_index(Index);
|
||||
void set_name(std::string&&);
|
||||
void set_name(string_view);
|
||||
void set_name(std::string_view);
|
||||
|
||||
Location loc;
|
||||
|
||||
@ -71,7 +78,7 @@ struct Var {
|
||||
std::string name_;
|
||||
};
|
||||
};
|
||||
typedef std::vector<Var> VarVector;
|
||||
using VarVector = std::vector<Var>;
|
||||
|
||||
struct Const {
|
||||
static constexpr uintptr_t kRefNullBits = ~uintptr_t(0);
|
||||
@ -95,7 +102,10 @@ struct Const {
|
||||
}
|
||||
|
||||
Type type() const { return type_; }
|
||||
Type lane_type() const { assert(type_ == Type::V128); return lane_type_; }
|
||||
Type lane_type() const {
|
||||
assert(type_ == Type::V128);
|
||||
return lane_type_;
|
||||
}
|
||||
|
||||
int lane_count() const {
|
||||
switch (lane_type()) {
|
||||
@ -117,7 +127,9 @@ struct Const {
|
||||
v128 vec128() const { return data_; }
|
||||
|
||||
template <typename T>
|
||||
T v128_lane(int lane) const { return data_.To<T>(lane); }
|
||||
T v128_lane(int lane) const {
|
||||
return data_.To<T>(lane);
|
||||
}
|
||||
|
||||
void set_u32(uint32_t x) { From(Type::I32, x); }
|
||||
void set_u64(uint64_t x) { From(Type::I64, x); }
|
||||
@ -132,11 +144,17 @@ struct Const {
|
||||
void set_v128_f64(int lane, uint64_t x) { set_v128_lane(lane, Type::F64, x); }
|
||||
|
||||
// Only used for expectations. (e.g. wast assertions)
|
||||
void set_f32(ExpectedNan nan) { set_f32(0); set_expected_nan(0, nan); }
|
||||
void set_f64(ExpectedNan nan) { set_f64(0); set_expected_nan(0, nan); }
|
||||
void set_funcref() { From<uintptr_t>(Type::FuncRef, 0); }
|
||||
void set_f32(ExpectedNan nan) {
|
||||
set_f32(0);
|
||||
set_expected_nan(0, nan);
|
||||
}
|
||||
void set_f64(ExpectedNan nan) {
|
||||
set_f64(0);
|
||||
set_expected_nan(0, nan);
|
||||
}
|
||||
void set_funcref() { From<uintptr_t>(Type::FuncRef, 0); }
|
||||
void set_externref(uintptr_t x) { From(Type::ExternRef, x); }
|
||||
void set_null(Type type) { From<uintptr_t>(type, kRefNullBits); }
|
||||
void set_null(Type type) { From<uintptr_t>(type, kRefNullBits); }
|
||||
|
||||
bool is_expected_nan(int lane = 0) const {
|
||||
return expected_nan(lane) != ExpectedNan::None;
|
||||
@ -178,16 +196,71 @@ struct Const {
|
||||
}
|
||||
|
||||
Type type_;
|
||||
Type lane_type_; // Only valid if type_ == Type::V128.
|
||||
Type lane_type_; // Only valid if type_ == Type::V128.
|
||||
v128 data_;
|
||||
ExpectedNan nan_[4];
|
||||
};
|
||||
typedef std::vector<Const> ConstVector;
|
||||
using ConstVector = std::vector<Const>;
|
||||
|
||||
enum class ExpectationType {
|
||||
Values,
|
||||
Either,
|
||||
};
|
||||
|
||||
class Expectation {
|
||||
public:
|
||||
Expectation() = delete;
|
||||
virtual ~Expectation() = default;
|
||||
ExpectationType type() const { return type_; }
|
||||
|
||||
Location loc;
|
||||
|
||||
ConstVector expected;
|
||||
|
||||
protected:
|
||||
explicit Expectation(ExpectationType type, const Location& loc = Location())
|
||||
: loc(loc), type_(type) {}
|
||||
|
||||
private:
|
||||
ExpectationType type_;
|
||||
};
|
||||
|
||||
template <ExpectationType TypeEnum>
|
||||
class ExpectationMixin : public Expectation {
|
||||
public:
|
||||
static bool classof(const Expectation* expectation) {
|
||||
return expectation->type() == TypeEnum;
|
||||
}
|
||||
|
||||
explicit ExpectationMixin(const Location& loc = Location())
|
||||
: Expectation(TypeEnum, loc) {}
|
||||
};
|
||||
|
||||
class ValueExpectation : public ExpectationMixin<ExpectationType::Values> {
|
||||
public:
|
||||
explicit ValueExpectation(const Location& loc = Location())
|
||||
: ExpectationMixin<ExpectationType::Values>(loc) {}
|
||||
};
|
||||
|
||||
struct EitherExpectation : public ExpectationMixin<ExpectationType::Either> {
|
||||
public:
|
||||
explicit EitherExpectation(const Location& loc = Location())
|
||||
: ExpectationMixin<ExpectationType::Either>(loc) {}
|
||||
};
|
||||
|
||||
typedef std::unique_ptr<Expectation> ExpectationPtr;
|
||||
|
||||
struct FuncSignature {
|
||||
TypeVector param_types;
|
||||
TypeVector result_types;
|
||||
|
||||
// Some types can have names, for example (ref $foo) has type $foo.
|
||||
// So to use this type we need to translate its name into
|
||||
// a proper index from the module type section.
|
||||
// This is the mapping from parameter/result index to its name.
|
||||
std::unordered_map<uint32_t, std::string> param_type_names;
|
||||
std::unordered_map<uint32_t, std::string> result_type_names;
|
||||
|
||||
Index GetNumParams() const { return param_types.size(); }
|
||||
Index GetNumResults() const { return result_types.size(); }
|
||||
Type GetParamType(Index index) const { return param_types[index]; }
|
||||
@ -215,9 +288,9 @@ class TypeEntry {
|
||||
|
||||
protected:
|
||||
explicit TypeEntry(TypeEntryKind kind,
|
||||
string_view name = string_view(),
|
||||
std::string_view name = std::string_view(),
|
||||
const Location& loc = Location())
|
||||
: loc(loc), name(name.to_string()), kind_(kind) {}
|
||||
: loc(loc), name(name), kind_(kind) {}
|
||||
|
||||
TypeEntryKind kind_;
|
||||
};
|
||||
@ -228,7 +301,7 @@ class FuncType : public TypeEntry {
|
||||
return entry->kind() == TypeEntryKind::Func;
|
||||
}
|
||||
|
||||
explicit FuncType(string_view name = string_view())
|
||||
explicit FuncType(std::string_view name = std::string_view())
|
||||
: TypeEntry(TypeEntryKind::Func, name) {}
|
||||
|
||||
Index GetNumParams() const { return sig.GetNumParams(); }
|
||||
@ -251,7 +324,7 @@ class StructType : public TypeEntry {
|
||||
return entry->kind() == TypeEntryKind::Struct;
|
||||
}
|
||||
|
||||
explicit StructType(string_view name = string_view())
|
||||
explicit StructType(std::string_view name = std::string_view())
|
||||
: TypeEntry(TypeEntryKind::Struct) {}
|
||||
|
||||
std::vector<Field> fields;
|
||||
@ -263,7 +336,7 @@ class ArrayType : public TypeEntry {
|
||||
return entry->kind() == TypeEntryKind::Array;
|
||||
}
|
||||
|
||||
explicit ArrayType(string_view name = string_view())
|
||||
explicit ArrayType(std::string_view name = std::string_view())
|
||||
: TypeEntry(TypeEntryKind::Array) {}
|
||||
|
||||
Field field;
|
||||
@ -296,6 +369,7 @@ enum class ExprType {
|
||||
Call,
|
||||
CallIndirect,
|
||||
CallRef,
|
||||
CodeMetadata,
|
||||
Compare,
|
||||
Const,
|
||||
Convert,
|
||||
@ -351,9 +425,9 @@ enum class ExprType {
|
||||
const char* GetExprTypeName(ExprType type);
|
||||
|
||||
class Expr;
|
||||
typedef intrusive_list<Expr> ExprList;
|
||||
using ExprList = intrusive_list<Expr>;
|
||||
|
||||
typedef FuncDeclaration BlockDeclaration;
|
||||
using BlockDeclaration = FuncDeclaration;
|
||||
|
||||
struct Block {
|
||||
Block() = default;
|
||||
@ -376,13 +450,9 @@ struct Catch {
|
||||
return var.is_index() && var.index() == kInvalidIndex;
|
||||
}
|
||||
};
|
||||
typedef std::vector<Catch> CatchVector;
|
||||
using CatchVector = std::vector<Catch>;
|
||||
|
||||
enum class TryKind {
|
||||
Plain,
|
||||
Catch,
|
||||
Delegate
|
||||
};
|
||||
enum class TryKind { Plain, Catch, Delegate };
|
||||
|
||||
class Expr : public intrusive_list_base<Expr> {
|
||||
public:
|
||||
@ -411,14 +481,39 @@ class ExprMixin : public Expr {
|
||||
explicit ExprMixin(const Location& loc = Location()) : Expr(TypeEnum, loc) {}
|
||||
};
|
||||
|
||||
typedef ExprMixin<ExprType::Drop> DropExpr;
|
||||
typedef ExprMixin<ExprType::MemoryGrow> MemoryGrowExpr;
|
||||
typedef ExprMixin<ExprType::MemorySize> MemorySizeExpr;
|
||||
typedef ExprMixin<ExprType::MemoryCopy> MemoryCopyExpr;
|
||||
typedef ExprMixin<ExprType::MemoryFill> MemoryFillExpr;
|
||||
typedef ExprMixin<ExprType::Nop> NopExpr;
|
||||
typedef ExprMixin<ExprType::Return> ReturnExpr;
|
||||
typedef ExprMixin<ExprType::Unreachable> UnreachableExpr;
|
||||
template <ExprType TypeEnum>
|
||||
class MemoryExpr : public ExprMixin<TypeEnum> {
|
||||
public:
|
||||
MemoryExpr(Var memidx, const Location& loc = Location())
|
||||
: ExprMixin<TypeEnum>(loc), memidx(memidx) {}
|
||||
|
||||
Var memidx;
|
||||
};
|
||||
|
||||
template <ExprType TypeEnum>
|
||||
class MemoryBinaryExpr : public ExprMixin<TypeEnum> {
|
||||
public:
|
||||
MemoryBinaryExpr(Var srcmemidx,
|
||||
Var destmemidx,
|
||||
const Location& loc = Location())
|
||||
: ExprMixin<TypeEnum>(loc),
|
||||
srcmemidx(srcmemidx),
|
||||
destmemidx(destmemidx) {}
|
||||
|
||||
Var srcmemidx;
|
||||
Var destmemidx;
|
||||
};
|
||||
|
||||
using DropExpr = ExprMixin<ExprType::Drop>;
|
||||
using NopExpr = ExprMixin<ExprType::Nop>;
|
||||
using ReturnExpr = ExprMixin<ExprType::Return>;
|
||||
using UnreachableExpr = ExprMixin<ExprType::Unreachable>;
|
||||
|
||||
using MemoryGrowExpr = MemoryExpr<ExprType::MemoryGrow>;
|
||||
using MemorySizeExpr = MemoryExpr<ExprType::MemorySize>;
|
||||
using MemoryFillExpr = MemoryExpr<ExprType::MemoryFill>;
|
||||
|
||||
using MemoryCopyExpr = MemoryBinaryExpr<ExprType::MemoryCopy>;
|
||||
|
||||
template <ExprType TypeEnum>
|
||||
class RefTypeExpr : public ExprMixin<TypeEnum> {
|
||||
@ -429,8 +524,8 @@ class RefTypeExpr : public ExprMixin<TypeEnum> {
|
||||
Type type;
|
||||
};
|
||||
|
||||
typedef RefTypeExpr<ExprType::RefNull> RefNullExpr;
|
||||
typedef ExprMixin<ExprType::RefIsNull> RefIsNullExpr;
|
||||
using RefNullExpr = RefTypeExpr<ExprType::RefNull>;
|
||||
using RefIsNullExpr = ExprMixin<ExprType::RefIsNull>;
|
||||
|
||||
template <ExprType TypeEnum>
|
||||
class OpcodeExpr : public ExprMixin<TypeEnum> {
|
||||
@ -441,11 +536,11 @@ class OpcodeExpr : public ExprMixin<TypeEnum> {
|
||||
Opcode opcode;
|
||||
};
|
||||
|
||||
typedef OpcodeExpr<ExprType::Binary> BinaryExpr;
|
||||
typedef OpcodeExpr<ExprType::Compare> CompareExpr;
|
||||
typedef OpcodeExpr<ExprType::Convert> ConvertExpr;
|
||||
typedef OpcodeExpr<ExprType::Unary> UnaryExpr;
|
||||
typedef OpcodeExpr<ExprType::Ternary> TernaryExpr;
|
||||
using BinaryExpr = OpcodeExpr<ExprType::Binary>;
|
||||
using CompareExpr = OpcodeExpr<ExprType::Compare>;
|
||||
using ConvertExpr = OpcodeExpr<ExprType::Convert>;
|
||||
using UnaryExpr = OpcodeExpr<ExprType::Unary>;
|
||||
using TernaryExpr = OpcodeExpr<ExprType::Ternary>;
|
||||
|
||||
class SimdLaneOpExpr : public ExprMixin<ExprType::SimdLaneOp> {
|
||||
public:
|
||||
@ -456,35 +551,41 @@ class SimdLaneOpExpr : public ExprMixin<ExprType::SimdLaneOp> {
|
||||
uint64_t val;
|
||||
};
|
||||
|
||||
class SimdLoadLaneExpr : public OpcodeExpr<ExprType::SimdLoadLane> {
|
||||
class SimdLoadLaneExpr : public MemoryExpr<ExprType::SimdLoadLane> {
|
||||
public:
|
||||
SimdLoadLaneExpr(Opcode opcode,
|
||||
Var memidx,
|
||||
Address align,
|
||||
Address offset,
|
||||
uint64_t val,
|
||||
const Location& loc = Location())
|
||||
: OpcodeExpr<ExprType::SimdLoadLane>(opcode, loc),
|
||||
: MemoryExpr<ExprType::SimdLoadLane>(memidx, loc),
|
||||
opcode(opcode),
|
||||
align(align),
|
||||
offset(offset),
|
||||
val(val) {}
|
||||
|
||||
Opcode opcode;
|
||||
Address align;
|
||||
Address offset;
|
||||
uint64_t val;
|
||||
};
|
||||
|
||||
class SimdStoreLaneExpr : public OpcodeExpr<ExprType::SimdStoreLane> {
|
||||
class SimdStoreLaneExpr : public MemoryExpr<ExprType::SimdStoreLane> {
|
||||
public:
|
||||
SimdStoreLaneExpr(Opcode opcode,
|
||||
Var memidx,
|
||||
Address align,
|
||||
Address offset,
|
||||
uint64_t val,
|
||||
const Location& loc = Location())
|
||||
: OpcodeExpr<ExprType::SimdStoreLane>(opcode, loc),
|
||||
: MemoryExpr<ExprType::SimdStoreLane>(memidx, loc),
|
||||
opcode(opcode),
|
||||
align(align),
|
||||
offset(offset),
|
||||
val(val) {}
|
||||
|
||||
Opcode opcode;
|
||||
Address align;
|
||||
Address offset;
|
||||
uint64_t val;
|
||||
@ -508,27 +609,37 @@ class VarExpr : public ExprMixin<TypeEnum> {
|
||||
Var var;
|
||||
};
|
||||
|
||||
typedef VarExpr<ExprType::Br> BrExpr;
|
||||
typedef VarExpr<ExprType::BrIf> BrIfExpr;
|
||||
typedef VarExpr<ExprType::Call> CallExpr;
|
||||
typedef VarExpr<ExprType::RefFunc> RefFuncExpr;
|
||||
typedef VarExpr<ExprType::GlobalGet> GlobalGetExpr;
|
||||
typedef VarExpr<ExprType::GlobalSet> GlobalSetExpr;
|
||||
typedef VarExpr<ExprType::LocalGet> LocalGetExpr;
|
||||
typedef VarExpr<ExprType::LocalSet> LocalSetExpr;
|
||||
typedef VarExpr<ExprType::LocalTee> LocalTeeExpr;
|
||||
typedef VarExpr<ExprType::ReturnCall> ReturnCallExpr;
|
||||
typedef VarExpr<ExprType::Throw> ThrowExpr;
|
||||
typedef VarExpr<ExprType::Rethrow> RethrowExpr;
|
||||
template <ExprType TypeEnum>
|
||||
class MemoryVarExpr : public MemoryExpr<TypeEnum> {
|
||||
public:
|
||||
MemoryVarExpr(const Var& var, Var memidx, const Location& loc = Location())
|
||||
: MemoryExpr<TypeEnum>(memidx, loc), var(var) {}
|
||||
|
||||
typedef VarExpr<ExprType::MemoryInit> MemoryInitExpr;
|
||||
typedef VarExpr<ExprType::DataDrop> DataDropExpr;
|
||||
typedef VarExpr<ExprType::ElemDrop> ElemDropExpr;
|
||||
typedef VarExpr<ExprType::TableGet> TableGetExpr;
|
||||
typedef VarExpr<ExprType::TableSet> TableSetExpr;
|
||||
typedef VarExpr<ExprType::TableGrow> TableGrowExpr;
|
||||
typedef VarExpr<ExprType::TableSize> TableSizeExpr;
|
||||
typedef VarExpr<ExprType::TableFill> TableFillExpr;
|
||||
Var var;
|
||||
};
|
||||
|
||||
using BrExpr = VarExpr<ExprType::Br>;
|
||||
using BrIfExpr = VarExpr<ExprType::BrIf>;
|
||||
using CallExpr = VarExpr<ExprType::Call>;
|
||||
using RefFuncExpr = VarExpr<ExprType::RefFunc>;
|
||||
using GlobalGetExpr = VarExpr<ExprType::GlobalGet>;
|
||||
using GlobalSetExpr = VarExpr<ExprType::GlobalSet>;
|
||||
using LocalGetExpr = VarExpr<ExprType::LocalGet>;
|
||||
using LocalSetExpr = VarExpr<ExprType::LocalSet>;
|
||||
using LocalTeeExpr = VarExpr<ExprType::LocalTee>;
|
||||
using ReturnCallExpr = VarExpr<ExprType::ReturnCall>;
|
||||
using ThrowExpr = VarExpr<ExprType::Throw>;
|
||||
using RethrowExpr = VarExpr<ExprType::Rethrow>;
|
||||
|
||||
using DataDropExpr = VarExpr<ExprType::DataDrop>;
|
||||
using ElemDropExpr = VarExpr<ExprType::ElemDrop>;
|
||||
using TableGetExpr = VarExpr<ExprType::TableGet>;
|
||||
using TableSetExpr = VarExpr<ExprType::TableSet>;
|
||||
using TableGrowExpr = VarExpr<ExprType::TableGrow>;
|
||||
using TableSizeExpr = VarExpr<ExprType::TableSize>;
|
||||
using TableFillExpr = VarExpr<ExprType::TableFill>;
|
||||
|
||||
using MemoryInitExpr = MemoryVarExpr<ExprType::MemoryInit>;
|
||||
|
||||
class SelectExpr : public ExprMixin<ExprType::Select> {
|
||||
public:
|
||||
@ -570,9 +681,22 @@ class CallIndirectExpr : public ExprMixin<ExprType::CallIndirect> {
|
||||
Var table;
|
||||
};
|
||||
|
||||
class CodeMetadataExpr : public ExprMixin<ExprType::CodeMetadata> {
|
||||
public:
|
||||
explicit CodeMetadataExpr(std::string_view name,
|
||||
std::vector<uint8_t> data,
|
||||
const Location& loc = Location())
|
||||
: ExprMixin<ExprType::CodeMetadata>(loc),
|
||||
name(std::move(name)),
|
||||
data(std::move(data)) {}
|
||||
|
||||
std::string_view name;
|
||||
std::vector<uint8_t> data;
|
||||
};
|
||||
|
||||
class ReturnCallIndirectExpr : public ExprMixin<ExprType::ReturnCallIndirect> {
|
||||
public:
|
||||
explicit ReturnCallIndirectExpr(const Location &loc = Location())
|
||||
explicit ReturnCallIndirectExpr(const Location& loc = Location())
|
||||
: ExprMixin<ExprType::ReturnCallIndirect>(loc) {}
|
||||
|
||||
FuncDeclaration decl;
|
||||
@ -581,7 +705,7 @@ class ReturnCallIndirectExpr : public ExprMixin<ExprType::ReturnCallIndirect> {
|
||||
|
||||
class CallRefExpr : public ExprMixin<ExprType::CallRef> {
|
||||
public:
|
||||
explicit CallRefExpr(const Location &loc = Location())
|
||||
explicit CallRefExpr(const Location& loc = Location())
|
||||
: ExprMixin<ExprType::CallRef>(loc) {}
|
||||
|
||||
// This field is setup only during Validate phase,
|
||||
@ -598,8 +722,8 @@ class BlockExprBase : public ExprMixin<TypeEnum> {
|
||||
Block block;
|
||||
};
|
||||
|
||||
typedef BlockExprBase<ExprType::Block> BlockExpr;
|
||||
typedef BlockExprBase<ExprType::Loop> LoopExpr;
|
||||
using BlockExpr = BlockExprBase<ExprType::Block>;
|
||||
using LoopExpr = BlockExprBase<ExprType::Loop>;
|
||||
|
||||
class IfExpr : public ExprMixin<ExprType::If> {
|
||||
public:
|
||||
@ -641,13 +765,14 @@ class ConstExpr : public ExprMixin<ExprType::Const> {
|
||||
|
||||
// TODO(binji): Rename this, it is used for more than loads/stores now.
|
||||
template <ExprType TypeEnum>
|
||||
class LoadStoreExpr : public ExprMixin<TypeEnum> {
|
||||
class LoadStoreExpr : public MemoryExpr<TypeEnum> {
|
||||
public:
|
||||
LoadStoreExpr(Opcode opcode,
|
||||
Var memidx,
|
||||
Address align,
|
||||
Address offset,
|
||||
const Location& loc = Location())
|
||||
: ExprMixin<TypeEnum>(loc),
|
||||
: MemoryExpr<TypeEnum>(memidx, loc),
|
||||
opcode(opcode),
|
||||
align(align),
|
||||
offset(offset) {}
|
||||
@ -657,16 +782,17 @@ class LoadStoreExpr : public ExprMixin<TypeEnum> {
|
||||
Address offset;
|
||||
};
|
||||
|
||||
typedef LoadStoreExpr<ExprType::Load> LoadExpr;
|
||||
typedef LoadStoreExpr<ExprType::Store> StoreExpr;
|
||||
typedef LoadStoreExpr<ExprType::AtomicLoad> AtomicLoadExpr;
|
||||
typedef LoadStoreExpr<ExprType::AtomicStore> AtomicStoreExpr;
|
||||
typedef LoadStoreExpr<ExprType::AtomicRmw> AtomicRmwExpr;
|
||||
typedef LoadStoreExpr<ExprType::AtomicRmwCmpxchg> AtomicRmwCmpxchgExpr;
|
||||
typedef LoadStoreExpr<ExprType::AtomicWait> AtomicWaitExpr;
|
||||
typedef LoadStoreExpr<ExprType::AtomicNotify> AtomicNotifyExpr;
|
||||
typedef LoadStoreExpr<ExprType::LoadSplat> LoadSplatExpr;
|
||||
typedef LoadStoreExpr<ExprType::LoadZero> LoadZeroExpr;
|
||||
using LoadExpr = LoadStoreExpr<ExprType::Load>;
|
||||
using StoreExpr = LoadStoreExpr<ExprType::Store>;
|
||||
|
||||
using AtomicLoadExpr = LoadStoreExpr<ExprType::AtomicLoad>;
|
||||
using AtomicStoreExpr = LoadStoreExpr<ExprType::AtomicStore>;
|
||||
using AtomicRmwExpr = LoadStoreExpr<ExprType::AtomicRmw>;
|
||||
using AtomicRmwCmpxchgExpr = LoadStoreExpr<ExprType::AtomicRmwCmpxchg>;
|
||||
using AtomicWaitExpr = LoadStoreExpr<ExprType::AtomicWait>;
|
||||
using AtomicNotifyExpr = LoadStoreExpr<ExprType::AtomicNotify>;
|
||||
using LoadSplatExpr = LoadStoreExpr<ExprType::LoadSplat>;
|
||||
using LoadZeroExpr = LoadStoreExpr<ExprType::LoadZero>;
|
||||
|
||||
class AtomicFenceExpr : public ExprMixin<ExprType::AtomicFence> {
|
||||
public:
|
||||
@ -679,7 +805,7 @@ class AtomicFenceExpr : public ExprMixin<ExprType::AtomicFence> {
|
||||
};
|
||||
|
||||
struct Tag {
|
||||
explicit Tag(string_view name) : name(name.to_string()) {}
|
||||
explicit Tag(std::string_view name) : name(name) {}
|
||||
|
||||
std::string name;
|
||||
FuncDeclaration decl;
|
||||
@ -687,8 +813,8 @@ struct Tag {
|
||||
|
||||
class LocalTypes {
|
||||
public:
|
||||
typedef std::pair<Type, Index> Decl;
|
||||
typedef std::vector<Decl> Decls;
|
||||
using Decl = std::pair<Type, Index>;
|
||||
using Decls = std::vector<Decl>;
|
||||
|
||||
struct const_iterator {
|
||||
const_iterator(Decls::const_iterator decl, Index index)
|
||||
@ -747,7 +873,7 @@ inline bool operator!=(const LocalTypes::const_iterator& lhs,
|
||||
}
|
||||
|
||||
struct Func {
|
||||
explicit Func(string_view name) : name(name.to_string()) {}
|
||||
explicit Func(std::string_view name) : name(name) {}
|
||||
|
||||
Type GetParamType(Index index) const { return decl.GetParamType(index); }
|
||||
Type GetResultType(Index index) const { return decl.GetResultType(index); }
|
||||
@ -766,10 +892,11 @@ struct Func {
|
||||
LocalTypes local_types;
|
||||
BindingHash bindings;
|
||||
ExprList exprs;
|
||||
Location loc;
|
||||
};
|
||||
|
||||
struct Global {
|
||||
explicit Global(string_view name) : name(name.to_string()) {}
|
||||
explicit Global(std::string_view name) : name(name) {}
|
||||
|
||||
std::string name;
|
||||
Type type = Type::Void;
|
||||
@ -778,33 +905,18 @@ struct Global {
|
||||
};
|
||||
|
||||
struct Table {
|
||||
explicit Table(string_view name)
|
||||
: name(name.to_string()), elem_type(Type::FuncRef) {}
|
||||
explicit Table(std::string_view name)
|
||||
: name(name), elem_type(Type::FuncRef) {}
|
||||
|
||||
std::string name;
|
||||
Limits elem_limits;
|
||||
Type elem_type;
|
||||
};
|
||||
|
||||
enum class ElemExprKind {
|
||||
RefNull,
|
||||
RefFunc,
|
||||
};
|
||||
|
||||
struct ElemExpr {
|
||||
ElemExpr() : kind(ElemExprKind::RefNull), type(Type::FuncRef) {}
|
||||
explicit ElemExpr(Var var) : kind(ElemExprKind::RefFunc), var(var) {}
|
||||
explicit ElemExpr(Type type) : kind(ElemExprKind::RefNull), type(type) {}
|
||||
|
||||
ElemExprKind kind;
|
||||
Var var; // Only used when kind == RefFunc.
|
||||
Type type; // Only used when kind == RefNull
|
||||
};
|
||||
|
||||
typedef std::vector<ElemExpr> ElemExprVector;
|
||||
using ExprListVector = std::vector<ExprList>;
|
||||
|
||||
struct ElemSegment {
|
||||
explicit ElemSegment(string_view name) : name(name.to_string()) {}
|
||||
explicit ElemSegment(std::string_view name) : name(name) {}
|
||||
uint8_t GetFlags(const Module*) const;
|
||||
|
||||
SegmentKind kind = SegmentKind::Active;
|
||||
@ -812,18 +924,18 @@ struct ElemSegment {
|
||||
Var table_var;
|
||||
Type elem_type;
|
||||
ExprList offset;
|
||||
ElemExprVector elem_exprs;
|
||||
ExprListVector elem_exprs;
|
||||
};
|
||||
|
||||
struct Memory {
|
||||
explicit Memory(string_view name) : name(name.to_string()) {}
|
||||
explicit Memory(std::string_view name) : name(name) {}
|
||||
|
||||
std::string name;
|
||||
Limits page_limits;
|
||||
};
|
||||
|
||||
struct DataSegment {
|
||||
explicit DataSegment(string_view name) : name(name.to_string()) {}
|
||||
explicit DataSegment(std::string_view name) : name(name) {}
|
||||
uint8_t GetFlags(const Module*) const;
|
||||
|
||||
SegmentKind kind = SegmentKind::Active;
|
||||
@ -862,7 +974,7 @@ class ImportMixin : public Import {
|
||||
|
||||
class FuncImport : public ImportMixin<ExternalKind::Func> {
|
||||
public:
|
||||
explicit FuncImport(string_view name = string_view())
|
||||
explicit FuncImport(std::string_view name = std::string_view())
|
||||
: ImportMixin<ExternalKind::Func>(), func(name) {}
|
||||
|
||||
Func func;
|
||||
@ -870,7 +982,7 @@ class FuncImport : public ImportMixin<ExternalKind::Func> {
|
||||
|
||||
class TableImport : public ImportMixin<ExternalKind::Table> {
|
||||
public:
|
||||
explicit TableImport(string_view name = string_view())
|
||||
explicit TableImport(std::string_view name = std::string_view())
|
||||
: ImportMixin<ExternalKind::Table>(), table(name) {}
|
||||
|
||||
Table table;
|
||||
@ -878,7 +990,7 @@ class TableImport : public ImportMixin<ExternalKind::Table> {
|
||||
|
||||
class MemoryImport : public ImportMixin<ExternalKind::Memory> {
|
||||
public:
|
||||
explicit MemoryImport(string_view name = string_view())
|
||||
explicit MemoryImport(std::string_view name = std::string_view())
|
||||
: ImportMixin<ExternalKind::Memory>(), memory(name) {}
|
||||
|
||||
Memory memory;
|
||||
@ -886,7 +998,7 @@ class MemoryImport : public ImportMixin<ExternalKind::Memory> {
|
||||
|
||||
class GlobalImport : public ImportMixin<ExternalKind::Global> {
|
||||
public:
|
||||
explicit GlobalImport(string_view name = string_view())
|
||||
explicit GlobalImport(std::string_view name = std::string_view())
|
||||
: ImportMixin<ExternalKind::Global>(), global(name) {}
|
||||
|
||||
Global global;
|
||||
@ -894,7 +1006,7 @@ class GlobalImport : public ImportMixin<ExternalKind::Global> {
|
||||
|
||||
class TagImport : public ImportMixin<ExternalKind::Tag> {
|
||||
public:
|
||||
explicit TagImport(string_view name = string_view())
|
||||
explicit TagImport(std::string_view name = std::string_view())
|
||||
: ImportMixin<ExternalKind::Tag>(), tag(name) {}
|
||||
|
||||
Tag tag;
|
||||
@ -937,7 +1049,7 @@ class ModuleField : public intrusive_list_base<ModuleField> {
|
||||
ModuleFieldType type_;
|
||||
};
|
||||
|
||||
typedef intrusive_list<ModuleField> ModuleFieldList;
|
||||
using ModuleFieldList = intrusive_list<ModuleField>;
|
||||
|
||||
template <ModuleFieldType TypeEnum>
|
||||
class ModuleFieldMixin : public ModuleField {
|
||||
@ -952,7 +1064,7 @@ class ModuleFieldMixin : public ModuleField {
|
||||
class FuncModuleField : public ModuleFieldMixin<ModuleFieldType::Func> {
|
||||
public:
|
||||
explicit FuncModuleField(const Location& loc = Location(),
|
||||
string_view name = string_view())
|
||||
std::string_view name = std::string_view())
|
||||
: ModuleFieldMixin<ModuleFieldType::Func>(loc), func(name) {}
|
||||
|
||||
Func func;
|
||||
@ -961,7 +1073,7 @@ class FuncModuleField : public ModuleFieldMixin<ModuleFieldType::Func> {
|
||||
class GlobalModuleField : public ModuleFieldMixin<ModuleFieldType::Global> {
|
||||
public:
|
||||
explicit GlobalModuleField(const Location& loc = Location(),
|
||||
string_view name = string_view())
|
||||
std::string_view name = std::string_view())
|
||||
: ModuleFieldMixin<ModuleFieldType::Global>(loc), global(name) {}
|
||||
|
||||
Global global;
|
||||
@ -998,7 +1110,7 @@ class TypeModuleField : public ModuleFieldMixin<ModuleFieldType::Type> {
|
||||
class TableModuleField : public ModuleFieldMixin<ModuleFieldType::Table> {
|
||||
public:
|
||||
explicit TableModuleField(const Location& loc = Location(),
|
||||
string_view name = string_view())
|
||||
std::string_view name = std::string_view())
|
||||
: ModuleFieldMixin<ModuleFieldType::Table>(loc), table(name) {}
|
||||
|
||||
Table table;
|
||||
@ -1008,7 +1120,7 @@ class ElemSegmentModuleField
|
||||
: public ModuleFieldMixin<ModuleFieldType::ElemSegment> {
|
||||
public:
|
||||
explicit ElemSegmentModuleField(const Location& loc = Location(),
|
||||
string_view name = string_view())
|
||||
std::string_view name = std::string_view())
|
||||
: ModuleFieldMixin<ModuleFieldType::ElemSegment>(loc),
|
||||
elem_segment(name) {}
|
||||
|
||||
@ -1018,7 +1130,7 @@ class ElemSegmentModuleField
|
||||
class MemoryModuleField : public ModuleFieldMixin<ModuleFieldType::Memory> {
|
||||
public:
|
||||
explicit MemoryModuleField(const Location& loc = Location(),
|
||||
string_view name = string_view())
|
||||
std::string_view name = std::string_view())
|
||||
: ModuleFieldMixin<ModuleFieldType::Memory>(loc), memory(name) {}
|
||||
|
||||
Memory memory;
|
||||
@ -1028,7 +1140,7 @@ class DataSegmentModuleField
|
||||
: public ModuleFieldMixin<ModuleFieldType::DataSegment> {
|
||||
public:
|
||||
explicit DataSegmentModuleField(const Location& loc = Location(),
|
||||
string_view name = string_view())
|
||||
std::string_view name = std::string_view())
|
||||
: ModuleFieldMixin<ModuleFieldType::DataSegment>(loc),
|
||||
data_segment(name) {}
|
||||
|
||||
@ -1038,7 +1150,7 @@ class DataSegmentModuleField
|
||||
class TagModuleField : public ModuleFieldMixin<ModuleFieldType::Tag> {
|
||||
public:
|
||||
explicit TagModuleField(const Location& loc = Location(),
|
||||
string_view name = string_view())
|
||||
std::string_view name = std::string_view())
|
||||
: ModuleFieldMixin<ModuleFieldType::Tag>(loc), tag(name) {}
|
||||
|
||||
Tag tag;
|
||||
@ -1070,7 +1182,7 @@ struct Module {
|
||||
Index GetGlobalIndex(const Var&) const;
|
||||
const Global* GetGlobal(const Var&) const;
|
||||
Global* GetGlobal(const Var&);
|
||||
const Export* GetExport(string_view) const;
|
||||
const Export* GetExport(std::string_view) const;
|
||||
Tag* GetTag(const Var&) const;
|
||||
Index GetTagIndex(const Var&) const;
|
||||
const DataSegment* GetDataSegment(const Var&) const;
|
||||
@ -1185,8 +1297,8 @@ class DataScriptModule : public ScriptModuleMixin<TypeEnum> {
|
||||
std::vector<uint8_t> data;
|
||||
};
|
||||
|
||||
typedef DataScriptModule<ScriptModuleType::Binary> BinaryScriptModule;
|
||||
typedef DataScriptModule<ScriptModuleType::Quoted> QuotedScriptModule;
|
||||
using BinaryScriptModule = DataScriptModule<ScriptModuleType::Binary>;
|
||||
using QuotedScriptModule = DataScriptModule<ScriptModuleType::Quoted>;
|
||||
|
||||
enum class ActionType {
|
||||
Invoke,
|
||||
@ -1212,7 +1324,7 @@ class Action {
|
||||
ActionType type_;
|
||||
};
|
||||
|
||||
typedef std::unique_ptr<Action> ActionPtr;
|
||||
using ActionPtr = std::unique_ptr<Action>;
|
||||
|
||||
template <ActionType TypeEnum>
|
||||
class ActionMixin : public Action {
|
||||
@ -1241,6 +1353,7 @@ class InvokeAction : public ActionMixin<ActionType::Invoke> {
|
||||
|
||||
enum class CommandType {
|
||||
Module,
|
||||
ScriptModule,
|
||||
Action,
|
||||
Register,
|
||||
AssertMalformed,
|
||||
@ -1250,11 +1363,12 @@ enum class CommandType {
|
||||
AssertReturn,
|
||||
AssertTrap,
|
||||
AssertExhaustion,
|
||||
AssertException,
|
||||
|
||||
First = Module,
|
||||
Last = AssertExhaustion,
|
||||
Last = AssertException,
|
||||
};
|
||||
static const int kCommandTypeCount = WABT_ENUM_COUNT(CommandType);
|
||||
constexpr int kCommandTypeCount = WABT_ENUM_COUNT(CommandType);
|
||||
|
||||
class Command {
|
||||
public:
|
||||
@ -1280,17 +1394,26 @@ class ModuleCommand : public CommandMixin<CommandType::Module> {
|
||||
Module module;
|
||||
};
|
||||
|
||||
class ScriptModuleCommand : public CommandMixin<CommandType::ScriptModule> {
|
||||
public:
|
||||
// Both the module and the script_module need to be stored since the module
|
||||
// has the parsed information about the module, but the script_module has the
|
||||
// original contents (binary or quoted).
|
||||
Module module;
|
||||
std::unique_ptr<ScriptModule> script_module;
|
||||
};
|
||||
|
||||
template <CommandType TypeEnum>
|
||||
class ActionCommandBase : public CommandMixin<TypeEnum> {
|
||||
public:
|
||||
ActionPtr action;
|
||||
};
|
||||
|
||||
typedef ActionCommandBase<CommandType::Action> ActionCommand;
|
||||
using ActionCommand = ActionCommandBase<CommandType::Action>;
|
||||
|
||||
class RegisterCommand : public CommandMixin<CommandType::Register> {
|
||||
public:
|
||||
RegisterCommand(string_view module_name, const Var& var)
|
||||
RegisterCommand(std::string_view module_name, const Var& var)
|
||||
: module_name(module_name), var(var) {}
|
||||
|
||||
std::string module_name;
|
||||
@ -1300,7 +1423,7 @@ class RegisterCommand : public CommandMixin<CommandType::Register> {
|
||||
class AssertReturnCommand : public CommandMixin<CommandType::AssertReturn> {
|
||||
public:
|
||||
ActionPtr action;
|
||||
ConstVector expected;
|
||||
ExpectationPtr expected;
|
||||
};
|
||||
|
||||
template <CommandType TypeEnum>
|
||||
@ -1310,9 +1433,9 @@ class AssertTrapCommandBase : public CommandMixin<TypeEnum> {
|
||||
std::string text;
|
||||
};
|
||||
|
||||
typedef AssertTrapCommandBase<CommandType::AssertTrap> AssertTrapCommand;
|
||||
typedef AssertTrapCommandBase<CommandType::AssertExhaustion>
|
||||
AssertExhaustionCommand;
|
||||
using AssertTrapCommand = AssertTrapCommandBase<CommandType::AssertTrap>;
|
||||
using AssertExhaustionCommand =
|
||||
AssertTrapCommandBase<CommandType::AssertExhaustion>;
|
||||
|
||||
template <CommandType TypeEnum>
|
||||
class AssertModuleCommand : public CommandMixin<TypeEnum> {
|
||||
@ -1321,16 +1444,22 @@ class AssertModuleCommand : public CommandMixin<TypeEnum> {
|
||||
std::string text;
|
||||
};
|
||||
|
||||
typedef AssertModuleCommand<CommandType::AssertMalformed>
|
||||
AssertMalformedCommand;
|
||||
typedef AssertModuleCommand<CommandType::AssertInvalid> AssertInvalidCommand;
|
||||
typedef AssertModuleCommand<CommandType::AssertUnlinkable>
|
||||
AssertUnlinkableCommand;
|
||||
typedef AssertModuleCommand<CommandType::AssertUninstantiable>
|
||||
AssertUninstantiableCommand;
|
||||
using AssertMalformedCommand =
|
||||
AssertModuleCommand<CommandType::AssertMalformed>;
|
||||
using AssertInvalidCommand = AssertModuleCommand<CommandType::AssertInvalid>;
|
||||
using AssertUnlinkableCommand =
|
||||
AssertModuleCommand<CommandType::AssertUnlinkable>;
|
||||
using AssertUninstantiableCommand =
|
||||
AssertModuleCommand<CommandType::AssertUninstantiable>;
|
||||
|
||||
typedef std::unique_ptr<Command> CommandPtr;
|
||||
typedef std::vector<CommandPtr> CommandPtrVector;
|
||||
class AssertExceptionCommand
|
||||
: public CommandMixin<CommandType::AssertException> {
|
||||
public:
|
||||
ActionPtr action;
|
||||
};
|
||||
|
||||
using CommandPtr = std::unique_ptr<Command>;
|
||||
using CommandPtrVector = std::vector<CommandPtr>;
|
||||
|
||||
struct Script {
|
||||
WABT_DISALLOW_COPY_AND_ASSIGN(Script);
|
@ -19,7 +19,7 @@
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "src/common.h"
|
||||
#include "wabt/common.h"
|
||||
|
||||
namespace wabt {
|
||||
|
@ -21,9 +21,9 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "src/common.h"
|
||||
#include "src/lexer-source.h"
|
||||
#include "src/range.h"
|
||||
#include "wabt/common.h"
|
||||
#include "wabt/lexer-source.h"
|
||||
#include "wabt/range.h"
|
||||
|
||||
namespace wabt {
|
||||
|
@ -22,8 +22,8 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "src/common.h"
|
||||
#include "src/range.h"
|
||||
#include "wabt/common.h"
|
||||
#include "wabt/range.h"
|
||||
|
||||
namespace wabt {
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "src/common.h"
|
||||
#include "wabt/common.h"
|
||||
|
||||
namespace wabt {
|
||||
|
||||
@ -75,6 +75,51 @@ Result ParseDouble(LiteralType literal_type,
|
||||
const char* end,
|
||||
uint64_t* out_bits);
|
||||
|
||||
// Same as above but taking a string_view
|
||||
inline Result ParseInt8(std::string_view v,
|
||||
uint8_t* out,
|
||||
ParseIntType parse_type) {
|
||||
return ParseInt8(v.data(), v.data() + v.size(), out, parse_type);
|
||||
}
|
||||
|
||||
inline Result ParseInt16(std::string_view v,
|
||||
uint16_t* out,
|
||||
ParseIntType parse_type) {
|
||||
return ParseInt16(v.data(), v.data() + v.size(), out, parse_type);
|
||||
}
|
||||
|
||||
inline Result ParseInt32(std::string_view v,
|
||||
uint32_t* out,
|
||||
ParseIntType parse_type) {
|
||||
return ParseInt32(v.data(), v.data() + v.size(), out, parse_type);
|
||||
}
|
||||
|
||||
inline Result ParseInt64(std::string_view v,
|
||||
uint64_t* out,
|
||||
ParseIntType parse_type) {
|
||||
return ParseInt64(v.data(), v.data() + v.size(), out, parse_type);
|
||||
}
|
||||
|
||||
inline Result ParseUint64(std::string_view v, uint64_t* out) {
|
||||
return ParseUint64(v.data(), v.data() + v.size(), out);
|
||||
}
|
||||
|
||||
inline Result ParseUint128(std::string_view v, v128* out) {
|
||||
return ParseUint128(v.data(), v.data() + v.size(), out);
|
||||
}
|
||||
|
||||
inline Result ParseFloat(LiteralType literal_type,
|
||||
std::string_view v,
|
||||
uint32_t* out_bits) {
|
||||
return ParseFloat(literal_type, v.data(), v.data() + v.size(), out_bits);
|
||||
}
|
||||
|
||||
inline Result ParseDouble(LiteralType literal_type,
|
||||
std::string_view v,
|
||||
uint64_t* out_bits) {
|
||||
return ParseDouble(literal_type, v.data(), v.data() + v.size(), out_bits);
|
||||
}
|
||||
|
||||
void WriteFloatHex(char* buffer, size_t size, uint32_t bits);
|
||||
void WriteDoubleHex(char* buffer, size_t size, uint64_t bits);
|
||||
void WriteUint128(char* buffer, size_t size, v128 bits);
|
@ -17,14 +17,19 @@
|
||||
#ifndef WABT_OPCODE_CODE_TABLE_H_
|
||||
#define WABT_OPCODE_CODE_TABLE_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define WABT_OPCODE_CODE_TABLE_SIZE 65536
|
||||
#define WABT_OPCODE_CODE_TABLE_SIZE 131072
|
||||
|
||||
/*
|
||||
* Number of bits required to store an opcode
|
||||
*/
|
||||
#define MAX_OPCODE_BITS 9
|
||||
|
||||
/* This structure is defined in C because C++ doesn't (yet) allow you to use
|
||||
* designated array initializers, i.e. [10] = {foo}.
|
@ -231,6 +231,8 @@ WABT_OPCODE(___, I32, ___, ___, 0, 0, 0xe1, InterpBrUnless, "br_unless",
|
||||
WABT_OPCODE(___, ___, ___, ___, 0, 0, 0xe2, InterpCallImport, "call_import", "")
|
||||
WABT_OPCODE(___, ___, ___, ___, 0, 0, 0xe3, InterpData, "data", "")
|
||||
WABT_OPCODE(___, ___, ___, ___, 0, 0, 0xe4, InterpDropKeep, "drop_keep", "")
|
||||
WABT_OPCODE(___, ___, ___, ___, 0, 0, 0xe5, InterpCatchDrop, "catch_drop", "")
|
||||
WABT_OPCODE(___, ___, ___, ___, 0, 0, 0xe6, InterpAdjustFrameForReturnCall, "adjust_frame_for_return_call", "")
|
||||
|
||||
/* Saturating float-to-int opcodes (--enable-saturating-float-to-int) */
|
||||
WABT_OPCODE(I32, F32, ___, ___, 0, 0xfc, 0x00, I32TruncSatF32S, "i32.trunc_sat_f32_s", "")
|
||||
@ -242,7 +244,7 @@ WABT_OPCODE(I64, F32, ___, ___, 0, 0xfc, 0x05, I64TruncSatF32U, "i64.trunc_
|
||||
WABT_OPCODE(I64, F64, ___, ___, 0, 0xfc, 0x06, I64TruncSatF64S, "i64.trunc_sat_f64_s", "")
|
||||
WABT_OPCODE(I64, F64, ___, ___, 0, 0xfc, 0x07, I64TruncSatF64U, "i64.trunc_sat_f64_u", "")
|
||||
|
||||
/* Bulk-memory (--enable-bulk-memory) */
|
||||
/* Bulk-memory */
|
||||
WABT_OPCODE(___, I32, I32, I32, 0, 0xfc, 0x08, MemoryInit, "memory.init", "")
|
||||
WABT_OPCODE(___, ___, ___, ___, 0, 0xfc, 0x09, DataDrop, "data.drop", "")
|
||||
WABT_OPCODE(___, I32, I32, I32, 0, 0xfc, 0x0a, MemoryCopy,"memory.copy", "")
|
||||
@ -251,7 +253,7 @@ WABT_OPCODE(___, I32, I32, I32, 0, 0xfc, 0x0c, TableInit, "table.init", "")
|
||||
WABT_OPCODE(___, ___, ___, ___, 0, 0xfc, 0x0d, ElemDrop, "elem.drop", "")
|
||||
WABT_OPCODE(___, I32, I32, I32, 0, 0xfc, 0x0e, TableCopy, "table.copy", "")
|
||||
|
||||
/* Reference types (--enable-reference-types) */
|
||||
/* Reference types */
|
||||
WABT_OPCODE(___, I32, ___, ___, 0, 0, 0x25, TableGet, "table.get", "")
|
||||
WABT_OPCODE(___, I32, ___, ___, 0, 0, 0x26, TableSet, "table.set", "")
|
||||
WABT_OPCODE(___, ___, I32, ___, 0, 0xfc, 0x0f, TableGrow, "table.grow", "")
|
||||
@ -499,6 +501,28 @@ WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0xfd, I32X4TruncSatF64X2UZero, "i3
|
||||
WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0xfe, F64X2ConvertLowI32X4S, "f64x2.convert_low_i32x4_s", "")
|
||||
WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0xff, F64X2ConvertLowI32X4U, "f64x2.convert_low_i32x4_u", "")
|
||||
|
||||
/* Relaxed-SIMD opcodes */
|
||||
WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x100, I8X16RelaxedSwizzle, "i8x16.relaxed_swizzle", "")
|
||||
WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0x101, I32X4RelaxedTruncF32X4S, "i32x4.relaxed_trunc_f32x4_s", "")
|
||||
WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0x102, I32X4RelaxedTruncF32X4U, "i32x4.relaxed_trunc_f32x4_u", "")
|
||||
WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0x103, I32X4RelaxedTruncF64X2SZero, "i32x4.relaxed_trunc_f64x2_s_zero", "")
|
||||
WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0x104, I32X4RelaxedTruncF64X2UZero, "i32x4.relaxed_trunc_f64x2_u_zero", "")
|
||||
WABT_OPCODE(V128, V128, V128, V128, 0, 0xfd, 0x105, F32X4RelaxedMadd, "f32x4.relaxed_madd", "")
|
||||
WABT_OPCODE(V128, V128, V128, V128, 0, 0xfd, 0x106, F32X4RelaxedNmadd, "f32x4.relaxed_nmadd", "")
|
||||
WABT_OPCODE(V128, V128, V128, V128, 0, 0xfd, 0x107, F64X2RelaxedMadd, "f64x2.relaxed_madd", "")
|
||||
WABT_OPCODE(V128, V128, V128, V128, 0, 0xfd, 0x108, F64X2RelaxedNmadd, "f64x2.relaxed_nmadd", "")
|
||||
WABT_OPCODE(V128, V128, V128, V128, 0, 0xfd, 0x109, I8X16RelaxedLaneSelect, "i8x16.relaxed_laneselect", "")
|
||||
WABT_OPCODE(V128, V128, V128, V128, 0, 0xfd, 0x10a, I16X8RelaxedLaneSelect, "i16x8.relaxed_laneselect", "")
|
||||
WABT_OPCODE(V128, V128, V128, V128, 0, 0xfd, 0x10b, I32X4RelaxedLaneSelect, "i32x4.relaxed_laneselect", "")
|
||||
WABT_OPCODE(V128, V128, V128, V128, 0, 0xfd, 0x10c, I64X2RelaxedLaneSelect, "i64x2.relaxed_laneselect", "")
|
||||
WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x10d, F32X4RelaxedMin, "f32x4.relaxed_min", "")
|
||||
WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x10e, F32X4RelaxedMax, "f32x4.relaxed_max", "")
|
||||
WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x10f, F64X2RelaxedMin, "f64x2.relaxed_min", "")
|
||||
WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x110, F64X2RelaxedMax, "f64x2.relaxed_max", "")
|
||||
WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x111, I16X8RelaxedQ15mulrS, "i16x8.relaxed_q15mulr_s", "")
|
||||
WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x112, I16X8DotI8X16I7X16S, "i16x8.dot_i8x16_i7x16_s", "")
|
||||
WABT_OPCODE(V128, V128, V128, V128, 0, 0xfd, 0x113, I32X4DotI8X16I7X16AddS, "i32x4.dot_i8x16_i7x16_add_s", "")
|
||||
|
||||
/* Thread opcodes (--enable-threads) */
|
||||
WABT_OPCODE(I32, I32, I32, ___, 4, 0xfe, 0x00, MemoryAtomicNotify, "memory.atomic.notify", "")
|
||||
WABT_OPCODE(I32, I32, I32, I64, 4, 0xfe, 0x01, MemoryAtomicWait32, "memory.atomic.wait32", "")
|
@ -19,9 +19,9 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "src/common.h"
|
||||
#include "src/opcode-code-table.h"
|
||||
#include "src/leb128.h"
|
||||
#include "wabt/common.h"
|
||||
#include "wabt/leb128.h"
|
||||
#include "wabt/opcode-code-table.h"
|
||||
|
||||
namespace wabt {
|
||||
|
||||
@ -36,7 +36,7 @@ struct Opcode {
|
||||
#define WABT_OPCODE(rtype, type1, type2, type3, mem_size, prefix, code, Name, \
|
||||
text, decomp) \
|
||||
Name,
|
||||
#include "src/opcode.def"
|
||||
#include "wabt/opcode.def"
|
||||
#undef WABT_OPCODE
|
||||
Invalid,
|
||||
};
|
||||
@ -45,7 +45,7 @@ struct Opcode {
|
||||
#define WABT_OPCODE(rtype, type1, type2, type3, mem_size, prefix, code, Name, \
|
||||
text, decomp) \
|
||||
static Opcode Name##_Opcode;
|
||||
#include "src/opcode.def"
|
||||
#include "wabt/opcode.def"
|
||||
#undef WABT_OPCODE
|
||||
|
||||
Opcode() = default; // Provided so Opcode can be member of a union.
|
||||
@ -69,14 +69,6 @@ struct Opcode {
|
||||
Type GetParamType(int n) const { return GetInfo().param_types[n - 1]; }
|
||||
Address GetMemorySize() const { return GetInfo().memory_size; }
|
||||
|
||||
// If this is a load/store op, the type depends on the memory used.
|
||||
Type GetMemoryParam(Type param,
|
||||
const Limits* limits,
|
||||
bool has_address_operands) {
|
||||
return limits && limits->is_64 && has_address_operands ? Type(Type::I64)
|
||||
: param;
|
||||
}
|
||||
|
||||
// Get the byte sequence for this opcode, including prefix.
|
||||
std::vector<uint8_t> GetBytes() const;
|
||||
|
||||
@ -99,9 +91,9 @@ struct Opcode {
|
||||
bool IsInvalid() const { return enum_ >= Invalid; }
|
||||
|
||||
private:
|
||||
static const uint32_t kMathPrefix = 0xfc;
|
||||
static const uint32_t kThreadsPrefix = 0xfe;
|
||||
static const uint32_t kSimdPrefix = 0xfd;
|
||||
static constexpr uint32_t kMathPrefix = 0xfc;
|
||||
static constexpr uint32_t kThreadsPrefix = 0xfe;
|
||||
static constexpr uint32_t kSimdPrefix = 0xfd;
|
||||
|
||||
struct Info {
|
||||
const char* name;
|
||||
@ -115,12 +107,11 @@ struct Opcode {
|
||||
};
|
||||
|
||||
static uint32_t PrefixCode(uint8_t prefix, uint32_t code) {
|
||||
// For now, 8 bits is enough for all codes.
|
||||
if (code >= 0x100) {
|
||||
// Clamp to 0xff, since we know that it is an invalid code.
|
||||
code = 0xff;
|
||||
if (code >= (1 << MAX_OPCODE_BITS)) {
|
||||
// Clamp to (2^bits - 1), since we know that it is an invalid code.
|
||||
code = (1 << MAX_OPCODE_BITS) - 1;
|
||||
}
|
||||
return (prefix << 8) | code;
|
||||
return (prefix << MAX_OPCODE_BITS) | code;
|
||||
}
|
||||
|
||||
// The Opcode struct only stores an enumeration (Opcode::Enum) of all valid
|
||||
@ -145,7 +136,7 @@ struct Opcode {
|
||||
uint8_t* out_prefix,
|
||||
uint32_t* out_code) {
|
||||
uint32_t prefix_code = ~static_cast<uint32_t>(e) + 1;
|
||||
*out_prefix = prefix_code >> 8;
|
||||
*out_prefix = prefix_code >> MAX_OPCODE_BITS;
|
||||
*out_code = prefix_code & 0xff;
|
||||
}
|
||||
|
||||
@ -176,7 +167,6 @@ inline Opcode Opcode::FromCode(uint8_t prefix, uint32_t code) {
|
||||
return Opcode(EncodeInvalidOpcode(prefix_code));
|
||||
}
|
||||
|
||||
|
||||
} // namespace wabt
|
||||
|
||||
#endif // WABT_OPCODE_H_
|
@ -21,7 +21,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "src/common.h"
|
||||
#include "wabt/common.h"
|
||||
|
||||
namespace wabt {
|
||||
|
||||
@ -31,8 +31,8 @@ class OptionParser {
|
||||
enum class ArgumentCount { One, OneOrMore, ZeroOrMore };
|
||||
|
||||
struct Option;
|
||||
typedef std::function<void(const char*)> Callback;
|
||||
typedef std::function<void()> NullCallback;
|
||||
using Callback = std::function<void(const char*)>;
|
||||
using NullCallback = std::function<void()>;
|
||||
|
||||
struct Option {
|
||||
Option(char short_name,
|
@ -29,8 +29,8 @@ struct Range {
|
||||
T size() const { return end - start; }
|
||||
};
|
||||
|
||||
typedef Range<Offset> OffsetRange;
|
||||
typedef Range<int> ColumnRange;
|
||||
using OffsetRange = Range<Offset>;
|
||||
using ColumnRange = Range<int>;
|
||||
|
||||
} // namespace wabt
|
||||
|
@ -17,8 +17,8 @@
|
||||
#ifndef WABT_RESOLVE_NAMES_H_
|
||||
#define WABT_RESOLVE_NAMES_H_
|
||||
|
||||
#include "src/common.h"
|
||||
#include "src/error.h"
|
||||
#include "wabt/common.h"
|
||||
#include "wabt/error.h"
|
||||
|
||||
namespace wabt {
|
||||
|
@ -14,28 +14,18 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef WABT_C_WRITER_H_
|
||||
#define WABT_C_WRITER_H_
|
||||
#ifndef WABT_SHA256_H_
|
||||
#define WABT_SHA256_H_
|
||||
|
||||
#include "src/common.h"
|
||||
#include "wabt/config.h"
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
namespace wabt {
|
||||
|
||||
struct Module;
|
||||
class Stream;
|
||||
|
||||
struct WriteCOptions {
|
||||
std::string mod_name;
|
||||
};
|
||||
|
||||
Result WriteC(Stream* c_stream,
|
||||
Stream* h_stream,
|
||||
const char* header_name,
|
||||
const Module*,
|
||||
const WriteCOptions&);
|
||||
void sha256(std::string_view input, std::string& digest);
|
||||
|
||||
} // namespace wabt
|
||||
|
||||
#endif /* WABT_C_WRITER_H_ */
|
||||
#endif // WABT_SHA256_H_
|
@ -22,14 +22,14 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "src/common.h"
|
||||
#include "src/error.h"
|
||||
#include "src/feature.h"
|
||||
#include "src/ir.h"
|
||||
#include "src/opcode.h"
|
||||
#include "src/type-checker.h"
|
||||
#include "wabt/common.h"
|
||||
#include "wabt/error.h"
|
||||
#include "wabt/feature.h"
|
||||
#include "wabt/ir.h"
|
||||
#include "wabt/opcode.h"
|
||||
#include "wabt/type-checker.h"
|
||||
|
||||
#include "src/binary-reader.h" // For TypeMut.
|
||||
#include "wabt/binary-reader.h" // For TypeMut.
|
||||
|
||||
namespace wabt {
|
||||
|
||||
@ -51,6 +51,9 @@ class SharedValidator {
|
||||
Result GetLabel(Index depth, Label** out_label) {
|
||||
return typechecker_.GetLabel(depth, out_label);
|
||||
}
|
||||
Result GetCatchCount(Index depth, Index* out_count) {
|
||||
return typechecker_.GetCatchCount(depth, out_count);
|
||||
}
|
||||
|
||||
Result WABT_PRINTF_FORMAT(3, 4)
|
||||
PrintError(const Location& loc, const char* fmt, ...);
|
||||
@ -65,7 +68,8 @@ class SharedValidator {
|
||||
Index param_count,
|
||||
const Type* param_types,
|
||||
Index result_count,
|
||||
const Type* result_types);
|
||||
const Type* result_types,
|
||||
Index type_index);
|
||||
Result OnStructType(const Location&, Index field_count, TypeMut* fields);
|
||||
Result OnArrayType(const Location&, TypeMut field);
|
||||
|
||||
@ -74,47 +78,38 @@ class SharedValidator {
|
||||
Result OnMemory(const Location&, const Limits&);
|
||||
Result OnGlobalImport(const Location&, Type type, bool mutable_);
|
||||
Result OnGlobal(const Location&, Type type, bool mutable_);
|
||||
Result OnGlobalInitExpr_Const(const Location&, Type);
|
||||
Result OnGlobalInitExpr_GlobalGet(const Location&, Var global_var);
|
||||
Result OnGlobalInitExpr_RefNull(const Location&, Type type);
|
||||
Result OnGlobalInitExpr_RefFunc(const Location&, Var func_var);
|
||||
Result OnGlobalInitExpr_Other(const Location&);
|
||||
Result OnTag(const Location&, Var sig_var);
|
||||
|
||||
Result OnExport(const Location&,
|
||||
ExternalKind,
|
||||
Var item_var,
|
||||
string_view name);
|
||||
std::string_view name);
|
||||
|
||||
Result OnStart(const Location&, Var func_var);
|
||||
|
||||
Result OnElemSegment(const Location&, Var table_var, SegmentKind);
|
||||
void OnElemSegmentElemType(Type elem_type);
|
||||
Result OnElemSegmentInitExpr_Const(const Location&, Type);
|
||||
Result OnElemSegmentInitExpr_GlobalGet(const Location&, Var global_var);
|
||||
Result OnElemSegmentInitExpr_Other(const Location&);
|
||||
Result OnElemSegmentElemType(const Location&, Type elem_type);
|
||||
Result OnElemSegmentElemExpr_RefNull(const Location&, Type type);
|
||||
Result OnElemSegmentElemExpr_RefFunc(const Location&, Var func_var);
|
||||
Result OnElemSegmentElemExpr_Other(const Location&);
|
||||
|
||||
void OnDataCount(Index count);
|
||||
|
||||
Result OnDataSegment(const Location&, Var memory_var, SegmentKind);
|
||||
Result OnDataSegmentInitExpr_Const(const Location&, Type);
|
||||
Result OnDataSegmentInitExpr_GlobalGet(const Location&, Var global_var);
|
||||
Result OnDataSegmentInitExpr_Other(const Location&);
|
||||
|
||||
Result BeginInitExpr(const Location&, Type type);
|
||||
Result EndInitExpr();
|
||||
|
||||
Result BeginFunctionBody(const Location&, Index func_index);
|
||||
Result EndFunctionBody(const Location&);
|
||||
Result OnLocalDecl(const Location&, Index count, Type type);
|
||||
|
||||
Result OnAtomicFence(const Location&, uint32_t consistency_model);
|
||||
Result OnAtomicLoad(const Location&, Opcode, Address align);
|
||||
Result OnAtomicNotify(const Location&, Opcode, Address align);
|
||||
Result OnAtomicRmwCmpxchg(const Location&, Opcode, Address align);
|
||||
Result OnAtomicRmw(const Location&, Opcode, Address align);
|
||||
Result OnAtomicStore(const Location&, Opcode, Address align);
|
||||
Result OnAtomicWait(const Location&, Opcode, Address align);
|
||||
Result OnAtomicLoad(const Location&, Opcode, Var memidx, Address align);
|
||||
Result OnAtomicNotify(const Location&, Opcode, Var memidx, Address align);
|
||||
Result OnAtomicRmwCmpxchg(const Location&, Opcode, Var memidx, Address align);
|
||||
Result OnAtomicRmw(const Location&, Opcode, Var memidx, Address align);
|
||||
Result OnAtomicStore(const Location&, Opcode, Var memidx, Address align);
|
||||
Result OnAtomicWait(const Location&, Opcode, Var memidx, Address align);
|
||||
Result OnBinary(const Location&, Opcode);
|
||||
Result OnBlock(const Location&, Type sig_type);
|
||||
Result OnBr(const Location&, Var depth);
|
||||
@ -138,18 +133,18 @@ class SharedValidator {
|
||||
Result OnGlobalGet(const Location&, Var);
|
||||
Result OnGlobalSet(const Location&, Var);
|
||||
Result OnIf(const Location&, Type sig_type);
|
||||
Result OnLoad(const Location&, Opcode, Address align);
|
||||
Result OnLoadSplat(const Location&, Opcode, Address align);
|
||||
Result OnLoadZero(const Location&, Opcode, Address align);
|
||||
Result OnLoad(const Location&, Opcode, Var memidx, Address align);
|
||||
Result OnLoadSplat(const Location&, Opcode, Var memidx, Address align);
|
||||
Result OnLoadZero(const Location&, Opcode, Var memidx, Address align);
|
||||
Result OnLocalGet(const Location&, Var);
|
||||
Result OnLocalSet(const Location&, Var);
|
||||
Result OnLocalTee(const Location&, Var);
|
||||
Result OnLoop(const Location&, Type sig_type);
|
||||
Result OnMemoryCopy(const Location&);
|
||||
Result OnMemoryFill(const Location&);
|
||||
Result OnMemoryGrow(const Location&);
|
||||
Result OnMemoryInit(const Location&, Var segment_var);
|
||||
Result OnMemorySize(const Location&);
|
||||
Result OnMemoryCopy(const Location&, Var srcmemidx, Var destmemidx);
|
||||
Result OnMemoryFill(const Location&, Var memidx);
|
||||
Result OnMemoryGrow(const Location&, Var memidx);
|
||||
Result OnMemoryInit(const Location&, Var segment_var, Var memidx);
|
||||
Result OnMemorySize(const Location&, Var memidx);
|
||||
Result OnNop(const Location&);
|
||||
Result OnRefFunc(const Location&, Var func_var);
|
||||
Result OnRefIsNull(const Location&);
|
||||
@ -160,10 +155,18 @@ class SharedValidator {
|
||||
Result OnReturn(const Location&);
|
||||
Result OnSelect(const Location&, Index result_count, Type* result_types);
|
||||
Result OnSimdLaneOp(const Location&, Opcode, uint64_t lane_idx);
|
||||
Result OnSimdLoadLane(const Location&, Opcode, Address align, uint64_t lane_idx);
|
||||
Result OnSimdStoreLane(const Location&, Opcode, Address align, uint64_t lane_idx);
|
||||
Result OnSimdLoadLane(const Location&,
|
||||
Opcode,
|
||||
Var memidx,
|
||||
Address align,
|
||||
uint64_t lane_idx);
|
||||
Result OnSimdStoreLane(const Location&,
|
||||
Opcode,
|
||||
Var memidx,
|
||||
Address align,
|
||||
uint64_t lane_idx);
|
||||
Result OnSimdShuffleOp(const Location&, Opcode, v128 lane_idx);
|
||||
Result OnStore(const Location&, Opcode, Address align);
|
||||
Result OnStore(const Location&, Opcode, Var memidx, Address align);
|
||||
Result OnTableCopy(const Location&, Var dst_var, Var src_var);
|
||||
Result OnTableFill(const Location&, Var table_var);
|
||||
Result OnTableGet(const Location&, Var table_var);
|
||||
@ -180,11 +183,14 @@ class SharedValidator {
|
||||
private:
|
||||
struct FuncType {
|
||||
FuncType() = default;
|
||||
FuncType(const TypeVector& params, const TypeVector& results)
|
||||
: params(params), results(results) {}
|
||||
FuncType(const TypeVector& params,
|
||||
const TypeVector& results,
|
||||
Index type_index)
|
||||
: params(params), results(results), type_index(type_index) {}
|
||||
|
||||
TypeVector params;
|
||||
TypeVector results;
|
||||
Index type_index;
|
||||
};
|
||||
|
||||
struct StructType {
|
||||
@ -230,9 +236,12 @@ class SharedValidator {
|
||||
|
||||
struct ElemType {
|
||||
ElemType() = default;
|
||||
ElemType(Type element) : element(element) {}
|
||||
ElemType(Type element, bool is_active, Type table_type)
|
||||
: element(element), is_active(is_active), table_type(table_type) {}
|
||||
|
||||
Type element;
|
||||
bool is_active;
|
||||
Type table_type;
|
||||
};
|
||||
|
||||
struct LocalDecl {
|
||||
@ -240,6 +249,8 @@ class SharedValidator {
|
||||
Index end;
|
||||
};
|
||||
|
||||
bool ValidInitOpcode(Opcode opcode) const;
|
||||
Result CheckInstr(Opcode opcode, const Location& loc);
|
||||
Result CheckType(const Location&,
|
||||
Type actual,
|
||||
Type expected,
|
||||
@ -269,7 +280,9 @@ class SharedValidator {
|
||||
Result CheckDataSegmentIndex(Var data_segment_var);
|
||||
|
||||
Result CheckAlign(const Location&, Address align, Address natural_align);
|
||||
Result CheckAtomicAlign(const Location&, Address align, Address natural_align);
|
||||
Result CheckAtomicAlign(const Location&,
|
||||
Address align,
|
||||
Address natural_align);
|
||||
|
||||
Result CheckBlockSignature(const Location&,
|
||||
Opcode,
|
||||
@ -277,13 +290,16 @@ class SharedValidator {
|
||||
TypeVector* out_param_types,
|
||||
TypeVector* out_result_types);
|
||||
|
||||
Index GetFunctionTypeIndex(Index func_index) const;
|
||||
|
||||
TypeVector ToTypeVector(Index count, const Type* types);
|
||||
|
||||
ValidateOptions options_;
|
||||
Errors* errors_;
|
||||
TypeChecker typechecker_; // TODO: Move into SharedValidator.
|
||||
// Cached for access by OnTypecheckerError.
|
||||
const Location* expr_loc_ = nullptr;
|
||||
Location expr_loc_ = Location(kInvalidOffset);
|
||||
bool in_init_expr_ = false;
|
||||
|
||||
Index num_types_ = 0;
|
||||
std::map<Index, FuncType> func_types_;
|
||||
@ -306,7 +322,7 @@ class SharedValidator {
|
||||
|
||||
std::set<std::string> export_names_; // Used to check for duplicates.
|
||||
std::set<Index> declared_funcs_; // TODO: optimize?
|
||||
std::vector<Var> init_expr_funcs_;
|
||||
std::vector<Var> check_declared_funcs_;
|
||||
};
|
||||
|
||||
} // namespace wabt
|
@ -21,7 +21,7 @@
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "src/common.h"
|
||||
#include "wabt/common.h"
|
||||
|
||||
namespace wabt {
|
||||
|
||||
@ -158,7 +158,8 @@ class Stream {
|
||||
};
|
||||
|
||||
struct OutputBuffer {
|
||||
Result WriteToFile(string_view filename) const;
|
||||
Result WriteToFile(std::string_view filename) const;
|
||||
Result WriteToStdout() const;
|
||||
|
||||
void clear() { data.clear(); }
|
||||
size_t size() const { return data.size(); }
|
||||
@ -169,6 +170,7 @@ struct OutputBuffer {
|
||||
class MemoryStream : public Stream {
|
||||
public:
|
||||
WABT_DISALLOW_COPY_AND_ASSIGN(MemoryStream);
|
||||
MemoryStream(MemoryStream&&) = default;
|
||||
explicit MemoryStream(Stream* log_stream = nullptr);
|
||||
explicit MemoryStream(std::unique_ptr<OutputBuffer>&&,
|
||||
Stream* log_stream = nullptr);
|
||||
@ -178,7 +180,7 @@ class MemoryStream : public Stream {
|
||||
|
||||
void Clear();
|
||||
|
||||
Result WriteToFile(string_view filename) {
|
||||
Result WriteToFile(std::string_view filename) {
|
||||
return buf_->WriteToFile(filename);
|
||||
}
|
||||
|
||||
@ -196,7 +198,7 @@ class MemoryStream : public Stream {
|
||||
class FileStream : public Stream {
|
||||
public:
|
||||
WABT_DISALLOW_COPY_AND_ASSIGN(FileStream);
|
||||
explicit FileStream(string_view filename, Stream* log_stream = nullptr);
|
||||
explicit FileStream(std::string_view filename, Stream* log_stream = nullptr);
|
||||
explicit FileStream(FILE*, Stream* log_stream = nullptr);
|
||||
FileStream(FileStream&&);
|
||||
FileStream& operator=(FileStream&&);
|
68
third_party/wasm2c/include/wabt/string-format.h
vendored
Normal file
68
third_party/wasm2c/include/wabt/string-format.h
vendored
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2021 WebAssembly Community Group participants
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef WABT_STRING_FORMAT_H_
|
||||
#define WABT_STRING_FORMAT_H_
|
||||
|
||||
#include <cstdarg>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "wabt/config.h"
|
||||
|
||||
#define PRIstringview "%.*s"
|
||||
#define WABT_PRINTF_STRING_VIEW_ARG(x) \
|
||||
static_cast<int>((x).length()), (x).data()
|
||||
|
||||
#define PRItypecode "%s%#x"
|
||||
#define WABT_PRINTF_TYPE_CODE(x) \
|
||||
(static_cast<int32_t>(x) < 0 ? "-" : ""), std::abs(static_cast<int32_t>(x))
|
||||
|
||||
#define WABT_DEFAULT_SNPRINTF_ALLOCA_BUFSIZE 128
|
||||
#define WABT_SNPRINTF_ALLOCA(buffer, len, format) \
|
||||
va_list args; \
|
||||
va_list args_copy; \
|
||||
va_start(args, format); \
|
||||
va_copy(args_copy, args); \
|
||||
char fixed_buf[WABT_DEFAULT_SNPRINTF_ALLOCA_BUFSIZE]; \
|
||||
char* buffer = fixed_buf; \
|
||||
size_t len = wabt_vsnprintf(fixed_buf, sizeof(fixed_buf), format, args); \
|
||||
va_end(args); \
|
||||
if (len + 1 > sizeof(fixed_buf)) { \
|
||||
buffer = static_cast<char*>(alloca(len + 1)); \
|
||||
len = wabt_vsnprintf(buffer, len + 1, format, args_copy); \
|
||||
} \
|
||||
va_end(args_copy)
|
||||
|
||||
namespace wabt {
|
||||
|
||||
inline std::string WABT_PRINTF_FORMAT(1, 2)
|
||||
StringPrintf(const char* format, ...) {
|
||||
va_list args;
|
||||
va_list args_copy;
|
||||
va_start(args, format);
|
||||
va_copy(args_copy, args);
|
||||
size_t len = wabt_vsnprintf(nullptr, 0, format, args) + 1; // For \0.
|
||||
std::vector<char> buffer(len);
|
||||
va_end(args);
|
||||
wabt_vsnprintf(buffer.data(), len, format, args_copy);
|
||||
va_end(args_copy);
|
||||
return std::string(buffer.data(), len - 1);
|
||||
}
|
||||
|
||||
} // namespace wabt
|
||||
|
||||
#endif // WABT_STRING_FORMAT_H_
|
82
third_party/wasm2c/include/wabt/string-util.h
vendored
Normal file
82
third_party/wasm2c/include/wabt/string-util.h
vendored
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright 2017 WebAssembly Community Group participants
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef WABT_STRING_UTIL_H_
|
||||
#define WABT_STRING_UTIL_H_
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
namespace wabt {
|
||||
|
||||
inline std::string& operator+=(std::string& x, std::string_view y) {
|
||||
x.append(y.data(), y.size());
|
||||
return x;
|
||||
}
|
||||
|
||||
inline std::string operator+(std::string_view x, std::string_view y) {
|
||||
std::string s;
|
||||
s.reserve(x.size() + y.size());
|
||||
s.append(x.data(), x.size());
|
||||
s.append(y.data(), y.size());
|
||||
return s;
|
||||
}
|
||||
|
||||
inline std::string operator+(const std::string& x, std::string_view y) {
|
||||
return std::string_view(x) + y;
|
||||
}
|
||||
|
||||
inline std::string operator+(std::string_view x, const std::string& y) {
|
||||
return x + std::string_view(y);
|
||||
}
|
||||
|
||||
inline std::string operator+(const char* x, std::string_view y) {
|
||||
return std::string_view(x) + y;
|
||||
}
|
||||
|
||||
inline std::string operator+(std::string_view x, const char* y) {
|
||||
return x + std::string_view(y);
|
||||
}
|
||||
|
||||
inline void cat_concatenate(std::string&) {}
|
||||
|
||||
template <typename T, typename... Ts>
|
||||
void cat_concatenate(std::string& s, const T& t, const Ts&... args) {
|
||||
s += t;
|
||||
cat_concatenate(s, args...);
|
||||
}
|
||||
|
||||
inline size_t cat_compute_size() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename T, typename... Ts>
|
||||
size_t cat_compute_size(const T& t, const Ts&... args) {
|
||||
return std::string_view(t).size() + cat_compute_size(args...);
|
||||
}
|
||||
|
||||
// Is able to concatenate any combination of string/string_view/char*
|
||||
template <typename... Ts>
|
||||
std::string cat(const Ts&... args) {
|
||||
std::string s;
|
||||
s.reserve(cat_compute_size(args...));
|
||||
cat_concatenate(s, args...);
|
||||
return s;
|
||||
}
|
||||
|
||||
} // namespace wabt
|
||||
|
||||
#endif // WABT_STRING_UTIL_H_
|
@ -21,6 +21,7 @@
|
||||
/* Tokens with no additional data (i.e. bare). */
|
||||
WABT_TOKEN(Invalid, "Invalid")
|
||||
WABT_TOKEN(Array, "array")
|
||||
WABT_TOKEN(AssertException, "assert_exception")
|
||||
WABT_TOKEN(AssertExhaustion, "assert_exhaustion")
|
||||
WABT_TOKEN(AssertInvalid, "assert_invalid")
|
||||
WABT_TOKEN(AssertMalformed, "assert_malformed")
|
||||
@ -33,6 +34,7 @@ WABT_TOKEN(Data, "data")
|
||||
WABT_TOKEN(Declare, "declare")
|
||||
WABT_TOKEN(Delegate, "delegate")
|
||||
WABT_TOKEN(Do, "do")
|
||||
WABT_TOKEN(Either, "either")
|
||||
WABT_TOKEN(Elem, "elem")
|
||||
WABT_TOKEN(Eof, "EOF")
|
||||
WABT_TOKEN(Tag, "tag")
|
||||
@ -53,6 +55,7 @@ WABT_TOKEN(NanCanonical, "nan:canonical")
|
||||
WABT_TOKEN(Offset, "offset")
|
||||
WABT_TOKEN(Output, "output")
|
||||
WABT_TOKEN(Param, "param")
|
||||
WABT_TOKEN(Ref, "ref")
|
||||
WABT_TOKEN(Quote, "quote")
|
||||
WABT_TOKEN(Register, "register")
|
||||
WABT_TOKEN(Result, "result")
|
@ -17,25 +17,26 @@
|
||||
#ifndef WABT_TOKEN_H_
|
||||
#define WABT_TOKEN_H_
|
||||
|
||||
#include "src/literal.h"
|
||||
#include "src/opcode.h"
|
||||
#include "src/string-view.h"
|
||||
#include <string_view>
|
||||
|
||||
#include "wabt/literal.h"
|
||||
#include "wabt/opcode.h"
|
||||
|
||||
namespace wabt {
|
||||
|
||||
struct Literal {
|
||||
Literal() = default;
|
||||
Literal(LiteralType type, string_view text) : type(type), text(text) {}
|
||||
Literal(LiteralType type, std::string_view text) : type(type), text(text) {}
|
||||
|
||||
LiteralType type;
|
||||
string_view text;
|
||||
std::string_view text;
|
||||
};
|
||||
|
||||
enum class TokenType {
|
||||
#define WABT_TOKEN(name, string) name,
|
||||
#define WABT_TOKEN_FIRST(group, first) First_##group = first,
|
||||
#define WABT_TOKEN_LAST(group, last) Last_##group = last,
|
||||
#include "token.def"
|
||||
#include "wabt/token.def"
|
||||
#undef WABT_TOKEN
|
||||
#undef WABT_TOKEN_FIRST
|
||||
#undef WABT_TOKEN_LAST
|
||||
@ -79,7 +80,7 @@ struct Token {
|
||||
Token() : token_type_(TokenType::Invalid) {}
|
||||
Token(Location, TokenType);
|
||||
Token(Location, TokenType, Type);
|
||||
Token(Location, TokenType, string_view);
|
||||
Token(Location, TokenType, std::string_view);
|
||||
Token(Location, TokenType, Opcode);
|
||||
Token(Location, TokenType, const Literal&);
|
||||
|
||||
@ -94,7 +95,7 @@ struct Token {
|
||||
bool HasOpcode() const { return IsTokenTypeOpcode(token_type_); }
|
||||
bool HasLiteral() const { return IsTokenTypeLiteral(token_type_); }
|
||||
|
||||
string_view text() const {
|
||||
std::string_view text() const {
|
||||
assert(HasText());
|
||||
return text_;
|
||||
}
|
||||
@ -121,7 +122,7 @@ struct Token {
|
||||
TokenType token_type_;
|
||||
|
||||
union {
|
||||
string_view text_;
|
||||
std::string_view text_;
|
||||
Type type_;
|
||||
Opcode opcode_;
|
||||
Literal literal_;
|
@ -29,7 +29,7 @@
|
||||
#define WABT_TRACING 0
|
||||
#endif
|
||||
|
||||
#include "src/common.h"
|
||||
#include "wabt/common.h"
|
||||
|
||||
namespace wabt {
|
||||
|
@ -20,15 +20,15 @@
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
|
||||
#include "src/common.h"
|
||||
#include "src/feature.h"
|
||||
#include "src/opcode.h"
|
||||
#include "wabt/common.h"
|
||||
#include "wabt/feature.h"
|
||||
#include "wabt/opcode.h"
|
||||
|
||||
namespace wabt {
|
||||
|
||||
class TypeChecker {
|
||||
public:
|
||||
typedef std::function<void(const char* msg)> ErrorCallback;
|
||||
using ErrorCallback = std::function<void(const char* msg)>;
|
||||
|
||||
struct Label {
|
||||
Label(LabelType,
|
||||
@ -58,6 +58,7 @@ class TypeChecker {
|
||||
bool IsUnreachable();
|
||||
Result GetLabel(Index depth, Label** out_label);
|
||||
Result GetRethrowLabel(Index depth, Label** out_label);
|
||||
Result GetCatchCount(Index depth, Index* out_depth);
|
||||
|
||||
Result BeginFunction(const TypeVector& sig);
|
||||
Result OnAtomicFence(uint32_t consistency_model);
|
||||
@ -77,9 +78,11 @@ class TypeChecker {
|
||||
Result OnCall(const TypeVector& param_types, const TypeVector& result_types);
|
||||
Result OnCallIndirect(const TypeVector& param_types,
|
||||
const TypeVector& result_types);
|
||||
Result OnFuncRef(Index* out_index);
|
||||
Result OnReturnCall(const TypeVector& param_types, const TypeVector& result_types);
|
||||
Result OnReturnCallIndirect(const TypeVector& param_types, const TypeVector& result_types);
|
||||
Result OnIndexedFuncRef(Index* out_index);
|
||||
Result OnReturnCall(const TypeVector& param_types,
|
||||
const TypeVector& result_types);
|
||||
Result OnReturnCallIndirect(const TypeVector& param_types,
|
||||
const TypeVector& result_types);
|
||||
Result OnCatch(const TypeVector& sig);
|
||||
Result OnCompare(Opcode);
|
||||
Result OnConst(Type);
|
||||
@ -96,7 +99,7 @@ class TypeChecker {
|
||||
Result OnLocalSet(Type);
|
||||
Result OnLocalTee(Type);
|
||||
Result OnLoop(const TypeVector& param_types, const TypeVector& result_types);
|
||||
Result OnMemoryCopy(const Limits& limits);
|
||||
Result OnMemoryCopy(const Limits& srclimits, const Limits& dstlimits);
|
||||
Result OnDataDrop(Index);
|
||||
Result OnMemoryFill(const Limits& limits);
|
||||
Result OnMemoryGrow(const Limits& limits);
|
||||
@ -110,7 +113,7 @@ class TypeChecker {
|
||||
Result OnTableGrow(Type elem_type);
|
||||
Result OnTableSize();
|
||||
Result OnTableFill(Type elem_type);
|
||||
Result OnRefFuncExpr(Index func_index);
|
||||
Result OnRefFuncExpr(Index func_type);
|
||||
Result OnRefNullExpr(Type type);
|
||||
Result OnRefIsNullExpr();
|
||||
Result OnRethrow(Index depth);
|
||||
@ -128,6 +131,9 @@ class TypeChecker {
|
||||
Result OnUnreachable();
|
||||
Result EndFunction();
|
||||
|
||||
Result BeginInitExpr(Type type);
|
||||
Result EndInitExpr();
|
||||
|
||||
static Result CheckType(Type actual, Type expected);
|
||||
|
||||
private:
|
||||
@ -140,17 +146,21 @@ class TypeChecker {
|
||||
const TypeVector& result_types);
|
||||
Result PopLabel();
|
||||
Result CheckLabelType(Label* label, LabelType label_type);
|
||||
Result Check2LabelTypes(Label* label, LabelType label_type1, LabelType label_type2);
|
||||
Result GetThisFunctionLabel(Label **label);
|
||||
Result Check2LabelTypes(Label* label,
|
||||
LabelType label_type1,
|
||||
LabelType label_type2);
|
||||
Result GetThisFunctionLabel(Label** label);
|
||||
Result PeekType(Index depth, Type* out_type);
|
||||
Result PeekAndCheckType(Index depth, Type expected);
|
||||
Result DropTypes(size_t drop_count);
|
||||
void PushType(Type type);
|
||||
void PushTypes(const TypeVector& types);
|
||||
Result CheckTypeStackEnd(const char* desc);
|
||||
Result CheckTypes(const TypeVector &actual, const TypeVector &expected);
|
||||
Result CheckTypes(const TypeVector& actual, const TypeVector& expected);
|
||||
Result CheckSignature(const TypeVector& sig, const char* desc);
|
||||
Result CheckReturnSignature(const TypeVector& sig, const TypeVector &expected,const char *desc);
|
||||
Result CheckReturnSignature(const TypeVector& sig,
|
||||
const TypeVector& expected,
|
||||
const char* desc);
|
||||
Result PopAndCheckSignature(const TypeVector& sig, const char* desc);
|
||||
Result PopAndCheckCall(const TypeVector& param_types,
|
||||
const TypeVector& result_types,
|
||||
@ -161,9 +171,7 @@ class TypeChecker {
|
||||
Type expected2,
|
||||
Type expected3,
|
||||
const char* desc);
|
||||
Result CheckOpcode1(Opcode opcode,
|
||||
const Limits* limits = nullptr,
|
||||
bool has_address_operands = false);
|
||||
Result CheckOpcode1(Opcode opcode, const Limits* limits = nullptr);
|
||||
Result CheckOpcode2(Opcode opcode, const Limits* limits = nullptr);
|
||||
Result CheckOpcode3(Opcode opcode,
|
||||
const Limits* limits1 = nullptr,
|
||||
@ -176,11 +184,14 @@ class TypeChecker {
|
||||
// Minor optimization, check result before constructing the vector to pass
|
||||
// to the other overload of PrintStackIfFailed.
|
||||
if (Failed(result)) {
|
||||
PrintStackIfFailed(result, desc, {args...});
|
||||
PrintStackIfFailedV(result, desc, {args...}, /*is_end=*/false);
|
||||
}
|
||||
}
|
||||
|
||||
void PrintStackIfFailed(Result, const char* desc, const TypeVector&);
|
||||
void PrintStackIfFailedV(Result,
|
||||
const char* desc,
|
||||
const TypeVector&,
|
||||
bool is_end);
|
||||
|
||||
ErrorCallback error_callback_;
|
||||
TypeVector type_stack_;
|
@ -21,13 +21,14 @@
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
#include "config.h"
|
||||
#include "wabt/config.h"
|
||||
#include "wabt/base-types.h"
|
||||
#include "wabt/string-format.h"
|
||||
|
||||
namespace wabt {
|
||||
|
||||
class Type;
|
||||
|
||||
using Index = uint32_t;
|
||||
using TypeVector = std::vector<Type>;
|
||||
|
||||
class Type {
|
||||
@ -43,33 +44,41 @@ class Type {
|
||||
I16 = -0x07, // 0x79 : packed-type only, used in gc and as v128 lane
|
||||
FuncRef = -0x10, // 0x70
|
||||
ExternRef = -0x11, // 0x6f
|
||||
Reference = -0x15, // 0x6b
|
||||
Func = -0x20, // 0x60
|
||||
Struct = -0x21, // 0x5f
|
||||
Array = -0x22, // 0x5e
|
||||
Void = -0x40, // 0x40
|
||||
___ = Void, // Convenient for the opcode table in opcode.h
|
||||
|
||||
Any = 0, // Not actually specified, but useful for type-checking
|
||||
Any = 0, // Not actually specified, but useful for type-checking
|
||||
I8U = 4, // Not actually specified, but used internally with load/store
|
||||
I16U = 6, // Not actually specified, but used internally with load/store
|
||||
I32U = 7, // Not actually specified, but used internally with load/store
|
||||
};
|
||||
|
||||
Type() = default; // Provided so Type can be member of a union.
|
||||
Type(int32_t code) : enum_(static_cast<Enum>(code)) {}
|
||||
Type(Enum e) : enum_(e) {}
|
||||
operator Enum() const { return enum_; }
|
||||
Type(int32_t code)
|
||||
: enum_(static_cast<Enum>(code)), type_index_(kInvalidIndex) {}
|
||||
Type(Enum e) : enum_(e), type_index_(kInvalidIndex) {}
|
||||
Type(Enum e, Index type_index) : enum_(e), type_index_(type_index) {
|
||||
assert(e == Enum::Reference);
|
||||
}
|
||||
constexpr operator Enum() const { return enum_; }
|
||||
|
||||
bool IsRef() const {
|
||||
return enum_ == Type::ExternRef || enum_ == Type::FuncRef;
|
||||
return enum_ == Type::ExternRef || enum_ == Type::FuncRef ||
|
||||
enum_ == Type::Reference;
|
||||
}
|
||||
|
||||
bool IsReferenceWithIndex() const { return enum_ == Type::Reference; }
|
||||
|
||||
bool IsNullableRef() const {
|
||||
// Currently all reftypes are nullable
|
||||
return IsRef();
|
||||
}
|
||||
|
||||
const char* GetName() const {
|
||||
std::string GetName() const {
|
||||
switch (enum_) {
|
||||
case Type::I32: return "i32";
|
||||
case Type::I64: return "i64";
|
||||
@ -83,7 +92,10 @@ class Type {
|
||||
case Type::Void: return "void";
|
||||
case Type::Any: return "any";
|
||||
case Type::ExternRef: return "externref";
|
||||
default: return "<type_index>";
|
||||
case Type::Reference:
|
||||
return StringPrintf("(ref %d)", type_index_);
|
||||
default:
|
||||
return StringPrintf("<type_index[%d]>", enum_);
|
||||
}
|
||||
}
|
||||
|
||||
@ -108,7 +120,7 @@ class Type {
|
||||
// (type $T (func (result i32 i64)))
|
||||
// ...
|
||||
// (block (type $T) ...)
|
||||
//
|
||||
//
|
||||
bool IsIndex() const { return static_cast<int32_t>(enum_) >= 0; }
|
||||
|
||||
Index GetIndex() const {
|
||||
@ -116,6 +128,11 @@ class Type {
|
||||
return static_cast<Index>(enum_);
|
||||
}
|
||||
|
||||
Index GetReferenceIndex() const {
|
||||
assert(enum_ == Enum::Reference);
|
||||
return type_index_;
|
||||
}
|
||||
|
||||
TypeVector GetInlineVector() const {
|
||||
assert(!IsIndex());
|
||||
switch (enum_) {
|
||||
@ -129,6 +146,7 @@ class Type {
|
||||
case Type::V128:
|
||||
case Type::FuncRef:
|
||||
case Type::ExternRef:
|
||||
case Type::Reference:
|
||||
return TypeVector(this, this + 1);
|
||||
|
||||
default:
|
||||
@ -138,6 +156,7 @@ class Type {
|
||||
|
||||
private:
|
||||
Enum enum_;
|
||||
Index type_index_; // Only used for for Type::Reference
|
||||
};
|
||||
|
||||
} // namespace wabt
|
@ -17,7 +17,7 @@
|
||||
#ifndef WABT_UTF8_H_
|
||||
#define WABT_UTF8_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <cstddef>
|
||||
|
||||
namespace wabt {
|
||||
|
@ -17,9 +17,9 @@
|
||||
#ifndef WABT_VALIDATOR_H_
|
||||
#define WABT_VALIDATOR_H_
|
||||
|
||||
#include "src/error.h"
|
||||
#include "src/feature.h"
|
||||
#include "src/shared-validator.h"
|
||||
#include "wabt/error.h"
|
||||
#include "wabt/feature.h"
|
||||
#include "wabt/shared-validator.h"
|
||||
|
||||
namespace wabt {
|
||||
|
||||
@ -33,4 +33,4 @@ Result ValidateModule(const Module*, Errors*, const ValidateOptions&);
|
||||
|
||||
} // namespace wabt
|
||||
|
||||
#endif // WABT_VALIDATOR_H_
|
||||
#endif // WABT_VALIDATOR_H_
|
@ -21,43 +21,45 @@
|
||||
#include <cstdio>
|
||||
#include <memory>
|
||||
|
||||
#include "src/common.h"
|
||||
#include "src/lexer-source-line-finder.h"
|
||||
#include "src/literal.h"
|
||||
#include "src/make-unique.h"
|
||||
#include "src/opcode.h"
|
||||
#include "src/token.h"
|
||||
#include "wabt/common.h"
|
||||
#include "wabt/error.h"
|
||||
#include "wabt/lexer-source-line-finder.h"
|
||||
#include "wabt/literal.h"
|
||||
#include "wabt/opcode.h"
|
||||
#include "wabt/token.h"
|
||||
|
||||
namespace wabt {
|
||||
|
||||
class ErrorHandler;
|
||||
class LexerSource;
|
||||
class WastParser;
|
||||
|
||||
class WastLexer {
|
||||
public:
|
||||
WABT_DISALLOW_COPY_AND_ASSIGN(WastLexer);
|
||||
|
||||
WastLexer(std::unique_ptr<LexerSource> source, string_view filename);
|
||||
WastLexer(std::unique_ptr<LexerSource> source,
|
||||
std::string_view filename,
|
||||
Errors*);
|
||||
|
||||
// Convenience functions.
|
||||
static std::unique_ptr<WastLexer> CreateBufferLexer(string_view filename,
|
||||
static std::unique_ptr<WastLexer> CreateBufferLexer(std::string_view filename,
|
||||
const void* data,
|
||||
size_t size);
|
||||
size_t size,
|
||||
Errors*);
|
||||
|
||||
Token GetToken(WastParser* parser);
|
||||
Token GetToken();
|
||||
|
||||
// TODO(binji): Move this out of the lexer.
|
||||
std::unique_ptr<LexerSourceLineFinder> MakeLineFinder() {
|
||||
return MakeUnique<LexerSourceLineFinder>(source_->Clone());
|
||||
return std::make_unique<LexerSourceLineFinder>(source_->Clone());
|
||||
}
|
||||
|
||||
private:
|
||||
static const int kEof = -1;
|
||||
enum class CharClass { Reserved = 1, Keyword = 2, HexDigit = 4, Digit = 8 };
|
||||
static constexpr int kEof = -1;
|
||||
enum class CharClass { IdChar = 1, Keyword = 2, HexDigit = 4, Digit = 8 };
|
||||
|
||||
Location GetLocation();
|
||||
string_view GetText(size_t offset = 0);
|
||||
std::string_view GetText(size_t offset = 0);
|
||||
|
||||
Token BareToken(TokenType);
|
||||
Token LiteralToken(TokenType, LiteralType);
|
||||
@ -66,9 +68,9 @@ class WastLexer {
|
||||
int PeekChar();
|
||||
int ReadChar();
|
||||
bool MatchChar(char);
|
||||
bool MatchString(string_view);
|
||||
bool MatchString(std::string_view);
|
||||
void Newline();
|
||||
bool ReadBlockComment(WastParser*); // Returns false if EOF.
|
||||
bool ReadBlockComment(); // Returns false if EOF.
|
||||
bool ReadLineComment(); // Returns false if EOF.
|
||||
void ReadWhitespace();
|
||||
|
||||
@ -76,20 +78,24 @@ class WastLexer {
|
||||
static bool IsDigit(int c) { return IsCharClass(c, CharClass::Digit); }
|
||||
static bool IsHexDigit(int c) { return IsCharClass(c, CharClass::HexDigit); }
|
||||
static bool IsKeyword(int c) { return IsCharClass(c, CharClass::Keyword); }
|
||||
static bool IsReserved(int c) { return IsCharClass(c, CharClass::Reserved); }
|
||||
static bool IsIdChar(int c) { return IsCharClass(c, CharClass::IdChar); }
|
||||
|
||||
bool ReadNum();
|
||||
bool ReadHexNum();
|
||||
int ReadReservedChars();
|
||||
bool NoTrailingReservedChars() { return ReadReservedChars() == 0; }
|
||||
|
||||
enum class ReservedChars { None, Some, Id };
|
||||
ReservedChars ReadReservedChars();
|
||||
bool NoTrailingReservedChars() {
|
||||
return ReadReservedChars() == ReservedChars::None;
|
||||
}
|
||||
void ReadSign();
|
||||
Token GetStringToken(WastParser*);
|
||||
Token GetStringToken();
|
||||
Token GetNumberToken(TokenType);
|
||||
Token GetHexNumberToken(TokenType);
|
||||
Token GetInfToken();
|
||||
Token GetNanToken();
|
||||
Token GetNameEqNumToken(string_view name, TokenType);
|
||||
Token GetIdToken();
|
||||
Token GetNameEqNumToken(std::string_view name, TokenType);
|
||||
Token GetIdChars();
|
||||
Token GetKeywordToken();
|
||||
Token GetReservedToken();
|
||||
|
||||
@ -101,6 +107,9 @@ class WastLexer {
|
||||
const char* line_start_;
|
||||
const char* token_start_;
|
||||
const char* cursor_;
|
||||
|
||||
Errors* errors_;
|
||||
void WABT_PRINTF_FORMAT(3, 4) Error(Location, const char* format, ...);
|
||||
};
|
||||
|
||||
} // namespace wabt
|
@ -18,13 +18,15 @@
|
||||
#define WABT_WAST_PARSER_H_
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "src/circular-array.h"
|
||||
#include "src/error.h"
|
||||
#include "src/feature.h"
|
||||
#include "src/intrusive-list.h"
|
||||
#include "src/ir.h"
|
||||
#include "src/wast-lexer.h"
|
||||
#include "wabt/circular-array.h"
|
||||
#include "wabt/error.h"
|
||||
#include "wabt/feature.h"
|
||||
#include "wabt/intrusive-list.h"
|
||||
#include "wabt/ir.h"
|
||||
#include "wabt/wast-lexer.h"
|
||||
|
||||
namespace wabt {
|
||||
|
||||
@ -35,7 +37,7 @@ struct WastParseOptions {
|
||||
bool debug_parsing = false;
|
||||
};
|
||||
|
||||
typedef std::array<TokenType, 2> TokenTypePair;
|
||||
using TokenTypePair = std::array<TokenType, 2>;
|
||||
|
||||
class WastParser {
|
||||
public:
|
||||
@ -81,7 +83,7 @@ class WastParser {
|
||||
TokenTypePair PeekPair();
|
||||
|
||||
// Returns true if the next token's type is equal to the parameter.
|
||||
bool PeekMatch(TokenType);
|
||||
bool PeekMatch(TokenType, size_t n = 0);
|
||||
|
||||
// Returns true if the next token's type is '(' and the following token is
|
||||
// equal to the parameter.
|
||||
@ -91,6 +93,9 @@ class WastParser {
|
||||
// folded expressions, plain instructions and block instructions.
|
||||
bool PeekMatchExpr();
|
||||
|
||||
// Returns true if the next two tokens are form reference type - (ref $t)
|
||||
bool PeekMatchRefType();
|
||||
|
||||
// Returns true if the next token's type is equal to the parameter. If so,
|
||||
// then the token is consumed.
|
||||
bool Match(TokenType);
|
||||
@ -110,7 +115,7 @@ class WastParser {
|
||||
// token (used for printing better error messages).
|
||||
void ConsumeIfLpar() { Match(TokenType::Lpar); }
|
||||
|
||||
typedef bool SynchronizeFunc(TokenTypePair pair);
|
||||
using SynchronizeFunc = bool(*)(TokenTypePair pair);
|
||||
|
||||
// Attempt to synchronize the token stream by dropping tokens until the
|
||||
// SynchronizeFunc returns true, or until a token limit is reached. This
|
||||
@ -126,17 +131,20 @@ class WastParser {
|
||||
Result ParseTextList(std::vector<uint8_t>* out_data);
|
||||
bool ParseTextListOpt(std::vector<uint8_t>* out_data);
|
||||
Result ParseVarList(VarVector* out_var_list);
|
||||
bool ParseElemExprOpt(ElemExpr* out_elem_expr);
|
||||
bool ParseElemExprListOpt(ElemExprVector* out_list);
|
||||
bool ParseElemExprVarListOpt(ElemExprVector* out_list);
|
||||
Result ParseValueType(Type* out_type);
|
||||
Result ParseValueTypeList(TypeVector* out_type_list);
|
||||
bool ParseElemExprOpt(ExprList* out_elem_expr);
|
||||
bool ParseElemExprListOpt(ExprListVector* out_list);
|
||||
bool ParseElemExprVarListOpt(ExprListVector* out_list);
|
||||
Result ParseValueType(Var* out_type);
|
||||
Result ParseValueTypeList(
|
||||
TypeVector* out_type_list,
|
||||
std::unordered_map<uint32_t, std::string>* type_names);
|
||||
Result ParseRefKind(Type* out_type);
|
||||
Result ParseRefType(Type* out_type);
|
||||
bool ParseRefTypeOpt(Type* out_type);
|
||||
Result ParseQuotedText(std::string* text);
|
||||
Result ParseQuotedText(std::string* text, bool check_utf8 = true);
|
||||
bool ParseOffsetOpt(Address* offset);
|
||||
bool ParseAlignOpt(Address* align);
|
||||
Result ParseMemidx(Location loc, Var* memidx);
|
||||
Result ParseLimitsIndex(Limits*);
|
||||
Result ParseLimits(Limits*);
|
||||
Result ParseNat(uint64_t*, bool is_64);
|
||||
@ -164,16 +172,23 @@ class WastParser {
|
||||
Result ParseBoundValueTypeList(TokenType,
|
||||
TypeVector*,
|
||||
BindingHash*,
|
||||
std::unordered_map<uint32_t, std::string>*,
|
||||
Index binding_index_offset = 0);
|
||||
Result ParseUnboundValueTypeList(TokenType, TypeVector*);
|
||||
Result ParseResultList(TypeVector*);
|
||||
Result ParseUnboundValueTypeList(TokenType,
|
||||
TypeVector*,
|
||||
std::unordered_map<uint32_t, std::string>*);
|
||||
Result ParseResultList(TypeVector*,
|
||||
std::unordered_map<uint32_t, std::string>*);
|
||||
Result ParseInstrList(ExprList*);
|
||||
Result ParseTerminatingInstrList(ExprList*);
|
||||
Result ParseInstr(ExprList*);
|
||||
Result ParseCodeMetadataAnnotation(ExprList*);
|
||||
Result ParsePlainInstr(std::unique_ptr<Expr>*);
|
||||
Result ParseF32(Const*, ConstType type);
|
||||
Result ParseF64(Const*, ConstType type);
|
||||
Result ParseConst(Const*, ConstType type);
|
||||
Result ParseExpectedValues(ExpectationPtr*);
|
||||
Result ParseEither(ConstVector*);
|
||||
Result ParseExternref(Const*);
|
||||
Result ParseExpectedNan(ExpectedNan* expected);
|
||||
Result ParseConstList(ConstVector*, ConstType type);
|
||||
@ -193,11 +208,22 @@ class WastParser {
|
||||
template <typename T>
|
||||
Result ParsePlainInstrVar(Location, std::unique_ptr<Expr>*);
|
||||
template <typename T>
|
||||
Result ParsePlainLoadStoreInstr(Location, Token, std::unique_ptr<Expr>*);
|
||||
Result ParseMemoryInstrVar(Location, std::unique_ptr<Expr>*);
|
||||
template <typename T>
|
||||
Result ParseLoadStoreInstr(Location, Token, std::unique_ptr<Expr>*);
|
||||
template <typename T>
|
||||
Result ParseSIMDLoadStoreInstr(Location loc,
|
||||
Token token,
|
||||
std::unique_ptr<Expr>* out_expr);
|
||||
template <typename T>
|
||||
Result ParseMemoryExpr(Location, std::unique_ptr<Expr>*);
|
||||
template <typename T>
|
||||
Result ParseMemoryBinaryExpr(Location, std::unique_ptr<Expr>*);
|
||||
Result ParseSimdLane(Location, uint64_t*);
|
||||
|
||||
Result ParseCommandList(Script*, CommandPtrVector*);
|
||||
Result ParseCommand(Script*, CommandPtr*);
|
||||
Result ParseAssertExceptionCommand(CommandPtr*);
|
||||
Result ParseAssertExhaustionCommand(CommandPtr*);
|
||||
Result ParseAssertInvalidCommand(CommandPtr*);
|
||||
Result ParseAssertMalformedCommand(CommandPtr*);
|
@ -17,7 +17,8 @@
|
||||
#ifndef WABT_WAT_WRITER_H_
|
||||
#define WABT_WAT_WRITER_H_
|
||||
|
||||
#include "src/common.h"
|
||||
#include "wabt/common.h"
|
||||
#include "wabt/feature.h"
|
||||
|
||||
namespace wabt {
|
||||
|
||||
@ -25,6 +26,9 @@ struct Module;
|
||||
class Stream;
|
||||
|
||||
struct WriteWatOptions {
|
||||
WriteWatOptions() = default;
|
||||
WriteWatOptions(const Features& features) : features(features) {}
|
||||
Features features;
|
||||
bool fold_exprs = false; // Write folded expressions.
|
||||
bool inline_export = false;
|
||||
bool inline_import = false;
|
131
third_party/wasm2c/src/apply-names.cc
vendored
131
third_party/wasm2c/src/apply-names.cc
vendored
@ -14,15 +14,16 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "src/apply-names.h"
|
||||
#include "wabt/apply-names.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include "src/expr-visitor.h"
|
||||
#include "src/ir.h"
|
||||
#include "src/string-view.h"
|
||||
#include "wabt/cast.h"
|
||||
#include "wabt/expr-visitor.h"
|
||||
#include "wabt/ir.h"
|
||||
|
||||
namespace wabt {
|
||||
|
||||
@ -49,13 +50,18 @@ class NameApplier : public ExprVisitor::DelegateNop {
|
||||
Result OnGlobalSetExpr(GlobalSetExpr*) override;
|
||||
Result BeginIfExpr(IfExpr*) override;
|
||||
Result EndIfExpr(IfExpr*) override;
|
||||
Result OnLoadExpr(LoadExpr*) override;
|
||||
Result OnLocalGetExpr(LocalGetExpr*) override;
|
||||
Result OnLocalSetExpr(LocalSetExpr*) override;
|
||||
Result OnLocalTeeExpr(LocalTeeExpr*) override;
|
||||
Result BeginLoopExpr(LoopExpr*) override;
|
||||
Result EndLoopExpr(LoopExpr*) override;
|
||||
Result OnMemoryCopyExpr(MemoryCopyExpr*) override;
|
||||
Result OnDataDropExpr(DataDropExpr*) override;
|
||||
Result OnMemoryFillExpr(MemoryFillExpr*) override;
|
||||
Result OnMemoryGrowExpr(MemoryGrowExpr*) override;
|
||||
Result OnMemoryInitExpr(MemoryInitExpr*) override;
|
||||
Result OnMemorySizeExpr(MemorySizeExpr*) override;
|
||||
Result OnElemDropExpr(ElemDropExpr*) override;
|
||||
Result OnTableCopyExpr(TableCopyExpr*) override;
|
||||
Result OnTableInitExpr(TableInitExpr*) override;
|
||||
@ -64,18 +70,21 @@ class NameApplier : public ExprVisitor::DelegateNop {
|
||||
Result OnTableGrowExpr(TableGrowExpr*) override;
|
||||
Result OnTableSizeExpr(TableSizeExpr*) override;
|
||||
Result OnTableFillExpr(TableFillExpr*) override;
|
||||
Result OnStoreExpr(StoreExpr*) override;
|
||||
Result BeginTryExpr(TryExpr*) override;
|
||||
Result EndTryExpr(TryExpr*) override;
|
||||
Result OnCatchExpr(TryExpr*, Catch*) override;
|
||||
Result OnDelegateExpr(TryExpr*) override;
|
||||
Result OnThrowExpr(ThrowExpr*) override;
|
||||
Result OnRethrowExpr(RethrowExpr*) override;
|
||||
Result OnSimdLoadLaneExpr(SimdLoadLaneExpr*) override;
|
||||
Result OnSimdStoreLaneExpr(SimdStoreLaneExpr*) override;
|
||||
|
||||
private:
|
||||
void PushLabel(const std::string& label);
|
||||
void PopLabel();
|
||||
string_view FindLabelByVar(Var* var);
|
||||
void UseNameForVar(string_view name, Var* var);
|
||||
std::string_view FindLabelByVar(Var* var);
|
||||
void UseNameForVar(std::string_view name, Var* var);
|
||||
Result UseNameForFuncTypeVar(Var* var);
|
||||
Result UseNameForFuncVar(Var* var);
|
||||
Result UseNameForGlobalVar(Var* var);
|
||||
@ -110,7 +119,7 @@ void NameApplier::PopLabel() {
|
||||
labels_.pop_back();
|
||||
}
|
||||
|
||||
string_view NameApplier::FindLabelByVar(Var* var) {
|
||||
std::string_view NameApplier::FindLabelByVar(Var* var) {
|
||||
if (var->is_name()) {
|
||||
for (int i = labels_.size() - 1; i >= 0; --i) {
|
||||
const std::string& label = labels_[i];
|
||||
@ -118,16 +127,16 @@ string_view NameApplier::FindLabelByVar(Var* var) {
|
||||
return label;
|
||||
}
|
||||
}
|
||||
return string_view();
|
||||
return std::string_view();
|
||||
} else {
|
||||
if (var->index() >= labels_.size()) {
|
||||
return string_view();
|
||||
return std::string_view();
|
||||
}
|
||||
return labels_[labels_.size() - 1 - var->index()];
|
||||
}
|
||||
}
|
||||
|
||||
void NameApplier::UseNameForVar(string_view name, Var* var) {
|
||||
void NameApplier::UseNameForVar(std::string_view name, Var* var) {
|
||||
if (var->is_name()) {
|
||||
assert(name == var->name());
|
||||
return;
|
||||
@ -253,12 +262,34 @@ Result NameApplier::OnDataDropExpr(DataDropExpr* expr) {
|
||||
return Result::Ok;
|
||||
}
|
||||
|
||||
Result NameApplier::OnMemoryInitExpr(MemoryInitExpr* expr) {
|
||||
CHECK_RESULT(UseNameForDataSegmentVar(&expr->var));
|
||||
Result NameApplier::OnMemoryCopyExpr(MemoryCopyExpr* expr) {
|
||||
CHECK_RESULT(UseNameForMemoryVar(&expr->srcmemidx));
|
||||
CHECK_RESULT(UseNameForMemoryVar(&expr->destmemidx));
|
||||
return Result::Ok;
|
||||
}
|
||||
|
||||
Result NameApplier::OnElemDropExpr(ElemDropExpr* expr) {
|
||||
Result NameApplier::OnMemoryFillExpr(MemoryFillExpr* expr) {
|
||||
CHECK_RESULT(UseNameForMemoryVar(&expr->memidx));
|
||||
return Result::Ok;
|
||||
}
|
||||
|
||||
Result NameApplier::OnMemoryGrowExpr(MemoryGrowExpr* expr) {
|
||||
CHECK_RESULT(UseNameForMemoryVar(&expr->memidx));
|
||||
return Result::Ok;
|
||||
}
|
||||
|
||||
Result NameApplier::OnMemoryInitExpr(MemoryInitExpr* expr) {
|
||||
CHECK_RESULT(UseNameForDataSegmentVar(&expr->var));
|
||||
CHECK_RESULT(UseNameForMemoryVar(&expr->memidx));
|
||||
return Result::Ok;
|
||||
}
|
||||
|
||||
Result NameApplier::OnMemorySizeExpr(MemorySizeExpr* expr) {
|
||||
CHECK_RESULT(UseNameForMemoryVar(&expr->memidx));
|
||||
return Result::Ok;
|
||||
}
|
||||
|
||||
Result NameApplier::OnElemDropExpr(ElemDropExpr* expr) {
|
||||
CHECK_RESULT(UseNameForElemSegmentVar(&expr->var));
|
||||
return Result::Ok;
|
||||
}
|
||||
@ -269,56 +300,61 @@ Result NameApplier::OnTableCopyExpr(TableCopyExpr* expr) {
|
||||
return Result::Ok;
|
||||
}
|
||||
|
||||
Result NameApplier::OnTableInitExpr(TableInitExpr* expr) {
|
||||
Result NameApplier::OnTableInitExpr(TableInitExpr* expr) {
|
||||
CHECK_RESULT(UseNameForElemSegmentVar(&expr->segment_index));
|
||||
CHECK_RESULT(UseNameForTableVar(&expr->table_index));
|
||||
return Result::Ok;
|
||||
}
|
||||
|
||||
Result NameApplier::OnTableGetExpr(TableGetExpr* expr) {
|
||||
Result NameApplier::OnTableGetExpr(TableGetExpr* expr) {
|
||||
CHECK_RESULT(UseNameForTableVar(&expr->var));
|
||||
return Result::Ok;
|
||||
}
|
||||
|
||||
Result NameApplier::OnTableSetExpr(TableSetExpr* expr) {
|
||||
Result NameApplier::OnTableSetExpr(TableSetExpr* expr) {
|
||||
CHECK_RESULT(UseNameForTableVar(&expr->var));
|
||||
return Result::Ok;
|
||||
}
|
||||
|
||||
Result NameApplier::OnTableGrowExpr(TableGrowExpr* expr) {
|
||||
Result NameApplier::OnTableGrowExpr(TableGrowExpr* expr) {
|
||||
CHECK_RESULT(UseNameForTableVar(&expr->var));
|
||||
return Result::Ok;
|
||||
}
|
||||
|
||||
Result NameApplier::OnTableSizeExpr(TableSizeExpr* expr) {
|
||||
Result NameApplier::OnTableSizeExpr(TableSizeExpr* expr) {
|
||||
CHECK_RESULT(UseNameForTableVar(&expr->var));
|
||||
return Result::Ok;
|
||||
}
|
||||
|
||||
Result NameApplier::OnTableFillExpr(TableFillExpr* expr) {
|
||||
Result NameApplier::OnTableFillExpr(TableFillExpr* expr) {
|
||||
CHECK_RESULT(UseNameForTableVar(&expr->var));
|
||||
return Result::Ok;
|
||||
}
|
||||
|
||||
Result NameApplier::OnStoreExpr(StoreExpr* expr) {
|
||||
CHECK_RESULT(UseNameForMemoryVar(&expr->memidx));
|
||||
return Result::Ok;
|
||||
}
|
||||
|
||||
Result NameApplier::OnBrExpr(BrExpr* expr) {
|
||||
string_view label = FindLabelByVar(&expr->var);
|
||||
std::string_view label = FindLabelByVar(&expr->var);
|
||||
UseNameForVar(label, &expr->var);
|
||||
return Result::Ok;
|
||||
}
|
||||
|
||||
Result NameApplier::OnBrIfExpr(BrIfExpr* expr) {
|
||||
string_view label = FindLabelByVar(&expr->var);
|
||||
std::string_view label = FindLabelByVar(&expr->var);
|
||||
UseNameForVar(label, &expr->var);
|
||||
return Result::Ok;
|
||||
}
|
||||
|
||||
Result NameApplier::OnBrTableExpr(BrTableExpr* expr) {
|
||||
for (Var& target : expr->targets) {
|
||||
string_view label = FindLabelByVar(&target);
|
||||
std::string_view label = FindLabelByVar(&target);
|
||||
UseNameForVar(label, &target);
|
||||
}
|
||||
|
||||
string_view label = FindLabelByVar(&expr->default_target);
|
||||
std::string_view label = FindLabelByVar(&expr->default_target);
|
||||
UseNameForVar(label, &expr->default_target);
|
||||
return Result::Ok;
|
||||
}
|
||||
@ -341,7 +377,8 @@ Result NameApplier::OnCatchExpr(TryExpr*, Catch* expr) {
|
||||
}
|
||||
|
||||
Result NameApplier::OnDelegateExpr(TryExpr* expr) {
|
||||
string_view label = FindLabelByVar(&expr->delegate_target);
|
||||
PopLabel();
|
||||
std::string_view label = FindLabelByVar(&expr->delegate_target);
|
||||
UseNameForVar(label, &expr->delegate_target);
|
||||
return Result::Ok;
|
||||
}
|
||||
@ -352,7 +389,7 @@ Result NameApplier::OnThrowExpr(ThrowExpr* expr) {
|
||||
}
|
||||
|
||||
Result NameApplier::OnRethrowExpr(RethrowExpr* expr) {
|
||||
string_view label = FindLabelByVar(&expr->var);
|
||||
std::string_view label = FindLabelByVar(&expr->var);
|
||||
UseNameForVar(label, &expr->var);
|
||||
return Result::Ok;
|
||||
}
|
||||
@ -408,6 +445,11 @@ Result NameApplier::EndIfExpr(IfExpr* expr) {
|
||||
return Result::Ok;
|
||||
}
|
||||
|
||||
Result NameApplier::OnLoadExpr(LoadExpr* expr) {
|
||||
CHECK_RESULT(UseNameForMemoryVar(&expr->memidx));
|
||||
return Result::Ok;
|
||||
}
|
||||
|
||||
Result NameApplier::OnGlobalSetExpr(GlobalSetExpr* expr) {
|
||||
CHECK_RESULT(UseNameForGlobalVar(&expr->var));
|
||||
return Result::Ok;
|
||||
@ -423,6 +465,16 @@ Result NameApplier::OnLocalTeeExpr(LocalTeeExpr* expr) {
|
||||
return Result::Ok;
|
||||
}
|
||||
|
||||
Result NameApplier::OnSimdLoadLaneExpr(SimdLoadLaneExpr* expr) {
|
||||
CHECK_RESULT(UseNameForMemoryVar(&expr->memidx));
|
||||
return Result::Ok;
|
||||
}
|
||||
|
||||
Result NameApplier::OnSimdStoreLaneExpr(SimdStoreLaneExpr* expr) {
|
||||
CHECK_RESULT(UseNameForMemoryVar(&expr->memidx));
|
||||
return Result::Ok;
|
||||
}
|
||||
|
||||
Result NameApplier::VisitFunc(Index func_index, Func* func) {
|
||||
current_func_ = func;
|
||||
if (func->decl.has_func_type) {
|
||||
@ -450,8 +502,26 @@ Result NameApplier::VisitTag(Tag* tag) {
|
||||
}
|
||||
|
||||
Result NameApplier::VisitExport(Index export_index, Export* export_) {
|
||||
if (export_->kind == ExternalKind::Func) {
|
||||
UseNameForFuncVar(&export_->var);
|
||||
switch (export_->kind) {
|
||||
case ExternalKind::Func:
|
||||
UseNameForFuncVar(&export_->var);
|
||||
break;
|
||||
|
||||
case ExternalKind::Table:
|
||||
UseNameForTableVar(&export_->var);
|
||||
break;
|
||||
|
||||
case ExternalKind::Memory:
|
||||
UseNameForMemoryVar(&export_->var);
|
||||
break;
|
||||
|
||||
case ExternalKind::Global:
|
||||
UseNameForGlobalVar(&export_->var);
|
||||
break;
|
||||
|
||||
case ExternalKind::Tag:
|
||||
UseNameForTagVar(&export_->var);
|
||||
break;
|
||||
}
|
||||
return Result::Ok;
|
||||
}
|
||||
@ -460,9 +530,10 @@ Result NameApplier::VisitElemSegment(Index elem_segment_index,
|
||||
ElemSegment* segment) {
|
||||
CHECK_RESULT(UseNameForTableVar(&segment->table_var));
|
||||
CHECK_RESULT(visitor_.VisitExprList(segment->offset));
|
||||
for (ElemExpr& elem_expr : segment->elem_exprs) {
|
||||
if (elem_expr.kind == ElemExprKind::RefFunc) {
|
||||
CHECK_RESULT(UseNameForFuncVar(&elem_expr.var));
|
||||
for (ExprList& elem_expr : segment->elem_exprs) {
|
||||
Expr* expr = &elem_expr.front();
|
||||
if (expr->type() == ExprType::RefFunc) {
|
||||
CHECK_RESULT(UseNameForFuncVar(&cast<RefFuncExpr>(expr)->var));
|
||||
}
|
||||
}
|
||||
return Result::Ok;
|
||||
|
801
third_party/wasm2c/src/binary-reader-ir.cc
vendored
801
third_party/wasm2c/src/binary-reader-ir.cc
vendored
File diff suppressed because it is too large
Load Diff
239
third_party/wasm2c/src/binary-reader-logging.cc
vendored
239
third_party/wasm2c/src/binary-reader-logging.cc
vendored
@ -14,11 +14,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "src/binary-reader-logging.h"
|
||||
#include "wabt/binary-reader-logging.h"
|
||||
|
||||
#include <cinttypes>
|
||||
|
||||
#include "src/stream.h"
|
||||
#include "wabt/stream.h"
|
||||
|
||||
namespace wabt {
|
||||
|
||||
@ -80,7 +80,7 @@ void BinaryReaderLogging::LogType(Type type) {
|
||||
if (type.IsIndex()) {
|
||||
LOGF_NOINDENT("typeidx[%d]", type.GetIndex());
|
||||
} else {
|
||||
LOGF_NOINDENT("%s", type.GetName());
|
||||
LOGF_NOINDENT("%s", type.GetName().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
@ -132,7 +132,7 @@ Result BinaryReaderLogging::BeginSection(Index section_index,
|
||||
|
||||
Result BinaryReaderLogging::BeginCustomSection(Index section_index,
|
||||
Offset size,
|
||||
string_view section_name) {
|
||||
std::string_view section_name) {
|
||||
LOGF("BeginCustomSection('" PRIstringview "', size: %" PRIzd ")\n",
|
||||
WABT_PRINTF_STRING_VIEW_ARG(section_name), size);
|
||||
Indent();
|
||||
@ -177,8 +177,8 @@ Result BinaryReaderLogging::OnArrayType(Index index, TypeMut field) {
|
||||
|
||||
Result BinaryReaderLogging::OnImport(Index index,
|
||||
ExternalKind kind,
|
||||
string_view module_name,
|
||||
string_view field_name) {
|
||||
std::string_view module_name,
|
||||
std::string_view field_name) {
|
||||
LOGF("OnImport(index: %" PRIindex ", kind: %s, module: \"" PRIstringview
|
||||
"\", field: \"" PRIstringview "\")\n",
|
||||
index, GetKindName(kind), WABT_PRINTF_STRING_VIEW_ARG(module_name),
|
||||
@ -187,8 +187,8 @@ Result BinaryReaderLogging::OnImport(Index index,
|
||||
}
|
||||
|
||||
Result BinaryReaderLogging::OnImportFunc(Index import_index,
|
||||
string_view module_name,
|
||||
string_view field_name,
|
||||
std::string_view module_name,
|
||||
std::string_view field_name,
|
||||
Index func_index,
|
||||
Index sig_index) {
|
||||
LOGF("OnImportFunc(import_index: %" PRIindex ", func_index: %" PRIindex
|
||||
@ -199,8 +199,8 @@ Result BinaryReaderLogging::OnImportFunc(Index import_index,
|
||||
}
|
||||
|
||||
Result BinaryReaderLogging::OnImportTable(Index import_index,
|
||||
string_view module_name,
|
||||
string_view field_name,
|
||||
std::string_view module_name,
|
||||
std::string_view field_name,
|
||||
Index table_index,
|
||||
Type elem_type,
|
||||
const Limits* elem_limits) {
|
||||
@ -208,14 +208,14 @@ Result BinaryReaderLogging::OnImportTable(Index import_index,
|
||||
SPrintLimits(buf, sizeof(buf), elem_limits);
|
||||
LOGF("OnImportTable(import_index: %" PRIindex ", table_index: %" PRIindex
|
||||
", elem_type: %s, %s)\n",
|
||||
import_index, table_index, elem_type.GetName(), buf);
|
||||
import_index, table_index, elem_type.GetName().c_str(), buf);
|
||||
return reader_->OnImportTable(import_index, module_name, field_name,
|
||||
table_index, elem_type, elem_limits);
|
||||
}
|
||||
|
||||
Result BinaryReaderLogging::OnImportMemory(Index import_index,
|
||||
string_view module_name,
|
||||
string_view field_name,
|
||||
std::string_view module_name,
|
||||
std::string_view field_name,
|
||||
Index memory_index,
|
||||
const Limits* page_limits) {
|
||||
char buf[100];
|
||||
@ -228,22 +228,23 @@ Result BinaryReaderLogging::OnImportMemory(Index import_index,
|
||||
}
|
||||
|
||||
Result BinaryReaderLogging::OnImportGlobal(Index import_index,
|
||||
string_view module_name,
|
||||
string_view field_name,
|
||||
std::string_view module_name,
|
||||
std::string_view field_name,
|
||||
Index global_index,
|
||||
Type type,
|
||||
bool mutable_) {
|
||||
LOGF("OnImportGlobal(import_index: %" PRIindex ", global_index: %" PRIindex
|
||||
", type: %s, mutable: "
|
||||
"%s)\n",
|
||||
import_index, global_index, type.GetName(), mutable_ ? "true" : "false");
|
||||
import_index, global_index, type.GetName().c_str(),
|
||||
mutable_ ? "true" : "false");
|
||||
return reader_->OnImportGlobal(import_index, module_name, field_name,
|
||||
global_index, type, mutable_);
|
||||
}
|
||||
|
||||
Result BinaryReaderLogging::OnImportTag(Index import_index,
|
||||
string_view module_name,
|
||||
string_view field_name,
|
||||
std::string_view module_name,
|
||||
std::string_view field_name,
|
||||
Index tag_index,
|
||||
Index sig_index) {
|
||||
LOGF("OnImportTag(import_index: %" PRIindex ", tag_index: %" PRIindex
|
||||
@ -259,7 +260,7 @@ Result BinaryReaderLogging::OnTable(Index index,
|
||||
char buf[100];
|
||||
SPrintLimits(buf, sizeof(buf), elem_limits);
|
||||
LOGF("OnTable(index: %" PRIindex ", elem_type: %s, %s)\n", index,
|
||||
elem_type.GetName(), buf);
|
||||
elem_type.GetName().c_str(), buf);
|
||||
return reader_->OnTable(index, elem_type, elem_limits);
|
||||
}
|
||||
|
||||
@ -272,14 +273,14 @@ Result BinaryReaderLogging::OnMemory(Index index, const Limits* page_limits) {
|
||||
|
||||
Result BinaryReaderLogging::BeginGlobal(Index index, Type type, bool mutable_) {
|
||||
LOGF("BeginGlobal(index: %" PRIindex ", type: %s, mutable: %s)\n", index,
|
||||
type.GetName(), mutable_ ? "true" : "false");
|
||||
type.GetName().c_str(), mutable_ ? "true" : "false");
|
||||
return reader_->BeginGlobal(index, type, mutable_);
|
||||
}
|
||||
|
||||
Result BinaryReaderLogging::OnExport(Index index,
|
||||
ExternalKind kind,
|
||||
Index item_index,
|
||||
string_view name) {
|
||||
std::string_view name) {
|
||||
LOGF("OnExport(index: %" PRIindex ", kind: %s, item_index: %" PRIindex
|
||||
", name: \"" PRIstringview "\")\n",
|
||||
index, GetKindName(kind), item_index, WABT_PRINTF_STRING_VIEW_ARG(name));
|
||||
@ -295,7 +296,7 @@ Result BinaryReaderLogging::OnLocalDecl(Index decl_index,
|
||||
Index count,
|
||||
Type type) {
|
||||
LOGF("OnLocalDecl(index: %" PRIindex ", count: %" PRIindex ", type: %s)\n",
|
||||
decl_index, count, type.GetName());
|
||||
decl_index, count, type.GetName().c_str());
|
||||
return reader_->OnLocalDecl(decl_index, count, type);
|
||||
}
|
||||
|
||||
@ -412,7 +413,7 @@ Result BinaryReaderLogging::BeginElemSegment(Index index,
|
||||
|
||||
Result BinaryReaderLogging::OnElemSegmentElemType(Index index, Type elem_type) {
|
||||
LOGF("OnElemSegmentElemType(index: %" PRIindex ", type: %s)\n", index,
|
||||
elem_type.GetName());
|
||||
elem_type.GetName().c_str());
|
||||
return reader_->OnElemSegmentElemType(index, elem_type);
|
||||
}
|
||||
|
||||
@ -433,7 +434,7 @@ Result BinaryReaderLogging::OnModuleNameSubsection(Index index,
|
||||
return reader_->OnModuleNameSubsection(index, name_type, subsection_size);
|
||||
}
|
||||
|
||||
Result BinaryReaderLogging::OnModuleName(string_view name) {
|
||||
Result BinaryReaderLogging::OnModuleName(std::string_view name) {
|
||||
LOGF("OnModuleName(name: \"" PRIstringview "\")\n",
|
||||
WABT_PRINTF_STRING_VIEW_ARG(name));
|
||||
return reader_->OnModuleName(name);
|
||||
@ -448,7 +449,7 @@ Result BinaryReaderLogging::OnFunctionNameSubsection(Index index,
|
||||
return reader_->OnFunctionNameSubsection(index, name_type, subsection_size);
|
||||
}
|
||||
|
||||
Result BinaryReaderLogging::OnFunctionName(Index index, string_view name) {
|
||||
Result BinaryReaderLogging::OnFunctionName(Index index, std::string_view name) {
|
||||
LOGF("OnFunctionName(index: %" PRIindex ", name: \"" PRIstringview "\")\n",
|
||||
index, WABT_PRINTF_STRING_VIEW_ARG(name));
|
||||
return reader_->OnFunctionName(index, name);
|
||||
@ -465,7 +466,7 @@ Result BinaryReaderLogging::OnLocalNameSubsection(Index index,
|
||||
|
||||
Result BinaryReaderLogging::OnLocalName(Index func_index,
|
||||
Index local_index,
|
||||
string_view name) {
|
||||
std::string_view name) {
|
||||
LOGF("OnLocalName(func_index: %" PRIindex ", local_index: %" PRIindex
|
||||
", name: \"" PRIstringview "\")\n",
|
||||
func_index, local_index, WABT_PRINTF_STRING_VIEW_ARG(name));
|
||||
@ -483,7 +484,7 @@ Result BinaryReaderLogging::OnNameSubsection(
|
||||
|
||||
Result BinaryReaderLogging::OnNameEntry(NameSectionSubsection type,
|
||||
Index index,
|
||||
string_view name) {
|
||||
std::string_view name) {
|
||||
LOGF("OnNameEntry(type: %s, index: %" PRIindex ", name: \"" PRIstringview
|
||||
"\")\n",
|
||||
GetNameSectionSubsectionName(type), index,
|
||||
@ -491,48 +492,6 @@ Result BinaryReaderLogging::OnNameEntry(NameSectionSubsection type,
|
||||
return reader_->OnNameEntry(type, index, name);
|
||||
}
|
||||
|
||||
Result BinaryReaderLogging::OnInitExprF32ConstExpr(Index index,
|
||||
uint32_t value_bits) {
|
||||
float value;
|
||||
memcpy(&value, &value_bits, sizeof(value));
|
||||
LOGF("OnInitExprF32ConstExpr(index: %" PRIindex ", value: %g (0x04%x))\n",
|
||||
index, value, value_bits);
|
||||
return reader_->OnInitExprF32ConstExpr(index, value_bits);
|
||||
}
|
||||
|
||||
Result BinaryReaderLogging::OnInitExprF64ConstExpr(Index index,
|
||||
uint64_t value_bits) {
|
||||
double value;
|
||||
memcpy(&value, &value_bits, sizeof(value));
|
||||
LOGF("OnInitExprF64ConstExpr(index: %" PRIindex " value: %g (0x08%" PRIx64
|
||||
"))\n",
|
||||
index, value, value_bits);
|
||||
return reader_->OnInitExprF64ConstExpr(index, value_bits);
|
||||
}
|
||||
|
||||
Result BinaryReaderLogging::OnInitExprV128ConstExpr(Index index,
|
||||
v128 value_bits) {
|
||||
LOGF("OnInitExprV128ConstExpr(index: %" PRIindex
|
||||
" value: ( 0x%08x 0x%08x 0x%08x 0x%08x))\n",
|
||||
index, value_bits.u32(0), value_bits.u32(1), value_bits.u32(2),
|
||||
value_bits.u32(3));
|
||||
return reader_->OnInitExprV128ConstExpr(index, value_bits);
|
||||
}
|
||||
|
||||
Result BinaryReaderLogging::OnInitExprI32ConstExpr(Index index,
|
||||
uint32_t value) {
|
||||
LOGF("OnInitExprI32ConstExpr(index: %" PRIindex ", value: %u)\n", index,
|
||||
value);
|
||||
return reader_->OnInitExprI32ConstExpr(index, value);
|
||||
}
|
||||
|
||||
Result BinaryReaderLogging::OnInitExprI64ConstExpr(Index index,
|
||||
uint64_t value) {
|
||||
LOGF("OnInitExprI64ConstExpr(index: %" PRIindex ", value: %" PRIu64 ")\n",
|
||||
index, value);
|
||||
return reader_->OnInitExprI64ConstExpr(index, value);
|
||||
}
|
||||
|
||||
Result BinaryReaderLogging::OnDylinkInfo(uint32_t mem_size,
|
||||
uint32_t mem_align,
|
||||
uint32_t table_size,
|
||||
@ -544,14 +503,30 @@ Result BinaryReaderLogging::OnDylinkInfo(uint32_t mem_size,
|
||||
return reader_->OnDylinkInfo(mem_size, mem_align, table_size, table_align);
|
||||
}
|
||||
|
||||
Result BinaryReaderLogging::OnDylinkNeeded(string_view so_name) {
|
||||
Result BinaryReaderLogging::OnDylinkNeeded(std::string_view so_name) {
|
||||
LOGF("OnDylinkNeeded(name: " PRIstringview ")\n",
|
||||
WABT_PRINTF_STRING_VIEW_ARG(so_name));
|
||||
return reader_->OnDylinkNeeded(so_name);
|
||||
}
|
||||
|
||||
Result BinaryReaderLogging::OnRelocCount(Index count,
|
||||
Index section_index) {
|
||||
Result BinaryReaderLogging::OnDylinkExport(std::string_view name,
|
||||
uint32_t flags) {
|
||||
LOGF("OnDylinkExport(name: " PRIstringview ", flags: 0x%x)\n",
|
||||
WABT_PRINTF_STRING_VIEW_ARG(name), flags);
|
||||
return reader_->OnDylinkExport(name, flags);
|
||||
}
|
||||
|
||||
Result BinaryReaderLogging::OnDylinkImport(std::string_view module,
|
||||
std::string_view name,
|
||||
uint32_t flags) {
|
||||
LOGF("OnDylinkImport(module: " PRIstringview ", name: " PRIstringview
|
||||
", flags: 0x%x)\n",
|
||||
WABT_PRINTF_STRING_VIEW_ARG(module), WABT_PRINTF_STRING_VIEW_ARG(name),
|
||||
flags);
|
||||
return reader_->OnDylinkImport(module, name, flags);
|
||||
}
|
||||
|
||||
Result BinaryReaderLogging::OnRelocCount(Index count, Index section_index) {
|
||||
LOGF("OnRelocCount(count: %" PRIindex ", section: %" PRIindex ")\n", count,
|
||||
section_index);
|
||||
return reader_->OnRelocCount(count, section_index);
|
||||
@ -568,9 +543,15 @@ Result BinaryReaderLogging::OnReloc(RelocType type,
|
||||
return reader_->OnReloc(type, offset, index, addend);
|
||||
}
|
||||
|
||||
Result BinaryReaderLogging::OnFeature(uint8_t prefix, std::string_view name) {
|
||||
LOGF("OnFeature(prefix: '%c', name: '" PRIstringview "')\n", prefix,
|
||||
WABT_PRINTF_STRING_VIEW_ARG(name));
|
||||
return reader_->OnFeature(prefix, name);
|
||||
}
|
||||
|
||||
Result BinaryReaderLogging::OnDataSymbol(Index index,
|
||||
uint32_t flags,
|
||||
string_view name,
|
||||
std::string_view name,
|
||||
Index segment,
|
||||
uint32_t offset,
|
||||
uint32_t size) {
|
||||
@ -581,7 +562,7 @@ Result BinaryReaderLogging::OnDataSymbol(Index index,
|
||||
|
||||
Result BinaryReaderLogging::OnFunctionSymbol(Index index,
|
||||
uint32_t flags,
|
||||
string_view name,
|
||||
std::string_view name,
|
||||
Index func_index) {
|
||||
LOGF("OnFunctionSymbol(name: " PRIstringview " flags: 0x%x index: %" PRIindex
|
||||
")\n",
|
||||
@ -591,7 +572,7 @@ Result BinaryReaderLogging::OnFunctionSymbol(Index index,
|
||||
|
||||
Result BinaryReaderLogging::OnGlobalSymbol(Index index,
|
||||
uint32_t flags,
|
||||
string_view name,
|
||||
std::string_view name,
|
||||
Index global_index) {
|
||||
LOGF("OnGlobalSymbol(name: " PRIstringview " flags: 0x%x index: %" PRIindex
|
||||
")\n",
|
||||
@ -609,7 +590,7 @@ Result BinaryReaderLogging::OnSectionSymbol(Index index,
|
||||
|
||||
Result BinaryReaderLogging::OnTagSymbol(Index index,
|
||||
uint32_t flags,
|
||||
string_view name,
|
||||
std::string_view name,
|
||||
Index tag_index) {
|
||||
LOGF("OnTagSymbol(name: " PRIstringview " flags: 0x%x index: %" PRIindex
|
||||
")\n",
|
||||
@ -619,16 +600,16 @@ Result BinaryReaderLogging::OnTagSymbol(Index index,
|
||||
|
||||
Result BinaryReaderLogging::OnTableSymbol(Index index,
|
||||
uint32_t flags,
|
||||
string_view name,
|
||||
std::string_view name,
|
||||
Index table_index) {
|
||||
LOGF("OnTableSymbol(name: " PRIstringview " flags: 0x%x index: %" PRIindex
|
||||
")\n",
|
||||
")\n",
|
||||
WABT_PRINTF_STRING_VIEW_ARG(name), flags, table_index);
|
||||
return reader_->OnTableSymbol(index, flags, name, table_index);
|
||||
}
|
||||
|
||||
Result BinaryReaderLogging::OnSegmentInfo(Index index,
|
||||
string_view name,
|
||||
std::string_view name,
|
||||
Address alignment,
|
||||
uint32_t flags) {
|
||||
LOGF("OnSegmentInfo(%d name: " PRIstringview ", alignment: %" PRIaddress
|
||||
@ -643,7 +624,7 @@ Result BinaryReaderLogging::OnInitFunction(uint32_t priority,
|
||||
return reader_->OnInitFunction(priority, func_index);
|
||||
}
|
||||
|
||||
Result BinaryReaderLogging::OnComdatBegin(string_view name,
|
||||
Result BinaryReaderLogging::OnComdatBegin(std::string_view name,
|
||||
uint32_t flags,
|
||||
Index count) {
|
||||
LOGF("OnComdatBegin(" PRIstringview ", flags: %d, count: %" PRIindex ")\n",
|
||||
@ -657,6 +638,22 @@ Result BinaryReaderLogging::OnComdatEntry(ComdatType kind, Index index) {
|
||||
return reader_->OnComdatEntry(kind, index);
|
||||
}
|
||||
|
||||
Result BinaryReaderLogging::BeginCodeMetadataSection(std::string_view name,
|
||||
Offset size) {
|
||||
LOGF("BeginCodeMetadataSection('" PRIstringview "', size:%" PRIzd ")\n",
|
||||
WABT_PRINTF_STRING_VIEW_ARG(name), size);
|
||||
Indent();
|
||||
return reader_->BeginCodeMetadataSection(name, size);
|
||||
}
|
||||
Result BinaryReaderLogging::OnCodeMetadata(Offset code_offset,
|
||||
const void* data,
|
||||
Address size) {
|
||||
std::string_view content(static_cast<const char*>(data), size);
|
||||
LOGF("OnCodeMetadata(offset: %" PRIzd ", data: \"" PRIstringview "\")\n",
|
||||
code_offset, WABT_PRINTF_STRING_VIEW_ARG(content));
|
||||
return reader_->OnCodeMetadata(code_offset, data, size);
|
||||
}
|
||||
|
||||
#define DEFINE_BEGIN(name) \
|
||||
Result BinaryReaderLogging::name(Offset size) { \
|
||||
LOGF(#name "(%" PRIzd ")\n", size); \
|
||||
@ -677,10 +674,10 @@ Result BinaryReaderLogging::OnComdatEntry(ComdatType kind, Index index) {
|
||||
return reader_->name(value); \
|
||||
}
|
||||
|
||||
#define DEFINE_TYPE(name) \
|
||||
Result BinaryReaderLogging::name(Type type) { \
|
||||
LOGF(#name "(%s)\n", type.GetName()); \
|
||||
return reader_->name(type); \
|
||||
#define DEFINE_TYPE(name) \
|
||||
Result BinaryReaderLogging::name(Type type) { \
|
||||
LOGF(#name "(%s)\n", type.GetName().c_str()); \
|
||||
return reader_->name(type); \
|
||||
}
|
||||
|
||||
#define DEFINE_INDEX_DESC(name, desc) \
|
||||
@ -689,10 +686,11 @@ Result BinaryReaderLogging::OnComdatEntry(ComdatType kind, Index index) {
|
||||
return reader_->name(value); \
|
||||
}
|
||||
|
||||
#define DEFINE_INDEX_TYPE(name) \
|
||||
Result BinaryReaderLogging::name(Index value, Type type) { \
|
||||
LOGF(#name "(index: %" PRIindex ", type: %s)\n", value, type.GetName()); \
|
||||
return reader_->name(value, type); \
|
||||
#define DEFINE_INDEX_TYPE(name) \
|
||||
Result BinaryReaderLogging::name(Index value, Type type) { \
|
||||
LOGF(#name "(index: %" PRIindex ", type: %s)\n", value, \
|
||||
type.GetName().c_str()); \
|
||||
return reader_->name(value, type); \
|
||||
}
|
||||
|
||||
#define DEFINE_INDEX_INDEX(name, desc0, desc1) \
|
||||
@ -717,22 +715,25 @@ Result BinaryReaderLogging::OnComdatEntry(ComdatType kind, Index index) {
|
||||
return reader_->name(opcode); \
|
||||
}
|
||||
|
||||
#define DEFINE_LOAD_STORE_OPCODE(name) \
|
||||
Result BinaryReaderLogging::name(Opcode opcode, Address alignment_log2, \
|
||||
Address offset) { \
|
||||
LOGF(#name "(opcode: \"%s\" (%u), align log2: %" PRIaddress \
|
||||
", offset: %" PRIaddress ")\n", \
|
||||
opcode.GetName(), opcode.GetCode(), alignment_log2, offset); \
|
||||
return reader_->name(opcode, alignment_log2, offset); \
|
||||
#define DEFINE_LOAD_STORE_OPCODE(name) \
|
||||
Result BinaryReaderLogging::name(Opcode opcode, Index memidx, \
|
||||
Address alignment_log2, Address offset) { \
|
||||
LOGF(#name "(opcode: \"%s\" (%u), memidx: %" PRIindex \
|
||||
", align log2: %" PRIaddress ", offset: %" PRIaddress ")\n", \
|
||||
opcode.GetName(), opcode.GetCode(), memidx, alignment_log2, offset); \
|
||||
return reader_->name(opcode, memidx, alignment_log2, offset); \
|
||||
}
|
||||
|
||||
#define DEFINE_SIMD_LOAD_STORE_LANE_OPCODE(name) \
|
||||
Result BinaryReaderLogging::name(Opcode opcode, Address alignment_log2, \
|
||||
Address offset, uint64_t value) { \
|
||||
LOGF(#name "(opcode: \"%s\" (%u), align log2: %" PRIaddress \
|
||||
", offset: %" PRIaddress ", lane: %" PRIu64 ")\n", \
|
||||
opcode.GetName(), opcode.GetCode(), alignment_log2, offset, value); \
|
||||
return reader_->name(opcode, alignment_log2, offset, value); \
|
||||
Result BinaryReaderLogging::name(Opcode opcode, Index memidx, \
|
||||
Address alignment_log2, Address offset, \
|
||||
uint64_t value) { \
|
||||
LOGF(#name "(opcode: \"%s\" (%u), memidx: %" PRIindex \
|
||||
", align log2: %" PRIaddress ", offset: %" PRIaddress \
|
||||
", lane: %" PRIu64 ")\n", \
|
||||
opcode.GetName(), opcode.GetCode(), memidx, alignment_log2, offset, \
|
||||
value); \
|
||||
return reader_->name(opcode, memidx, alignment_log2, offset, value); \
|
||||
}
|
||||
|
||||
#define DEFINE0(name) \
|
||||
@ -810,12 +811,12 @@ DEFINE_LOAD_STORE_OPCODE(OnLoadExpr);
|
||||
DEFINE_INDEX_DESC(OnLocalGetExpr, "index")
|
||||
DEFINE_INDEX_DESC(OnLocalSetExpr, "index")
|
||||
DEFINE_INDEX_DESC(OnLocalTeeExpr, "index")
|
||||
DEFINE0(OnMemoryCopyExpr)
|
||||
DEFINE_INDEX_INDEX(OnMemoryCopyExpr, "src_memory_index", "dest_memory_index")
|
||||
DEFINE_INDEX(OnDataDropExpr)
|
||||
DEFINE0(OnMemoryFillExpr)
|
||||
DEFINE0(OnMemoryGrowExpr)
|
||||
DEFINE_INDEX(OnMemoryInitExpr)
|
||||
DEFINE0(OnMemorySizeExpr)
|
||||
DEFINE_INDEX(OnMemoryFillExpr)
|
||||
DEFINE_INDEX(OnMemoryGrowExpr)
|
||||
DEFINE_INDEX_INDEX(OnMemoryInitExpr, "segment_index", "memory_index")
|
||||
DEFINE_INDEX(OnMemorySizeExpr)
|
||||
DEFINE_INDEX_INDEX(OnTableCopyExpr, "dst_index", "src_index")
|
||||
DEFINE_INDEX(OnElemDropExpr)
|
||||
DEFINE_INDEX_INDEX(OnTableInitExpr, "segment_index", "table_index")
|
||||
@ -876,14 +877,16 @@ DEFINE_END(EndNamesSection)
|
||||
DEFINE_BEGIN(BeginRelocSection)
|
||||
DEFINE_END(EndRelocSection)
|
||||
|
||||
DEFINE_INDEX_INDEX(OnInitExprGlobalGetExpr, "index", "global_index")
|
||||
DEFINE_INDEX_TYPE(OnInitExprRefNull)
|
||||
DEFINE_INDEX_INDEX(OnInitExprRefFunc, "index", "func_index")
|
||||
|
||||
DEFINE_BEGIN(BeginDylinkSection)
|
||||
DEFINE_INDEX(OnDylinkNeededCount)
|
||||
DEFINE_INDEX(OnDylinkExportCount)
|
||||
DEFINE_INDEX(OnDylinkImportCount)
|
||||
DEFINE_END(EndDylinkSection)
|
||||
|
||||
DEFINE_BEGIN(BeginTargetFeaturesSection)
|
||||
DEFINE_INDEX(OnFeatureCount)
|
||||
DEFINE_END(EndTargetFeaturesSection)
|
||||
|
||||
DEFINE_BEGIN(BeginLinkingSection)
|
||||
DEFINE_INDEX(OnSymbolCount)
|
||||
DEFINE_INDEX(OnSegmentInfoCount)
|
||||
@ -896,6 +899,10 @@ DEFINE_INDEX(OnTagCount);
|
||||
DEFINE_INDEX_INDEX(OnTagType, "index", "sig_index")
|
||||
DEFINE_END(EndTagSection);
|
||||
|
||||
DEFINE_INDEX(OnCodeMetadataFuncCount);
|
||||
DEFINE_INDEX_INDEX(OnCodeMetadataCount, "func_index", "count");
|
||||
DEFINE_END(EndCodeMetadataSection);
|
||||
|
||||
// We don't need to log these (the individual opcodes are logged instead), but
|
||||
// we still need to forward the calls.
|
||||
Result BinaryReaderLogging::OnOpcode(Opcode opcode) {
|
||||
@ -929,6 +936,14 @@ Result BinaryReaderLogging::OnOpcodeUint32Uint32Uint32(uint32_t value,
|
||||
return reader_->OnOpcodeUint32Uint32Uint32(value, value2, value3);
|
||||
}
|
||||
|
||||
Result BinaryReaderLogging::OnOpcodeUint32Uint32Uint32Uint32(uint32_t value,
|
||||
uint32_t value2,
|
||||
uint32_t value3,
|
||||
uint32_t value4) {
|
||||
return reader_->OnOpcodeUint32Uint32Uint32Uint32(value, value2, value3,
|
||||
value4);
|
||||
}
|
||||
|
||||
Result BinaryReaderLogging::OnOpcodeUint64(uint64_t value) {
|
||||
return reader_->OnOpcodeUint64(value);
|
||||
}
|
||||
@ -953,8 +968,4 @@ Result BinaryReaderLogging::OnOpcodeType(Type type) {
|
||||
return reader_->OnOpcodeType(type);
|
||||
}
|
||||
|
||||
Result BinaryReaderLogging::OnEndFunc() {
|
||||
return reader_->OnEndFunc();
|
||||
}
|
||||
|
||||
} // namespace wabt
|
||||
|
945
third_party/wasm2c/src/binary-reader-objdump.cc
vendored
945
third_party/wasm2c/src/binary-reader-objdump.cc
vendored
File diff suppressed because it is too large
Load Diff
58
third_party/wasm2c/src/binary-reader-opcnt.cc
vendored
58
third_party/wasm2c/src/binary-reader-opcnt.cc
vendored
@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "src/binary-reader-opcnt.h"
|
||||
#include "wabt/binary-reader-opcnt.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cinttypes>
|
||||
@ -22,10 +22,10 @@
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
|
||||
#include "src/binary-reader-nop.h"
|
||||
#include "src/common.h"
|
||||
#include "src/literal.h"
|
||||
#include "src/stream.h"
|
||||
#include "wabt/binary-reader-nop.h"
|
||||
#include "wabt/common.h"
|
||||
#include "wabt/literal.h"
|
||||
#include "wabt/stream.h"
|
||||
|
||||
namespace wabt {
|
||||
|
||||
@ -61,19 +61,19 @@ std::pair<const T*, size_t> OpcodeInfo::GetDataArray() const {
|
||||
|
||||
template <typename T>
|
||||
const T* OpcodeInfo::GetData(size_t expected_size) const {
|
||||
auto pair = GetDataArray<T>();
|
||||
assert(pair.second == expected_size);
|
||||
return pair.first;
|
||||
auto [data, size] = GetDataArray<T>();
|
||||
assert(size == expected_size);
|
||||
return data;
|
||||
}
|
||||
|
||||
template <typename T, typename F>
|
||||
void OpcodeInfo::WriteArray(Stream& stream, F&& write_func) {
|
||||
auto pair = GetDataArray<T>();
|
||||
for (size_t i = 0; i < pair.second; ++i) {
|
||||
auto [data, size] = GetDataArray<T>();
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
// Write an initial space (to separate from the opcode name) first, then
|
||||
// comma-separate.
|
||||
stream.Writef("%s", i == 0 ? " " : ", ");
|
||||
write_func(pair.first[i]);
|
||||
write_func(data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -113,7 +113,20 @@ void OpcodeInfo::Write(Stream& stream) {
|
||||
break;
|
||||
}
|
||||
|
||||
case Kind::V128: {
|
||||
auto data = *GetData<v128>();
|
||||
auto l0 = data.u32(0);
|
||||
auto l1 = data.u32(1);
|
||||
auto l2 = data.u32(2);
|
||||
auto l3 = data.u32(3);
|
||||
stream.Writef(" %u %u %u %u (0x%x 0x%x 0x%x 0x%x)", l0, l1, l2, l3, l0,
|
||||
l1, l2, l3);
|
||||
break;
|
||||
}
|
||||
|
||||
case Kind::Uint32Uint32:
|
||||
case Kind::Uint32Uint32Uint32:
|
||||
case Kind::Uint32Uint32Uint32Uint32:
|
||||
WriteArray<uint32_t>(
|
||||
stream, [&stream](uint32_t value) { stream.Writef("%u", value); });
|
||||
break;
|
||||
@ -123,7 +136,7 @@ void OpcodeInfo::Write(Stream& stream) {
|
||||
if (type.IsIndex()) {
|
||||
stream.Writef(" type:%d", type.GetIndex());
|
||||
} else if (type != Type::Void) {
|
||||
stream.Writef(" %s", type.GetName());
|
||||
stream.Writef(" %s", type.GetName().c_str());
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -191,15 +204,18 @@ class BinaryReaderOpcnt : public BinaryReaderNop {
|
||||
Result OnOpcodeUint32(uint32_t value) override;
|
||||
Result OnOpcodeIndex(Index value) override;
|
||||
Result OnOpcodeUint32Uint32(uint32_t value, uint32_t value2) override;
|
||||
Result OnOpcodeUint32Uint32Uint32(uint32_t value,
|
||||
uint32_t value2,
|
||||
uint32_t value3) override;
|
||||
Result OnOpcodeUint64(uint64_t value) override;
|
||||
Result OnOpcodeF32(uint32_t value) override;
|
||||
Result OnOpcodeF64(uint64_t value) override;
|
||||
Result OnOpcodeV128(v128 value) override;
|
||||
Result OnOpcodeBlockSig(Type sig_type) override;
|
||||
Result OnBrTableExpr(Index num_targets,
|
||||
Index* target_depths,
|
||||
Index default_target_depth) override;
|
||||
Result OnEndExpr() override;
|
||||
Result OnEndFunc() override;
|
||||
|
||||
private:
|
||||
template <typename... Args>
|
||||
@ -246,6 +262,14 @@ Result BinaryReaderOpcnt::OnOpcodeUint32Uint32(uint32_t value0,
|
||||
return Emplace(current_opcode_, OpcodeInfo::Kind::Uint32Uint32, array, 2);
|
||||
}
|
||||
|
||||
Result BinaryReaderOpcnt::OnOpcodeUint32Uint32Uint32(uint32_t value0,
|
||||
uint32_t value1,
|
||||
uint32_t value2) {
|
||||
uint32_t array[3] = {value0, value1, value2};
|
||||
return Emplace(current_opcode_, OpcodeInfo::Kind::Uint32Uint32Uint32, array,
|
||||
3);
|
||||
}
|
||||
|
||||
Result BinaryReaderOpcnt::OnOpcodeUint64(uint64_t value) {
|
||||
return Emplace(current_opcode_, OpcodeInfo::Kind::Uint64, &value);
|
||||
}
|
||||
@ -258,6 +282,10 @@ Result BinaryReaderOpcnt::OnOpcodeF64(uint64_t value) {
|
||||
return Emplace(current_opcode_, OpcodeInfo::Kind::Float64, &value);
|
||||
}
|
||||
|
||||
Result BinaryReaderOpcnt::OnOpcodeV128(v128 value) {
|
||||
return Emplace(current_opcode_, OpcodeInfo::Kind::V128, &value);
|
||||
}
|
||||
|
||||
Result BinaryReaderOpcnt::OnOpcodeBlockSig(Type sig_type) {
|
||||
return Emplace(current_opcode_, OpcodeInfo::Kind::BlockSig, &sig_type);
|
||||
}
|
||||
@ -273,10 +301,6 @@ Result BinaryReaderOpcnt::OnEndExpr() {
|
||||
return Emplace(Opcode::End, OpcodeInfo::Kind::Bare);
|
||||
}
|
||||
|
||||
Result BinaryReaderOpcnt::OnEndFunc() {
|
||||
return Emplace(Opcode::End, OpcodeInfo::Kind::Bare);
|
||||
}
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
Result ReadBinaryOpcnt(const void* data,
|
||||
|
767
third_party/wasm2c/src/binary-reader.cc
vendored
767
third_party/wasm2c/src/binary-reader.cc
vendored
File diff suppressed because it is too large
Load Diff
108
third_party/wasm2c/src/binary-writer-spec.cc
vendored
108
third_party/wasm2c/src/binary-writer-spec.cc
vendored
@ -14,21 +14,21 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "src/binary-writer-spec.h"
|
||||
#include "wabt/binary-writer-spec.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cinttypes>
|
||||
#include <string_view>
|
||||
|
||||
#include "config.h"
|
||||
#include "wabt/config.h"
|
||||
|
||||
#include "src/binary-writer.h"
|
||||
#include "src/binary.h"
|
||||
#include "src/cast.h"
|
||||
#include "src/filenames.h"
|
||||
#include "src/ir.h"
|
||||
#include "src/literal.h"
|
||||
#include "src/stream.h"
|
||||
#include "src/string-view.h"
|
||||
#include "wabt/binary-writer.h"
|
||||
#include "wabt/binary.h"
|
||||
#include "wabt/cast.h"
|
||||
#include "wabt/filenames.h"
|
||||
#include "wabt/ir.h"
|
||||
#include "wabt/literal.h"
|
||||
#include "wabt/stream.h"
|
||||
|
||||
namespace wabt {
|
||||
|
||||
@ -38,8 +38,8 @@ class BinaryWriterSpec {
|
||||
public:
|
||||
BinaryWriterSpec(Stream* json_stream,
|
||||
WriteBinarySpecStreamFactory module_stream_factory,
|
||||
string_view source_filename,
|
||||
string_view module_filename_noext,
|
||||
std::string_view source_filename,
|
||||
std::string_view module_filename_noext,
|
||||
const WriteBinaryOptions& options);
|
||||
|
||||
Result WriteScript(const Script& script);
|
||||
@ -49,7 +49,7 @@ class BinaryWriterSpec {
|
||||
void WriteString(const char* s);
|
||||
void WriteKey(const char* key);
|
||||
void WriteSeparator();
|
||||
void WriteEscapedString(string_view);
|
||||
void WriteEscapedString(std::string_view);
|
||||
void WriteCommandType(const Command& command);
|
||||
void WriteLocation(const Location& loc);
|
||||
void WriteVar(const Var& var);
|
||||
@ -61,10 +61,10 @@ class BinaryWriterSpec {
|
||||
void WriteConstVector(const ConstVector& consts);
|
||||
void WriteAction(const Action& action);
|
||||
void WriteActionResultType(const Action& action);
|
||||
void WriteModule(string_view filename, const Module& module);
|
||||
void WriteScriptModule(string_view filename,
|
||||
void WriteModule(std::string_view filename, const Module& module);
|
||||
void WriteScriptModule(std::string_view filename,
|
||||
const ScriptModule& script_module);
|
||||
void WriteInvalidModule(const ScriptModule& module, string_view text);
|
||||
void WriteInvalidModule(const ScriptModule& module, std::string_view text);
|
||||
void WriteCommands();
|
||||
|
||||
const Script* script_ = nullptr;
|
||||
@ -80,8 +80,8 @@ class BinaryWriterSpec {
|
||||
BinaryWriterSpec::BinaryWriterSpec(
|
||||
Stream* json_stream,
|
||||
WriteBinarySpecStreamFactory module_stream_factory,
|
||||
string_view source_filename,
|
||||
string_view module_filename_noext,
|
||||
std::string_view source_filename,
|
||||
std::string_view module_filename_noext,
|
||||
const WriteBinaryOptions& options)
|
||||
: json_stream_(json_stream),
|
||||
module_stream_factory_(module_stream_factory),
|
||||
@ -110,7 +110,7 @@ void BinaryWriterSpec::WriteSeparator() {
|
||||
json_stream_->Writef(", ");
|
||||
}
|
||||
|
||||
void BinaryWriterSpec::WriteEscapedString(string_view s) {
|
||||
void BinaryWriterSpec::WriteEscapedString(std::string_view s) {
|
||||
json_stream_->WriteChar('"');
|
||||
for (size_t i = 0; i < s.length(); ++i) {
|
||||
uint8_t c = s[i];
|
||||
@ -125,6 +125,7 @@ void BinaryWriterSpec::WriteEscapedString(string_view s) {
|
||||
|
||||
void BinaryWriterSpec::WriteCommandType(const Command& command) {
|
||||
static const char* s_command_names[] = {
|
||||
"module",
|
||||
"module",
|
||||
"action",
|
||||
"register",
|
||||
@ -135,6 +136,7 @@ void BinaryWriterSpec::WriteCommandType(const Command& command) {
|
||||
"assert_return",
|
||||
"assert_trap",
|
||||
"assert_exhaustion",
|
||||
"assert_exception",
|
||||
};
|
||||
WABT_STATIC_ASSERT(WABT_ARRAY_SIZE(s_command_names) == kCommandTypeCount);
|
||||
|
||||
@ -159,7 +161,7 @@ void BinaryWriterSpec::WriteVar(const Var& var) {
|
||||
void BinaryWriterSpec::WriteTypeObject(Type type) {
|
||||
json_stream_->Writef("{");
|
||||
WriteKey("type");
|
||||
WriteString(type.GetName());
|
||||
WriteString(type.GetName().c_str());
|
||||
json_stream_->Writef("}");
|
||||
}
|
||||
|
||||
@ -258,7 +260,7 @@ void BinaryWriterSpec::WriteConst(const Const& const_) {
|
||||
WriteString("v128");
|
||||
WriteSeparator();
|
||||
WriteKey("lane_type");
|
||||
WriteString(const_.lane_type().GetName());
|
||||
WriteString(const_.lane_type().GetName().c_str());
|
||||
WriteSeparator();
|
||||
WriteKey("value");
|
||||
json_stream_->Writef("[");
|
||||
@ -380,12 +382,13 @@ void BinaryWriterSpec::WriteActionResultType(const Action& action) {
|
||||
json_stream_->Writef("]");
|
||||
}
|
||||
|
||||
void BinaryWriterSpec::WriteModule(string_view filename, const Module& module) {
|
||||
void BinaryWriterSpec::WriteModule(std::string_view filename,
|
||||
const Module& module) {
|
||||
result_ |=
|
||||
WriteBinaryModule(module_stream_factory_(filename), &module, options_);
|
||||
}
|
||||
|
||||
void BinaryWriterSpec::WriteScriptModule(string_view filename,
|
||||
void BinaryWriterSpec::WriteScriptModule(std::string_view filename,
|
||||
const ScriptModule& script_module) {
|
||||
switch (script_module.type()) {
|
||||
case ScriptModuleType::Text:
|
||||
@ -405,7 +408,7 @@ void BinaryWriterSpec::WriteScriptModule(string_view filename,
|
||||
}
|
||||
|
||||
void BinaryWriterSpec::WriteInvalidModule(const ScriptModule& module,
|
||||
string_view text) {
|
||||
std::string_view text) {
|
||||
const char* extension = "";
|
||||
const char* module_type = "";
|
||||
switch (module.type()) {
|
||||
@ -475,6 +478,25 @@ void BinaryWriterSpec::WriteCommands() {
|
||||
break;
|
||||
}
|
||||
|
||||
case CommandType::ScriptModule: {
|
||||
auto* script_module_command = cast<ScriptModuleCommand>(command);
|
||||
const auto& module = script_module_command->module;
|
||||
std::string filename = GetModuleFilename(kWasmExtension);
|
||||
WriteLocation(module.loc);
|
||||
WriteSeparator();
|
||||
if (!module.name.empty()) {
|
||||
WriteKey("name");
|
||||
WriteEscapedString(module.name);
|
||||
WriteSeparator();
|
||||
}
|
||||
WriteKey("filename");
|
||||
WriteEscapedString(GetBasename(filename));
|
||||
WriteScriptModule(filename, *script_module_command->script_module);
|
||||
num_modules_++;
|
||||
last_module_index = i;
|
||||
break;
|
||||
}
|
||||
|
||||
case CommandType::Action: {
|
||||
const Action& action = *cast<ActionCommand>(command)->action;
|
||||
WriteLocation(action.loc);
|
||||
@ -546,8 +568,17 @@ void BinaryWriterSpec::WriteCommands() {
|
||||
WriteSeparator();
|
||||
WriteAction(*assert_return_command->action);
|
||||
WriteSeparator();
|
||||
WriteKey("expected");
|
||||
WriteConstVector(assert_return_command->expected);
|
||||
const Expectation* expectation = assert_return_command->expected.get();
|
||||
switch (expectation->type()) {
|
||||
case ExpectationType::Values:
|
||||
WriteKey("expected");
|
||||
break;
|
||||
|
||||
case ExpectationType::Either:
|
||||
WriteKey("either");
|
||||
break;
|
||||
}
|
||||
WriteConstVector(expectation->expected);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -579,6 +610,17 @@ void BinaryWriterSpec::WriteCommands() {
|
||||
WriteActionResultType(*assert_exhaustion_command->action);
|
||||
break;
|
||||
}
|
||||
|
||||
case CommandType::AssertException: {
|
||||
auto* assert_exception_command = cast<AssertExceptionCommand>(command);
|
||||
WriteLocation(assert_exception_command->action->loc);
|
||||
WriteSeparator();
|
||||
WriteAction(*assert_exception_command->action);
|
||||
WriteSeparator();
|
||||
WriteKey("expected");
|
||||
WriteActionResultType(*assert_exception_command->action);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
json_stream_->Writef("}");
|
||||
@ -597,8 +639,8 @@ Result BinaryWriterSpec::WriteScript(const Script& script) {
|
||||
Result WriteBinarySpecScript(Stream* json_stream,
|
||||
WriteBinarySpecStreamFactory module_stream_factory,
|
||||
Script* script,
|
||||
string_view source_filename,
|
||||
string_view module_filename_noext,
|
||||
std::string_view source_filename,
|
||||
std::string_view module_filename_noext,
|
||||
const WriteBinaryOptions& options) {
|
||||
BinaryWriterSpec binary_writer_spec(json_stream, module_stream_factory,
|
||||
source_filename, module_filename_noext,
|
||||
@ -609,15 +651,15 @@ Result WriteBinarySpecScript(Stream* json_stream,
|
||||
Result WriteBinarySpecScript(
|
||||
Stream* json_stream,
|
||||
Script* script,
|
||||
string_view source_filename,
|
||||
string_view module_filename_noext,
|
||||
std::string_view source_filename,
|
||||
std::string_view module_filename_noext,
|
||||
const WriteBinaryOptions& options,
|
||||
std::vector<FilenameMemoryStreamPair>* out_module_streams,
|
||||
Stream* log_stream) {
|
||||
WriteBinarySpecStreamFactory module_stream_factory =
|
||||
[&](string_view filename) {
|
||||
out_module_streams->emplace_back(filename,
|
||||
MakeUnique<MemoryStream>(log_stream));
|
||||
[&](std::string_view filename) {
|
||||
out_module_streams->emplace_back(
|
||||
filename, std::make_unique<MemoryStream>(log_stream));
|
||||
return out_module_streams->back().stream.get();
|
||||
};
|
||||
|
||||
|
355
third_party/wasm2c/src/binary-writer.cc
vendored
355
third_party/wasm2c/src/binary-writer.cc
vendored
@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "src/binary-writer.h"
|
||||
#include "wabt/binary-writer.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
@ -22,16 +22,17 @@
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <set>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include "config.h"
|
||||
#include "wabt/config.h"
|
||||
|
||||
#include "src/binary.h"
|
||||
#include "src/cast.h"
|
||||
#include "src/ir.h"
|
||||
#include "src/leb128.h"
|
||||
#include "src/stream.h"
|
||||
#include "src/string-view.h"
|
||||
#include "wabt/binary.h"
|
||||
#include "wabt/cast.h"
|
||||
#include "wabt/expr-visitor.h"
|
||||
#include "wabt/ir.h"
|
||||
#include "wabt/leb128.h"
|
||||
#include "wabt/stream.h"
|
||||
|
||||
#define PRINT_HEADER_NO_INDEX -1
|
||||
#define MAX_U32_LEB128_BYTES 5
|
||||
@ -39,7 +40,7 @@
|
||||
namespace wabt {
|
||||
|
||||
void WriteStr(Stream* stream,
|
||||
string_view s,
|
||||
std::string_view s,
|
||||
const char* desc,
|
||||
PrintChars print_chars) {
|
||||
WriteU32Leb128(stream, s.length(), "string length");
|
||||
@ -56,7 +57,11 @@ void WriteOpcode(Stream* stream, Opcode opcode) {
|
||||
}
|
||||
|
||||
void WriteType(Stream* stream, Type type, const char* desc) {
|
||||
WriteS32Leb128(stream, type, desc ? desc : type.GetName());
|
||||
WriteS32Leb128(stream, type, desc ? desc : type.GetName().c_str());
|
||||
if (type.IsReferenceWithIndex()) {
|
||||
WriteS32Leb128(stream, type.GetReferenceIndex(),
|
||||
desc ? desc : type.GetName().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void WriteLimits(Stream* stream, const Limits* limits) {
|
||||
@ -73,12 +78,12 @@ void WriteLimits(Stream* stream, const Limits* limits) {
|
||||
WriteU32Leb128(stream, limits->initial, "limits: initial");
|
||||
if (limits->has_max) {
|
||||
WriteU32Leb128(stream, limits->max, "limits: max");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WriteDebugName(Stream* stream, string_view name, const char* desc) {
|
||||
string_view stripped_name = name;
|
||||
void WriteDebugName(Stream* stream, std::string_view name, const char* desc) {
|
||||
std::string_view stripped_name = name;
|
||||
if (!stripped_name.empty()) {
|
||||
// Strip leading $ from name
|
||||
assert(stripped_name.front() == '$');
|
||||
@ -91,7 +96,7 @@ namespace {
|
||||
|
||||
/* TODO(binji): better leb size guess. Some sections we know will only be 1
|
||||
byte, but others we can be fairly certain will be larger. */
|
||||
static const size_t LEB_SECTION_SIZE_GUESS = 1;
|
||||
constexpr size_t LEB_SECTION_SIZE_GUESS = 1;
|
||||
|
||||
#define ALLOC_FAILURE \
|
||||
fprintf(stderr, "%s:%d: allocation failed\n", __FILE__, __LINE__)
|
||||
@ -136,7 +141,7 @@ class Symbol {
|
||||
|
||||
private:
|
||||
SymbolType type_;
|
||||
string_view name_;
|
||||
std::string_view name_;
|
||||
uint8_t flags_;
|
||||
union {
|
||||
Function function_;
|
||||
@ -148,21 +153,21 @@ class Symbol {
|
||||
};
|
||||
|
||||
public:
|
||||
Symbol(const string_view& name, uint8_t flags, const Function& f)
|
||||
Symbol(const std::string_view& name, uint8_t flags, const Function& f)
|
||||
: type_(Function::type), name_(name), flags_(flags), function_(f) {}
|
||||
Symbol(const string_view& name, uint8_t flags, const Data& d)
|
||||
Symbol(const std::string_view& name, uint8_t flags, const Data& d)
|
||||
: type_(Data::type), name_(name), flags_(flags), data_(d) {}
|
||||
Symbol(const string_view& name, uint8_t flags, const Global& g)
|
||||
Symbol(const std::string_view& name, uint8_t flags, const Global& g)
|
||||
: type_(Global::type), name_(name), flags_(flags), global_(g) {}
|
||||
Symbol(const string_view& name, uint8_t flags, const Section& s)
|
||||
Symbol(const std::string_view& name, uint8_t flags, const Section& s)
|
||||
: type_(Section::type), name_(name), flags_(flags), section_(s) {}
|
||||
Symbol(const string_view& name, uint8_t flags, const Tag& e)
|
||||
Symbol(const std::string_view& name, uint8_t flags, const Tag& e)
|
||||
: type_(Tag::type), name_(name), flags_(flags), tag_(e) {}
|
||||
Symbol(const string_view& name, uint8_t flags, const Table& t)
|
||||
Symbol(const std::string_view& name, uint8_t flags, const Table& t)
|
||||
: type_(Table::type), name_(name), flags_(flags), table_(t) {}
|
||||
|
||||
SymbolType type() const { return type_; }
|
||||
const string_view& name() const { return name_; }
|
||||
const std::string_view& name() const { return name_; }
|
||||
uint8_t flags() const { return flags_; }
|
||||
|
||||
SymbolVisibility visibility() const {
|
||||
@ -174,7 +179,9 @@ class Symbol {
|
||||
bool undefined() const { return flags() & WABT_SYMBOL_FLAG_UNDEFINED; }
|
||||
bool defined() const { return !undefined(); }
|
||||
bool exported() const { return flags() & WABT_SYMBOL_FLAG_EXPORTED; }
|
||||
bool explicit_name() const { return flags() & WABT_SYMBOL_FLAG_EXPLICIT_NAME; }
|
||||
bool explicit_name() const {
|
||||
return flags() & WABT_SYMBOL_FLAG_EXPLICIT_NAME;
|
||||
}
|
||||
bool no_strip() const { return flags() & WABT_SYMBOL_FLAG_NO_STRIP; }
|
||||
|
||||
bool IsFunction() const { return type() == Function::type; }
|
||||
@ -219,12 +226,14 @@ class SymbolTable {
|
||||
std::vector<Index> tables_;
|
||||
std::vector<Index> globals_;
|
||||
|
||||
std::set<string_view> seen_names_;
|
||||
std::set<std::string_view> seen_names_;
|
||||
|
||||
Result EnsureUnique(const string_view& name) {
|
||||
Result EnsureUnique(const std::string_view& name) {
|
||||
if (seen_names_.count(name)) {
|
||||
fprintf(stderr, "error: duplicate symbol when writing relocatable "
|
||||
"binary: %s\n", &name[0]);
|
||||
fprintf(stderr,
|
||||
"error: duplicate symbol when writing relocatable "
|
||||
"binary: %s\n",
|
||||
&name[0]);
|
||||
return Result::Error;
|
||||
}
|
||||
seen_names_.insert(name);
|
||||
@ -232,15 +241,18 @@ class SymbolTable {
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
Result AddSymbol(std::vector<Index>* map, string_view name,
|
||||
bool imported, bool exported, T&& sym) {
|
||||
Result AddSymbol(std::vector<Index>* map,
|
||||
std::string_view name,
|
||||
bool imported,
|
||||
bool exported,
|
||||
T&& sym) {
|
||||
uint8_t flags = 0;
|
||||
if (imported) {
|
||||
flags |= WABT_SYMBOL_FLAG_UNDEFINED;
|
||||
// Wabt currently has no way for a user to explicitly specify the name of
|
||||
// an import, so never set the EXPLICIT_NAME flag, and ignore any display
|
||||
// name fabricated by wabt.
|
||||
name = string_view();
|
||||
name = std::string_view();
|
||||
} else {
|
||||
if (name.empty()) {
|
||||
// Definitions without a name are local.
|
||||
@ -286,20 +298,20 @@ class SymbolTable {
|
||||
|
||||
for (const Export* export_ : module->exports) {
|
||||
switch (export_->kind) {
|
||||
case ExternalKind::Func:
|
||||
exported_funcs.insert(module->GetFuncIndex(export_->var));
|
||||
break;
|
||||
case ExternalKind::Table:
|
||||
exported_tables.insert(module->GetTableIndex(export_->var));
|
||||
break;
|
||||
case ExternalKind::Memory:
|
||||
break;
|
||||
case ExternalKind::Global:
|
||||
exported_globals.insert(module->GetGlobalIndex(export_->var));
|
||||
break;
|
||||
case ExternalKind::Tag:
|
||||
exported_tags.insert(module->GetTagIndex(export_->var));
|
||||
break;
|
||||
case ExternalKind::Func:
|
||||
exported_funcs.insert(module->GetFuncIndex(export_->var));
|
||||
break;
|
||||
case ExternalKind::Table:
|
||||
exported_tables.insert(module->GetTableIndex(export_->var));
|
||||
break;
|
||||
case ExternalKind::Memory:
|
||||
break;
|
||||
case ExternalKind::Global:
|
||||
exported_globals.insert(module->GetGlobalIndex(export_->var));
|
||||
break;
|
||||
case ExternalKind::Tag:
|
||||
exported_tags.insert(module->GetTagIndex(export_->var));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -344,6 +356,23 @@ class SymbolTable {
|
||||
}
|
||||
};
|
||||
|
||||
struct CodeMetadata {
|
||||
Offset offset;
|
||||
std::vector<uint8_t> data;
|
||||
CodeMetadata(Offset offset, std::vector<uint8_t> data)
|
||||
: offset(offset), data(std::move(data)) {}
|
||||
};
|
||||
struct FuncCodeMetadata {
|
||||
Index func_idx;
|
||||
std::vector<CodeMetadata> entries;
|
||||
FuncCodeMetadata(Index func_idx) : func_idx(func_idx) {}
|
||||
};
|
||||
struct CodeMetadataSection {
|
||||
std::vector<FuncCodeMetadata> entries;
|
||||
};
|
||||
using CodeMetadataSections =
|
||||
std::unordered_map<std::string_view, CodeMetadataSection>;
|
||||
|
||||
class BinaryWriter {
|
||||
WABT_DISALLOW_COPY_AND_ASSIGN(BinaryWriter);
|
||||
|
||||
@ -382,7 +411,9 @@ class BinaryWriter {
|
||||
template <typename T>
|
||||
void WriteLoadStoreExpr(const Func* func, const Expr* expr, const char* desc);
|
||||
template <typename T>
|
||||
void WriteSimdLoadStoreLaneExpr(const Func* func, const Expr* expr, const char* desc);
|
||||
void WriteSimdLoadStoreLaneExpr(const Func* func,
|
||||
const Expr* expr,
|
||||
const char* desc);
|
||||
void WriteExpr(const Func* func, const Expr* expr);
|
||||
void WriteExprList(const Func* func, const ExprList& exprs);
|
||||
void WriteInitExpr(const ExprList& expr);
|
||||
@ -396,6 +427,7 @@ class BinaryWriter {
|
||||
void WriteLinkingSection();
|
||||
template <typename T>
|
||||
void WriteNames(const std::vector<T*>& elems, NameSectionSubsection type);
|
||||
void WriteCodeMetadataSections();
|
||||
|
||||
Stream* stream_;
|
||||
const WriteBinaryOptions& options_;
|
||||
@ -421,6 +453,10 @@ class BinaryWriter {
|
||||
size_t data_count_start_ = 0;
|
||||
size_t data_count_end_ = 0;
|
||||
bool has_data_segment_instruction_ = false;
|
||||
|
||||
CodeMetadataSections code_metadata_sections_;
|
||||
Offset cur_func_start_offset_;
|
||||
Index cur_func_index_;
|
||||
};
|
||||
|
||||
static uint8_t log2_u32(uint32_t x) {
|
||||
@ -494,7 +530,8 @@ void BinaryWriter::WriteBlockDecl(const BlockDeclaration& decl) {
|
||||
Index index = decl.has_func_type ? module_->GetFuncTypeIndex(decl.type_var)
|
||||
: module_->GetFuncTypeIndex(decl.sig);
|
||||
assert(index != kInvalidIndex);
|
||||
WriteS32Leb128WithReloc(index, "block type function index", RelocType::TypeIndexLEB);
|
||||
WriteS32Leb128WithReloc(index, "block type function index",
|
||||
RelocType::TypeIndexLEB);
|
||||
}
|
||||
|
||||
void BinaryWriter::WriteSectionHeader(const char* desc,
|
||||
@ -579,7 +616,8 @@ void BinaryWriter::AddReloc(RelocType reloc_type, Index index) {
|
||||
// Add a new reloc section if needed
|
||||
if (!current_reloc_section_ ||
|
||||
current_reloc_section_->section_index != section_count_) {
|
||||
reloc_sections_.emplace_back(GetSectionName(last_section_type_), section_count_);
|
||||
reloc_sections_.emplace_back(GetSectionName(last_section_type_),
|
||||
section_count_);
|
||||
current_reloc_section_ = &reloc_sections_.back();
|
||||
}
|
||||
|
||||
@ -618,8 +656,7 @@ void BinaryWriter::WriteS32Leb128WithReloc(int32_t value,
|
||||
}
|
||||
}
|
||||
|
||||
void BinaryWriter::WriteTableNumberWithReloc(Index value,
|
||||
const char* desc) {
|
||||
void BinaryWriter::WriteTableNumberWithReloc(Index value, const char* desc) {
|
||||
// Unless reference types are enabled, all references to tables refer to table
|
||||
// 0, so no relocs need be emitted when making relocatable binaries.
|
||||
if (options_.relocatable && options_.features.reference_types_enabled()) {
|
||||
@ -650,7 +687,13 @@ void BinaryWriter::WriteLoadStoreExpr(const Func* func,
|
||||
auto* typed_expr = cast<T>(expr);
|
||||
WriteOpcode(stream_, typed_expr->opcode);
|
||||
Address align = typed_expr->opcode.GetAlignment(typed_expr->align);
|
||||
stream_->WriteU8(log2_u32(align), "alignment");
|
||||
Index memidx = module_->GetMemoryIndex(typed_expr->memidx);
|
||||
if (memidx != 0) {
|
||||
stream_->WriteU8(log2_u32(align) | (1 << 6), "alignment");
|
||||
WriteU32Leb128(stream_, memidx, "memidx");
|
||||
} else {
|
||||
stream_->WriteU8(log2_u32(align), "alignment");
|
||||
}
|
||||
WriteU32Leb128(stream_, typed_expr->offset, desc);
|
||||
}
|
||||
|
||||
@ -658,11 +701,8 @@ template <typename T>
|
||||
void BinaryWriter::WriteSimdLoadStoreLaneExpr(const Func* func,
|
||||
const Expr* expr,
|
||||
const char* desc) {
|
||||
WriteLoadStoreExpr<T>(func, expr, desc);
|
||||
auto* typed_expr = cast<T>(expr);
|
||||
WriteOpcode(stream_, typed_expr->opcode);
|
||||
Address align = typed_expr->opcode.GetAlignment(typed_expr->align);
|
||||
stream_->WriteU8(log2_u32(align), "alignment");
|
||||
WriteU32Leb128(stream_, typed_expr->offset, desc);
|
||||
stream_->WriteU8(static_cast<uint8_t>(typed_expr->val), "Simd Lane literal");
|
||||
}
|
||||
|
||||
@ -725,7 +765,7 @@ void BinaryWriter::WriteExpr(const Func* func, const Expr* expr) {
|
||||
WriteU32Leb128(stream_, depth, "break depth for default");
|
||||
break;
|
||||
}
|
||||
case ExprType::Call:{
|
||||
case ExprType::Call: {
|
||||
Index index = module_->GetFuncIndex(cast<CallExpr>(expr)->var);
|
||||
WriteOpcode(stream_, Opcode::Call);
|
||||
WriteU32Leb128WithReloc(index, "function index", RelocType::FuncIndexLEB);
|
||||
@ -737,17 +777,18 @@ void BinaryWriter::WriteExpr(const Func* func, const Expr* expr) {
|
||||
WriteU32Leb128WithReloc(index, "function index", RelocType::FuncIndexLEB);
|
||||
break;
|
||||
}
|
||||
case ExprType::CallIndirect:{
|
||||
case ExprType::CallIndirect: {
|
||||
Index sig_index =
|
||||
module_->GetFuncTypeIndex(cast<CallIndirectExpr>(expr)->decl);
|
||||
module_->GetFuncTypeIndex(cast<CallIndirectExpr>(expr)->decl);
|
||||
Index table_index =
|
||||
module_->GetTableIndex(cast<CallIndirectExpr>(expr)->table);
|
||||
module_->GetTableIndex(cast<CallIndirectExpr>(expr)->table);
|
||||
WriteOpcode(stream_, Opcode::CallIndirect);
|
||||
WriteU32Leb128WithReloc(sig_index, "signature index", RelocType::TypeIndexLEB);
|
||||
WriteU32Leb128WithReloc(sig_index, "signature index",
|
||||
RelocType::TypeIndexLEB);
|
||||
WriteTableNumberWithReloc(table_index, "table index");
|
||||
break;
|
||||
}
|
||||
case ExprType::CallRef:{
|
||||
case ExprType::CallRef: {
|
||||
WriteOpcode(stream_, Opcode::CallRef);
|
||||
break;
|
||||
}
|
||||
@ -757,7 +798,8 @@ void BinaryWriter::WriteExpr(const Func* func, const Expr* expr) {
|
||||
Index table_index =
|
||||
module_->GetTableIndex(cast<ReturnCallIndirectExpr>(expr)->table);
|
||||
WriteOpcode(stream_, Opcode::ReturnCallIndirect);
|
||||
WriteU32Leb128WithReloc(sig_index, "signature index", RelocType::TypeIndexLEB);
|
||||
WriteU32Leb128WithReloc(sig_index, "signature index",
|
||||
RelocType::TypeIndexLEB);
|
||||
WriteTableNumberWithReloc(table_index, "table index");
|
||||
break;
|
||||
}
|
||||
@ -850,40 +892,55 @@ void BinaryWriter::WriteExpr(const Func* func, const Expr* expr) {
|
||||
WriteExprList(func, cast<LoopExpr>(expr)->block.exprs);
|
||||
WriteOpcode(stream_, Opcode::End);
|
||||
break;
|
||||
case ExprType::MemoryCopy:
|
||||
case ExprType::MemoryCopy: {
|
||||
Index srcmemidx =
|
||||
module_->GetMemoryIndex(cast<MemoryCopyExpr>(expr)->srcmemidx);
|
||||
Index destmemidx =
|
||||
module_->GetMemoryIndex(cast<MemoryCopyExpr>(expr)->destmemidx);
|
||||
WriteOpcode(stream_, Opcode::MemoryCopy);
|
||||
WriteU32Leb128(stream_, 0, "memory.copy reserved");
|
||||
WriteU32Leb128(stream_, 0, "memory.copy reserved");
|
||||
WriteU32Leb128(stream_, srcmemidx, "memory.copy srcmemidx");
|
||||
WriteU32Leb128(stream_, destmemidx, "memory.copy destmemidx");
|
||||
break;
|
||||
}
|
||||
case ExprType::DataDrop: {
|
||||
Index index =
|
||||
module_->GetDataSegmentIndex(cast<DataDropExpr>(expr)->var);
|
||||
Index index = module_->GetDataSegmentIndex(cast<DataDropExpr>(expr)->var);
|
||||
WriteOpcode(stream_, Opcode::DataDrop);
|
||||
WriteU32Leb128(stream_, index, "data.drop segment");
|
||||
has_data_segment_instruction_ = true;
|
||||
break;
|
||||
}
|
||||
case ExprType::MemoryFill:
|
||||
case ExprType::MemoryFill: {
|
||||
Index memidx =
|
||||
module_->GetMemoryIndex(cast<MemoryFillExpr>(expr)->memidx);
|
||||
WriteOpcode(stream_, Opcode::MemoryFill);
|
||||
WriteU32Leb128(stream_, 0, "memory.fill reserved");
|
||||
WriteU32Leb128(stream_, memidx, "memory.fill memidx");
|
||||
break;
|
||||
case ExprType::MemoryGrow:
|
||||
}
|
||||
case ExprType::MemoryGrow: {
|
||||
Index memidx =
|
||||
module_->GetMemoryIndex(cast<MemoryGrowExpr>(expr)->memidx);
|
||||
WriteOpcode(stream_, Opcode::MemoryGrow);
|
||||
WriteU32Leb128(stream_, 0, "memory.grow reserved");
|
||||
WriteU32Leb128(stream_, memidx, "memory.grow memidx");
|
||||
break;
|
||||
}
|
||||
case ExprType::MemoryInit: {
|
||||
Index index =
|
||||
module_->GetDataSegmentIndex(cast<MemoryInitExpr>(expr)->var);
|
||||
Index memidx =
|
||||
module_->GetMemoryIndex(cast<MemoryInitExpr>(expr)->memidx);
|
||||
WriteOpcode(stream_, Opcode::MemoryInit);
|
||||
WriteU32Leb128(stream_, index, "memory.init segment");
|
||||
WriteU32Leb128(stream_, 0, "memory.init reserved");
|
||||
WriteU32Leb128(stream_, memidx, "memory.init memidx");
|
||||
has_data_segment_instruction_ = true;
|
||||
break;
|
||||
}
|
||||
case ExprType::MemorySize:
|
||||
case ExprType::MemorySize: {
|
||||
Index memidx =
|
||||
module_->GetMemoryIndex(cast<MemorySizeExpr>(expr)->memidx);
|
||||
WriteOpcode(stream_, Opcode::MemorySize);
|
||||
WriteU32Leb128(stream_, 0, "memory.size reserved");
|
||||
WriteU32Leb128(stream_, memidx, "memory.size memidx");
|
||||
break;
|
||||
}
|
||||
case ExprType::TableCopy: {
|
||||
auto* copy_expr = cast<TableCopyExpr>(expr);
|
||||
Index dst = module_->GetTableIndex(copy_expr->dst_table);
|
||||
@ -894,8 +951,7 @@ void BinaryWriter::WriteExpr(const Func* func, const Expr* expr) {
|
||||
break;
|
||||
}
|
||||
case ExprType::ElemDrop: {
|
||||
Index index =
|
||||
module_->GetElemSegmentIndex(cast<ElemDropExpr>(expr)->var);
|
||||
Index index = module_->GetElemSegmentIndex(cast<ElemDropExpr>(expr)->var);
|
||||
WriteOpcode(stream_, Opcode::ElemDrop);
|
||||
WriteU32Leb128(stream_, index, "elem.drop segment");
|
||||
break;
|
||||
@ -911,36 +967,31 @@ void BinaryWriter::WriteExpr(const Func* func, const Expr* expr) {
|
||||
break;
|
||||
}
|
||||
case ExprType::TableGet: {
|
||||
Index index =
|
||||
module_->GetTableIndex(cast<TableGetExpr>(expr)->var);
|
||||
Index index = module_->GetTableIndex(cast<TableGetExpr>(expr)->var);
|
||||
WriteOpcode(stream_, Opcode::TableGet);
|
||||
WriteTableNumberWithReloc(index, "table.get table index");
|
||||
break;
|
||||
}
|
||||
case ExprType::TableSet: {
|
||||
Index index =
|
||||
module_->GetTableIndex(cast<TableSetExpr>(expr)->var);
|
||||
Index index = module_->GetTableIndex(cast<TableSetExpr>(expr)->var);
|
||||
WriteOpcode(stream_, Opcode::TableSet);
|
||||
WriteTableNumberWithReloc(index, "table.set table index");
|
||||
break;
|
||||
}
|
||||
case ExprType::TableGrow: {
|
||||
Index index =
|
||||
module_->GetTableIndex(cast<TableGrowExpr>(expr)->var);
|
||||
Index index = module_->GetTableIndex(cast<TableGrowExpr>(expr)->var);
|
||||
WriteOpcode(stream_, Opcode::TableGrow);
|
||||
WriteTableNumberWithReloc(index, "table.grow table index");
|
||||
break;
|
||||
}
|
||||
case ExprType::TableSize: {
|
||||
Index index =
|
||||
module_->GetTableIndex(cast<TableSizeExpr>(expr)->var);
|
||||
Index index = module_->GetTableIndex(cast<TableSizeExpr>(expr)->var);
|
||||
WriteOpcode(stream_, Opcode::TableSize);
|
||||
WriteTableNumberWithReloc(index, "table.size table index");
|
||||
break;
|
||||
}
|
||||
case ExprType::TableFill: {
|
||||
Index index =
|
||||
module_->GetTableIndex(cast<TableFillExpr>(expr)->var);
|
||||
Index index = module_->GetTableIndex(cast<TableFillExpr>(expr)->var);
|
||||
WriteOpcode(stream_, Opcode::TableFill);
|
||||
WriteTableNumberWithReloc(index, "table.fill table index");
|
||||
break;
|
||||
@ -1012,8 +1063,7 @@ void BinaryWriter::WriteExpr(const Func* func, const Expr* expr) {
|
||||
break;
|
||||
case TryKind::Delegate:
|
||||
WriteOpcode(stream_, Opcode::Delegate);
|
||||
WriteU32Leb128(stream_,
|
||||
GetLabelVarDepth(&try_expr->delegate_target),
|
||||
WriteU32Leb128(stream_, GetLabelVarDepth(&try_expr->delegate_target),
|
||||
"delegate depth");
|
||||
break;
|
||||
case TryKind::Plain:
|
||||
@ -1059,6 +1109,17 @@ void BinaryWriter::WriteExpr(const Func* func, const Expr* expr) {
|
||||
case ExprType::Unreachable:
|
||||
WriteOpcode(stream_, Opcode::Unreachable);
|
||||
break;
|
||||
case ExprType::CodeMetadata: {
|
||||
auto* meta_expr = cast<CodeMetadataExpr>(expr);
|
||||
auto& s = code_metadata_sections_[meta_expr->name];
|
||||
if (s.entries.empty() || s.entries.back().func_idx != cur_func_index_) {
|
||||
s.entries.emplace_back(cur_func_index_);
|
||||
}
|
||||
auto& a = s.entries.back();
|
||||
Offset code_offset = stream_->offset() - cur_func_start_offset_;
|
||||
a.entries.emplace_back(code_offset, meta_expr->data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1495,31 +1556,25 @@ Result BinaryWriter::WriteModule() {
|
||||
// preceeded by length
|
||||
WriteU32Leb128(stream_, segment->elem_exprs.size(), "num elems");
|
||||
if (flags & SegUseElemExprs) {
|
||||
for (const ElemExpr& elem_expr : segment->elem_exprs) {
|
||||
switch (elem_expr.kind) {
|
||||
case ElemExprKind::RefNull:
|
||||
WriteOpcode(stream_, Opcode::RefNull);
|
||||
WriteType(stream_, elem_expr.type, "elem expr ref.null type");
|
||||
break;
|
||||
|
||||
case ElemExprKind::RefFunc:
|
||||
WriteOpcode(stream_, Opcode::RefFunc);
|
||||
WriteU32Leb128(stream_, module_->GetFuncIndex(elem_expr.var), "elem expr function index");
|
||||
break;
|
||||
}
|
||||
WriteOpcode(stream_, Opcode::End);
|
||||
for (const ExprList& elem_expr : segment->elem_exprs) {
|
||||
WriteInitExpr(elem_expr);
|
||||
}
|
||||
} else {
|
||||
for (const ElemExpr& elem_expr : segment->elem_exprs) {
|
||||
assert(elem_expr.kind == ElemExprKind::RefFunc);
|
||||
WriteU32Leb128(stream_, module_->GetFuncIndex(elem_expr.var), "elem function index");
|
||||
for (const ExprList& elem_expr : segment->elem_exprs) {
|
||||
assert(elem_expr.size() == 1);
|
||||
const Expr* expr = &elem_expr.front();
|
||||
assert(expr->type() == ExprType::RefFunc);
|
||||
WriteU32Leb128(stream_,
|
||||
module_->GetFuncIndex(cast<RefFuncExpr>(expr)->var),
|
||||
"elem function index");
|
||||
}
|
||||
}
|
||||
}
|
||||
EndSection();
|
||||
}
|
||||
|
||||
if (options_.features.bulk_memory_enabled()) {
|
||||
if (options_.features.bulk_memory_enabled() &&
|
||||
module_->data_segments.size()) {
|
||||
// Keep track of the data count section offset so it can be removed if
|
||||
// it isn't needed.
|
||||
data_count_start_ = stream_->offset();
|
||||
@ -1535,21 +1590,24 @@ Result BinaryWriter::WriteModule() {
|
||||
WriteU32Leb128(stream_, num_funcs, "num functions");
|
||||
|
||||
for (size_t i = 0; i < num_funcs; ++i) {
|
||||
cur_func_index_ = i + module_->num_func_imports;
|
||||
WriteHeader("function body", i);
|
||||
const Func* func = module_->funcs[i + module_->num_func_imports];
|
||||
const Func* func = module_->funcs[cur_func_index_];
|
||||
|
||||
/* TODO(binji): better guess of the size of the function body section */
|
||||
const Offset leb_size_guess = 1;
|
||||
Offset body_size_offset =
|
||||
WriteU32Leb128Space(leb_size_guess, "func body size (guess)");
|
||||
cur_func_start_offset_ = stream_->offset();
|
||||
WriteFunc(func);
|
||||
auto func_start_offset = body_size_offset - last_section_payload_offset_;
|
||||
auto func_end_offset = stream_->offset() - last_section_payload_offset_;
|
||||
auto delta = WriteFixupU32Leb128Size(body_size_offset, leb_size_guess,
|
||||
"FIXUP func body size");
|
||||
"FIXUP func body size");
|
||||
if (current_reloc_section_ && delta != 0) {
|
||||
for (Reloc& reloc : current_reloc_section_->relocations) {
|
||||
if (reloc.offset >= func_start_offset && reloc.offset <= func_end_offset) {
|
||||
if (reloc.offset >= func_start_offset &&
|
||||
reloc.offset <= func_end_offset) {
|
||||
reloc.offset += delta;
|
||||
}
|
||||
}
|
||||
@ -1560,7 +1618,7 @@ Result BinaryWriter::WriteModule() {
|
||||
|
||||
// Remove the DataCount section if there are no instructions that require it.
|
||||
if (options_.features.bulk_memory_enabled() &&
|
||||
!has_data_segment_instruction_) {
|
||||
module_->data_segments.size() && !has_data_segment_instruction_) {
|
||||
Offset size = stream_->offset() - data_count_end_;
|
||||
if (size) {
|
||||
// If the DataCount section was followed by anything, assert that it's
|
||||
@ -1569,6 +1627,7 @@ Result BinaryWriter::WriteModule() {
|
||||
assert(data_count_end_ == code_start_);
|
||||
assert(last_section_type_ == BinarySection::Code);
|
||||
stream_->MoveData(data_count_start_, data_count_end_, size);
|
||||
code_start_ = data_count_start_;
|
||||
}
|
||||
stream_->Truncate(data_count_start_ + size);
|
||||
|
||||
@ -1584,6 +1643,8 @@ Result BinaryWriter::WriteModule() {
|
||||
}
|
||||
}
|
||||
|
||||
WriteCodeMetadataSections();
|
||||
|
||||
if (module_->data_segments.size()) {
|
||||
BeginKnownSection(BinarySection::Data);
|
||||
WriteU32Leb128(stream_, module_->data_segments.size(), "num data segments");
|
||||
@ -1593,7 +1654,13 @@ Result BinaryWriter::WriteModule() {
|
||||
uint8_t flags = segment->GetFlags(module_);
|
||||
stream_->WriteU8(flags, "segment flags");
|
||||
if (!(flags & SegPassive)) {
|
||||
assert(module_->GetMemoryIndex(segment->memory_var) == 0);
|
||||
if (options_.features.multi_memory_enabled() &&
|
||||
(flags & SegExplicitIndex)) {
|
||||
WriteU32Leb128(stream_, module_->GetMemoryIndex(segment->memory_var),
|
||||
"memidx");
|
||||
} else {
|
||||
assert(module_->GetMemoryIndex(segment->memory_var) == 0);
|
||||
}
|
||||
WriteInitExpr(segment->offset);
|
||||
}
|
||||
WriteU32Leb128(stream_, segment->data.size(), "data segment size");
|
||||
@ -1626,17 +1693,25 @@ Result BinaryWriter::WriteModule() {
|
||||
for (size_t i = 0; i < module_->funcs.size(); ++i) {
|
||||
const Func* func = module_->funcs[i];
|
||||
Index num_params_and_locals = func->GetNumParamsAndLocals();
|
||||
|
||||
WriteU32Leb128(stream_, i, "function index");
|
||||
WriteU32Leb128(stream_, num_params_and_locals, "num locals");
|
||||
|
||||
MakeTypeBindingReverseMapping(num_params_and_locals, func->bindings,
|
||||
&index_to_name);
|
||||
Index num_named = 0;
|
||||
for (auto s : index_to_name) {
|
||||
if (!s.empty()) {
|
||||
num_named++;
|
||||
}
|
||||
}
|
||||
|
||||
WriteU32Leb128(stream_, i, "function index");
|
||||
WriteU32Leb128(stream_, num_named, "num locals");
|
||||
|
||||
for (size_t j = 0; j < num_params_and_locals; ++j) {
|
||||
const std::string& name = index_to_name[j];
|
||||
wabt_snprintf(desc, sizeof(desc), "local name %" PRIzd, j);
|
||||
WriteU32Leb128(stream_, j, "local index");
|
||||
WriteDebugName(stream_, name, desc);
|
||||
if (!name.empty()) {
|
||||
wabt_snprintf(desc, sizeof(desc), "local name %" PRIzd, j);
|
||||
WriteU32Leb128(stream_, j, "local index");
|
||||
WriteDebugName(stream_, name, desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
EndSubsection();
|
||||
@ -1649,6 +1724,7 @@ Result BinaryWriter::WriteModule() {
|
||||
NameSectionSubsection::ElemSegment);
|
||||
WriteNames<DataSegment>(module_->data_segments,
|
||||
NameSectionSubsection::DataSegment);
|
||||
WriteNames<Tag>(module_->tags, NameSectionSubsection::Tag);
|
||||
|
||||
EndSection();
|
||||
}
|
||||
@ -1663,6 +1739,53 @@ Result BinaryWriter::WriteModule() {
|
||||
return stream_->result();
|
||||
}
|
||||
|
||||
void BinaryWriter::WriteCodeMetadataSections() {
|
||||
if (code_metadata_sections_.empty())
|
||||
return;
|
||||
|
||||
section_count_ -= 1;
|
||||
// We have to increment the code section's index; adjust anything
|
||||
// that might have captured it.
|
||||
for (RelocSection& section : reloc_sections_) {
|
||||
if (section.section_index == section_count_) {
|
||||
assert(last_section_type_ == BinarySection::Code);
|
||||
section.section_index += code_metadata_sections_.size();
|
||||
}
|
||||
}
|
||||
|
||||
MemoryStream tmp_stream;
|
||||
Stream* main_stream = stream_;
|
||||
stream_ = &tmp_stream;
|
||||
for (auto& s : code_metadata_sections_) {
|
||||
std::string name = "metadata.code.";
|
||||
name.append(s.first);
|
||||
auto& section = s.second;
|
||||
BeginCustomSection(name.c_str());
|
||||
WriteU32Leb128(stream_, section.entries.size(), "function count");
|
||||
for (auto& f : section.entries) {
|
||||
WriteU32Leb128WithReloc(f.func_idx, "function index",
|
||||
RelocType::FuncIndexLEB);
|
||||
WriteU32Leb128(stream_, f.entries.size(), "instances count");
|
||||
for (auto& a : f.entries) {
|
||||
WriteU32Leb128(stream_, a.offset, "code offset");
|
||||
WriteU32Leb128(stream_, a.data.size(), "data length");
|
||||
stream_->WriteData(a.data.data(), a.data.size(), "data",
|
||||
PrintChars::Yes);
|
||||
}
|
||||
}
|
||||
EndSection();
|
||||
}
|
||||
stream_ = main_stream;
|
||||
auto buf = tmp_stream.ReleaseOutputBuffer();
|
||||
stream_->MoveData(code_start_ + buf->data.size(), code_start_,
|
||||
stream_->offset() - code_start_);
|
||||
stream_->WriteDataAt(code_start_, buf->data.data(), buf->data.size());
|
||||
stream_->AddOffset(buf->data.size());
|
||||
code_start_ += buf->data.size();
|
||||
section_count_ += 1;
|
||||
last_section_type_ = BinarySection::Code;
|
||||
}
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
Result WriteBinaryModule(Stream* stream,
|
||||
|
32
third_party/wasm2c/src/binary.cc
vendored
32
third_party/wasm2c/src/binary.cc
vendored
@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "src/binary.h"
|
||||
#include "wabt/binary.h"
|
||||
|
||||
namespace wabt {
|
||||
|
||||
@ -25,8 +25,8 @@ BinarySectionOrder GetSectionOrder(BinarySection sec) {
|
||||
return BinarySectionOrder::Name;
|
||||
WABT_FOREACH_BINARY_SECTION(V)
|
||||
#undef V
|
||||
default:
|
||||
WABT_UNREACHABLE;
|
||||
default:
|
||||
WABT_UNREACHABLE;
|
||||
}
|
||||
}
|
||||
|
||||
@ -42,20 +42,26 @@ const char* GetSectionName(BinarySection sec) {
|
||||
}
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
const char* NameSubsectionName[] = {
|
||||
"module",
|
||||
"function",
|
||||
"local",
|
||||
"label",
|
||||
"type",
|
||||
"table",
|
||||
"memory",
|
||||
"global",
|
||||
"elemseg",
|
||||
"dataseg",
|
||||
"module",
|
||||
"function",
|
||||
"local",
|
||||
"label",
|
||||
"type",
|
||||
"table",
|
||||
"memory",
|
||||
"global",
|
||||
"elemseg",
|
||||
"dataseg",
|
||||
"tag",
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
const char* GetNameSectionSubsectionName(NameSectionSubsection subsec) {
|
||||
static_assert(WABT_ENUM_COUNT(NameSectionSubsection) ==
|
||||
WABT_ARRAY_SIZE(NameSubsectionName),
|
||||
"Malformed ExprTypeName array");
|
||||
return NameSubsectionName[size_t(subsec)];
|
||||
}
|
||||
|
||||
|
4
third_party/wasm2c/src/binding-hash.cc
vendored
4
third_party/wasm2c/src/binding-hash.cc
vendored
@ -14,12 +14,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "src/binding-hash.h"
|
||||
#include "wabt/binding-hash.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#include "src/ir.h"
|
||||
#include "wabt/ir.h"
|
||||
|
||||
namespace wabt {
|
||||
|
||||
|
4210
third_party/wasm2c/src/c-writer.cc
vendored
4210
third_party/wasm2c/src/c-writer.cc
vendored
File diff suppressed because it is too large
Load Diff
4
third_party/wasm2c/src/color.cc
vendored
4
third_party/wasm2c/src/color.cc
vendored
@ -14,11 +14,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "src/color.h"
|
||||
#include "wabt/color.h"
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include "src/common.h"
|
||||
#include "wabt/common.h"
|
||||
|
||||
#if _WIN32
|
||||
#include <io.h>
|
||||
|
9
third_party/wasm2c/src/common.cc
vendored
9
third_party/wasm2c/src/common.cc
vendored
@ -14,16 +14,17 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "src/common.h"
|
||||
#include "wabt/common.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cerrno>
|
||||
#include <climits>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#if COMPILER_IS_MSVC
|
||||
#include <fcntl.h>
|
||||
@ -76,8 +77,8 @@ static Result ReadStdin(std::vector<uint8_t>* out_data) {
|
||||
}
|
||||
}
|
||||
|
||||
Result ReadFile(string_view filename, std::vector<uint8_t>* out_data) {
|
||||
std::string filename_str = filename.to_string();
|
||||
Result ReadFile(std::string_view filename, std::vector<uint8_t>* out_data) {
|
||||
std::string filename_str(filename);
|
||||
const char* filename_cstr = filename_str.c_str();
|
||||
|
||||
if (filename == "-") {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user