[wasm] Draft version of C/C++ Wasm API
Imported from https://github.com/WebAssembly/wasm-c-api/ and updated to work inside V8. Tests will be added in an upcoming CL. This is experimental; it is not yet recommended to rely on it. Change-Id: I05914f4b63298bf7c848c4d4c8811f0f6eb882e3 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1516478 Commit-Queue: Jakob Kummerow <jkummerow@chromium.org> Reviewed-by: Michael Starzinger <mstarzinger@chromium.org> Cr-Commit-Position: refs/heads/master@{#60910}
This commit is contained in:
parent
bfc8afdbd1
commit
f80bfeaf07
21
BUILD.gn
21
BUILD.gn
@ -3664,6 +3664,27 @@ if (v8_monolithic) {
|
||||
}
|
||||
}
|
||||
|
||||
v8_static_library("wee8") {
|
||||
deps = [
|
||||
":v8_base",
|
||||
":v8_libbase",
|
||||
":v8_libplatform",
|
||||
":v8_libsampler",
|
||||
":v8_maybe_snapshot",
|
||||
"//build/win:default_exe_manifest",
|
||||
]
|
||||
|
||||
# TODO: v8dll-main.cc equivalent for shared library builds
|
||||
|
||||
configs = [ ":internal_config" ]
|
||||
|
||||
sources = [
|
||||
"src/wasm/c-api.cc",
|
||||
"third_party/wasm-c-api/wasm.h",
|
||||
"third_party/wasm-c-api/wasm.hh",
|
||||
]
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Executables
|
||||
#
|
||||
|
10
LICENSE
10
LICENSE
@ -20,11 +20,13 @@ are:
|
||||
This code is copyrighted by Sun Microsystems Inc. and released
|
||||
under a 3-clause BSD license.
|
||||
|
||||
- Valgrind client API header, located at third_party/valgrind/valgrind.h
|
||||
This is release under the BSD license.
|
||||
- Valgrind client API header, located at src/third_party/valgrind/valgrind.h
|
||||
This is released under the BSD license.
|
||||
|
||||
- antlr4 parser generator Cpp library located in third_party/antlr4
|
||||
This is release under the BSD license.
|
||||
- The Wasm C/C++ API headers, located at third_party/wasm-api/wasm.{h,hh}
|
||||
This is released under the Apache license. The API's upstream prototype
|
||||
implementation also formed the basis of V8's implementation in
|
||||
src/wasm/c-api.cc.
|
||||
|
||||
These libraries have their own licenses; we recommend you read them,
|
||||
as their terms may differ from the terms below.
|
||||
|
7
src/wasm/DEPS
Normal file
7
src/wasm/DEPS
Normal file
@ -0,0 +1,7 @@
|
||||
specific_include_rules = {
|
||||
"c-api\.cc": [
|
||||
"+include/libplatform/libplatform.h",
|
||||
"+third_party/wasm-api/wasm.h",
|
||||
"+third_party/wasm-api/wasm.hh",
|
||||
],
|
||||
}
|
3599
src/wasm/c-api.cc
Normal file
3599
src/wasm/c-api.cc
Normal file
File diff suppressed because it is too large
Load Diff
202
third_party/wasm-api/LICENSE
vendored
Normal file
202
third_party/wasm-api/LICENSE
vendored
Normal file
@ -0,0 +1,202 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright {yyyy} {name of copyright owner}
|
||||
|
||||
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.
|
||||
|
17
third_party/wasm-api/README.v8
vendored
Normal file
17
third_party/wasm-api/README.v8
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
Name: Wasm C/C++ API
|
||||
Short Name: wasm-c-api
|
||||
URL: https://github.com/WebAssembly/wasm-c-api/
|
||||
Version: 0
|
||||
Revision: 5c742b048f7766a0c00be3a7af23fb71ba816026
|
||||
Date: 2019-03-18
|
||||
License: Apache 2.0
|
||||
License File: LICENSE
|
||||
Security Critical: yes
|
||||
|
||||
Description:
|
||||
Provides a "black box" API for embedding a Wasm engine in C/C++ applications.
|
||||
|
||||
Local modifications:
|
||||
None.
|
||||
This is only the contents of the "include/" directory of the upstream
|
||||
repository.
|
677
third_party/wasm-api/wasm.h
vendored
Normal file
677
third_party/wasm-api/wasm.h
vendored
Normal file
@ -0,0 +1,677 @@
|
||||
// WebAssembly C API
|
||||
|
||||
#ifndef __WASM_H
|
||||
#define __WASM_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Auxiliaries
|
||||
|
||||
// Machine types
|
||||
|
||||
inline void assertions() {
|
||||
static_assert(sizeof(float) == sizeof(uint32_t), "incompatible float type");
|
||||
static_assert(sizeof(double) == sizeof(uint64_t), "incompatible double type");
|
||||
static_assert(sizeof(intptr_t) == sizeof(uint32_t) ||
|
||||
sizeof(intptr_t) == sizeof(uint64_t),
|
||||
"incompatible pointer type");
|
||||
}
|
||||
|
||||
typedef char byte_t;
|
||||
typedef float float32_t;
|
||||
typedef double float64_t;
|
||||
|
||||
|
||||
// Ownership
|
||||
|
||||
#define own
|
||||
|
||||
// The qualifier `own` is used to indicate ownership of data in this API.
|
||||
// It is intended to be interpreted similar to a `const` qualifier:
|
||||
//
|
||||
// - `own wasm_xxx_t*` owns the pointed-to data
|
||||
// - `own wasm_xxx_t` distributes to all fields of a struct or union `xxx`
|
||||
// - `own wasm_xxx_vec_t` owns the vector as well as its elements(!)
|
||||
// - an `own` function parameter passes ownership from caller to callee
|
||||
// - an `own` function result passes ownership from callee to caller
|
||||
// - an exception are `own` pointer parameters named `out`, which are copy-back
|
||||
// output parameters passing back ownership from callee to caller
|
||||
//
|
||||
// Own data is created by `wasm_xxx_new` functions and some others.
|
||||
// It must be released with the corresponding `wasm_xxx_delete` function.
|
||||
//
|
||||
// Deleting a reference does not necessarily delete the underlying object,
|
||||
// it merely indicates that this owner no longer uses it.
|
||||
//
|
||||
// For vectors, `const wasm_xxx_vec_t` is used informally to indicate that
|
||||
// neither the vector nor its elements should be modified.
|
||||
// TODO: introduce proper `wasm_xxx_const_vec_t`?
|
||||
|
||||
|
||||
#define WASM_DECLARE_OWN(name) \
|
||||
typedef struct wasm_##name##_t wasm_##name##_t; \
|
||||
\
|
||||
void wasm_##name##_delete(own wasm_##name##_t*);
|
||||
|
||||
|
||||
// Vectors
|
||||
|
||||
#define WASM_DECLARE_VEC(name, ptr_or_none) \
|
||||
typedef struct wasm_##name##_vec_t { \
|
||||
size_t size; \
|
||||
wasm_##name##_t ptr_or_none* data; \
|
||||
} wasm_##name##_vec_t; \
|
||||
\
|
||||
void wasm_##name##_vec_new_empty(own wasm_##name##_vec_t* out); \
|
||||
void wasm_##name##_vec_new_uninitialized( \
|
||||
own wasm_##name##_vec_t* out, size_t); \
|
||||
void wasm_##name##_vec_new( \
|
||||
own wasm_##name##_vec_t* out, \
|
||||
size_t, own wasm_##name##_t ptr_or_none const[]); \
|
||||
void wasm_##name##_vec_copy( \
|
||||
own wasm_##name##_vec_t* out, wasm_##name##_vec_t*); \
|
||||
void wasm_##name##_vec_delete(own wasm_##name##_vec_t*);
|
||||
|
||||
|
||||
// Byte vectors
|
||||
|
||||
typedef byte_t wasm_byte_t;
|
||||
WASM_DECLARE_VEC(byte, )
|
||||
|
||||
typedef wasm_byte_vec_t wasm_name_t;
|
||||
|
||||
#define wasm_name wasm_byte_vec
|
||||
#define wasm_name_new wasm_byte_vec_new
|
||||
#define wasm_name_new_empty wasm_byte_vec_new_empty
|
||||
#define wasm_name_new_new_uninitialized wasm_byte_vec_new_uninitialized
|
||||
#define wasm_name_copy wasm_byte_vec_copy
|
||||
#define wasm_name_delete wasm_byte_vec_delete
|
||||
|
||||
static inline void wasm_name_new_from_string(
|
||||
own wasm_name_t* out, const char* s
|
||||
) {
|
||||
wasm_name_new(out, strlen(s) + 1, s);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Runtime Environment
|
||||
|
||||
// Configuration
|
||||
|
||||
WASM_DECLARE_OWN(config)
|
||||
|
||||
own wasm_config_t* wasm_config_new();
|
||||
|
||||
// Embedders may provide custom functions for manipulating configs.
|
||||
|
||||
|
||||
// Engine
|
||||
|
||||
WASM_DECLARE_OWN(engine)
|
||||
|
||||
own wasm_engine_t* wasm_engine_new();
|
||||
own wasm_engine_t* wasm_engine_new_with_config(own wasm_config_t*);
|
||||
|
||||
|
||||
// Store
|
||||
|
||||
WASM_DECLARE_OWN(store)
|
||||
|
||||
own wasm_store_t* wasm_store_new(wasm_engine_t*);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Type Representations
|
||||
|
||||
// Type attributes
|
||||
|
||||
typedef enum wasm_mutability_t {
|
||||
WASM_CONST,
|
||||
WASM_VAR
|
||||
} wasm_mutability_t;
|
||||
|
||||
typedef struct wasm_limits_t {
|
||||
uint32_t min;
|
||||
uint32_t max;
|
||||
} wasm_limits_t;
|
||||
|
||||
static const uint32_t wasm_limits_max_default = 0xffffffff;
|
||||
|
||||
|
||||
// Generic
|
||||
|
||||
#define WASM_DECLARE_TYPE(name) \
|
||||
WASM_DECLARE_OWN(name) \
|
||||
WASM_DECLARE_VEC(name, *) \
|
||||
\
|
||||
own wasm_##name##_t* wasm_##name##_copy(wasm_##name##_t*);
|
||||
|
||||
|
||||
// Value Types
|
||||
|
||||
WASM_DECLARE_TYPE(valtype)
|
||||
|
||||
typedef enum wasm_valkind_t {
|
||||
WASM_I32,
|
||||
WASM_I64,
|
||||
WASM_F32,
|
||||
WASM_F64,
|
||||
WASM_ANYREF,
|
||||
WASM_FUNCREF
|
||||
} wasm_valkind_t;
|
||||
|
||||
own wasm_valtype_t* wasm_valtype_new(wasm_valkind_t);
|
||||
|
||||
wasm_valkind_t wasm_valtype_kind(const wasm_valtype_t*);
|
||||
|
||||
static inline bool wasm_valkind_is_num(wasm_valkind_t k) {
|
||||
return k < WASM_ANYREF;
|
||||
}
|
||||
static inline bool wasm_valkind_is_ref(wasm_valkind_t k) {
|
||||
return k >= WASM_ANYREF;
|
||||
}
|
||||
|
||||
static inline bool wasm_valtype_is_num(const wasm_valtype_t* t) {
|
||||
return wasm_valkind_is_num(wasm_valtype_kind(t));
|
||||
}
|
||||
static inline bool wasm_valtype_is_ref(const wasm_valtype_t* t) {
|
||||
return wasm_valkind_is_ref(wasm_valtype_kind(t));
|
||||
}
|
||||
|
||||
|
||||
// Function Types
|
||||
|
||||
WASM_DECLARE_TYPE(functype)
|
||||
|
||||
own wasm_functype_t* wasm_functype_new(
|
||||
own wasm_valtype_vec_t* params, own wasm_valtype_vec_t* results);
|
||||
|
||||
const wasm_valtype_vec_t* wasm_functype_params(const wasm_functype_t*);
|
||||
const wasm_valtype_vec_t* wasm_functype_results(const wasm_functype_t*);
|
||||
|
||||
|
||||
// Global Types
|
||||
|
||||
WASM_DECLARE_TYPE(globaltype)
|
||||
|
||||
own wasm_globaltype_t* wasm_globaltype_new(
|
||||
own wasm_valtype_t*, wasm_mutability_t);
|
||||
|
||||
const wasm_valtype_t* wasm_globaltype_content(const wasm_globaltype_t*);
|
||||
wasm_mutability_t wasm_globaltype_mutability(const wasm_globaltype_t*);
|
||||
|
||||
|
||||
// Table Types
|
||||
|
||||
WASM_DECLARE_TYPE(tabletype)
|
||||
|
||||
own wasm_tabletype_t* wasm_tabletype_new(
|
||||
own wasm_valtype_t*, const wasm_limits_t*);
|
||||
|
||||
const wasm_valtype_t* wasm_tabletype_element(const wasm_tabletype_t*);
|
||||
const wasm_limits_t* wasm_tabletype_limits(const wasm_tabletype_t*);
|
||||
|
||||
|
||||
// Memory Types
|
||||
|
||||
WASM_DECLARE_TYPE(memorytype)
|
||||
|
||||
own wasm_memorytype_t* wasm_memorytype_new(const wasm_limits_t*);
|
||||
|
||||
const wasm_limits_t* wasm_memorytype_limits(const wasm_memorytype_t*);
|
||||
|
||||
|
||||
// Extern Types
|
||||
|
||||
WASM_DECLARE_TYPE(externtype)
|
||||
|
||||
typedef enum wasm_externkind_t {
|
||||
WASM_EXTERN_FUNC,
|
||||
WASM_EXTERN_GLOBAL,
|
||||
WASM_EXTERN_TABLE,
|
||||
WASM_EXTERN_MEMORY
|
||||
} wasm_externkind_t;
|
||||
|
||||
wasm_externkind_t wasm_externtype_kind(const wasm_externtype_t*);
|
||||
|
||||
wasm_externtype_t* wasm_functype_as_externtype(wasm_functype_t*);
|
||||
wasm_externtype_t* wasm_globaltype_as_externtype(wasm_globaltype_t*);
|
||||
wasm_externtype_t* wasm_tabletype_as_externtype(wasm_tabletype_t*);
|
||||
wasm_externtype_t* wasm_memorytype_as_externtype(wasm_memorytype_t*);
|
||||
|
||||
wasm_functype_t* wasm_externtype_as_functype(wasm_externtype_t*);
|
||||
wasm_globaltype_t* wasm_externtype_as_globaltype(wasm_externtype_t*);
|
||||
wasm_tabletype_t* wasm_externtype_as_tabletype(wasm_externtype_t*);
|
||||
wasm_memorytype_t* wasm_externtype_as_memorytype(wasm_externtype_t*);
|
||||
|
||||
const wasm_externtype_t* wasm_functype_as_externtype_const(const wasm_functype_t*);
|
||||
const wasm_externtype_t* wasm_globaltype_as_externtype_const(const wasm_globaltype_t*);
|
||||
const wasm_externtype_t* wasm_tabletype_as_externtype_const(const wasm_tabletype_t*);
|
||||
const wasm_externtype_t* wasm_memorytype_as_externtype_const(const wasm_memorytype_t*);
|
||||
|
||||
const wasm_functype_t* wasm_externtype_as_functype_const(const wasm_externtype_t*);
|
||||
const wasm_globaltype_t* wasm_externtype_as_globaltype_const(const wasm_externtype_t*);
|
||||
const wasm_tabletype_t* wasm_externtype_as_tabletype_const(const wasm_externtype_t*);
|
||||
const wasm_memorytype_t* wasm_externtype_as_memorytype_const(const wasm_externtype_t*);
|
||||
|
||||
|
||||
// Import Types
|
||||
|
||||
WASM_DECLARE_TYPE(importtype)
|
||||
|
||||
own wasm_importtype_t* wasm_importtype_new(
|
||||
own wasm_name_t* module, own wasm_name_t* name, own wasm_externtype_t*);
|
||||
|
||||
const wasm_name_t* wasm_importtype_module(const wasm_importtype_t*);
|
||||
const wasm_name_t* wasm_importtype_name(const wasm_importtype_t*);
|
||||
const wasm_externtype_t* wasm_importtype_type(const wasm_importtype_t*);
|
||||
|
||||
|
||||
// Export Types
|
||||
|
||||
WASM_DECLARE_TYPE(exporttype)
|
||||
|
||||
own wasm_exporttype_t* wasm_exporttype_new(
|
||||
own wasm_name_t*, own wasm_externtype_t*);
|
||||
|
||||
const wasm_name_t* wasm_exporttype_name(const wasm_exporttype_t*);
|
||||
const wasm_externtype_t* wasm_exporttype_type(const wasm_exporttype_t*);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Runtime Objects
|
||||
|
||||
// Values
|
||||
|
||||
struct wasm_ref_t;
|
||||
|
||||
typedef struct wasm_val_t {
|
||||
wasm_valkind_t kind;
|
||||
union {
|
||||
int32_t i32;
|
||||
int64_t i64;
|
||||
float32_t f32;
|
||||
float64_t f64;
|
||||
struct wasm_ref_t* ref;
|
||||
} of;
|
||||
} wasm_val_t;
|
||||
|
||||
void wasm_val_delete(own wasm_val_t* v);
|
||||
void wasm_val_copy(own wasm_val_t* out, const wasm_val_t*);
|
||||
|
||||
WASM_DECLARE_VEC(val, )
|
||||
|
||||
|
||||
// References
|
||||
|
||||
#define WASM_DECLARE_REF_BASE(name) \
|
||||
WASM_DECLARE_OWN(name) \
|
||||
\
|
||||
own wasm_##name##_t* wasm_##name##_copy(const wasm_##name##_t*); \
|
||||
\
|
||||
void* wasm_##name##_get_host_info(const wasm_##name##_t*); \
|
||||
void wasm_##name##_set_host_info(wasm_##name##_t*, void*); \
|
||||
void wasm_##name##_set_host_info_with_finalizer( \
|
||||
wasm_##name##_t*, void*, void (*)(void*));
|
||||
|
||||
#define WASM_DECLARE_REF(name) \
|
||||
WASM_DECLARE_REF_BASE(name) \
|
||||
\
|
||||
wasm_ref_t* wasm_##name##_as_ref(wasm_##name##_t*); \
|
||||
wasm_##name##_t* wasm_ref_as_##name(wasm_ref_t*); \
|
||||
const wasm_ref_t* wasm_##name##_as_ref_const(const wasm_##name##_t*); \
|
||||
const wasm_##name##_t* wasm_ref_as_##name##_const(const wasm_ref_t*);
|
||||
|
||||
#define WASM_DECLARE_SHARABLE_REF(name) \
|
||||
WASM_DECLARE_REF(name) \
|
||||
WASM_DECLARE_OWN(shared_##name) \
|
||||
\
|
||||
own wasm_shared_##name##_t* wasm_##name##_share(const wasm_##name##_t*); \
|
||||
own wasm_##name##_t* wasm_##name##_obtain(wasm_store_t*, const wasm_shared_##name##_t*);
|
||||
|
||||
|
||||
WASM_DECLARE_REF_BASE(ref)
|
||||
|
||||
|
||||
// Traps
|
||||
|
||||
typedef wasm_name_t wasm_message_t; // null terminated
|
||||
|
||||
WASM_DECLARE_REF(trap)
|
||||
|
||||
own wasm_trap_t* wasm_trap_new(wasm_store_t* store, const wasm_message_t*);
|
||||
|
||||
void wasm_trap_message(const wasm_trap_t*, own wasm_message_t* out);
|
||||
|
||||
|
||||
// Foreign Objects
|
||||
|
||||
WASM_DECLARE_REF(foreign)
|
||||
|
||||
own wasm_foreign_t* wasm_foreign_new(wasm_store_t*);
|
||||
|
||||
|
||||
// Modules
|
||||
|
||||
WASM_DECLARE_SHARABLE_REF(module)
|
||||
|
||||
own wasm_module_t* wasm_module_new(
|
||||
wasm_store_t*, const wasm_byte_vec_t* binary);
|
||||
|
||||
bool wasm_module_validate(wasm_store_t*, const wasm_byte_vec_t* binary);
|
||||
|
||||
void wasm_module_imports(const wasm_module_t*, own wasm_importtype_vec_t* out);
|
||||
void wasm_module_exports(const wasm_module_t*, own wasm_exporttype_vec_t* out);
|
||||
|
||||
void wasm_module_serialize(const wasm_module_t*, own wasm_byte_vec_t* out);
|
||||
own wasm_module_t* wasm_module_deserialize(wasm_store_t*, const wasm_byte_vec_t*);
|
||||
|
||||
|
||||
// Function Instances
|
||||
|
||||
WASM_DECLARE_REF(func)
|
||||
|
||||
typedef own wasm_trap_t* (*wasm_func_callback_t)(
|
||||
const wasm_val_t args[], wasm_val_t results[]);
|
||||
typedef own wasm_trap_t* (*wasm_func_callback_with_env_t)(
|
||||
void* env, const wasm_val_t args[], wasm_val_t results[]);
|
||||
|
||||
own wasm_func_t* wasm_func_new(
|
||||
wasm_store_t*, const wasm_functype_t*, wasm_func_callback_t);
|
||||
own wasm_func_t* wasm_func_new_with_env(
|
||||
wasm_store_t*, const wasm_functype_t* type, wasm_func_callback_with_env_t,
|
||||
void* env, void (*finalizer)(void*));
|
||||
|
||||
own wasm_functype_t* wasm_func_type(const wasm_func_t*);
|
||||
size_t wasm_func_param_arity(const wasm_func_t*);
|
||||
size_t wasm_func_result_arity(const wasm_func_t*);
|
||||
|
||||
own wasm_trap_t* wasm_func_call(
|
||||
const wasm_func_t*, const wasm_val_t args[], wasm_val_t results[]);
|
||||
|
||||
|
||||
// Global Instances
|
||||
|
||||
WASM_DECLARE_REF(global)
|
||||
|
||||
own wasm_global_t* wasm_global_new(
|
||||
wasm_store_t*, const wasm_globaltype_t*, const wasm_val_t*);
|
||||
|
||||
own wasm_globaltype_t* wasm_global_type(const wasm_global_t*);
|
||||
|
||||
void wasm_global_get(const wasm_global_t*, own wasm_val_t* out);
|
||||
void wasm_global_set(wasm_global_t*, const wasm_val_t*);
|
||||
|
||||
|
||||
// Table Instances
|
||||
|
||||
WASM_DECLARE_REF(table)
|
||||
|
||||
typedef uint32_t wasm_table_size_t;
|
||||
|
||||
own wasm_table_t* wasm_table_new(
|
||||
wasm_store_t*, const wasm_tabletype_t*, wasm_ref_t* init);
|
||||
|
||||
own wasm_tabletype_t* wasm_table_type(const wasm_table_t*);
|
||||
|
||||
own wasm_ref_t* wasm_table_get(const wasm_table_t*, wasm_table_size_t index);
|
||||
bool wasm_table_set(wasm_table_t*, wasm_table_size_t index, wasm_ref_t*);
|
||||
|
||||
wasm_table_size_t wasm_table_size(const wasm_table_t*);
|
||||
bool wasm_table_grow(wasm_table_t*, wasm_table_size_t delta, wasm_ref_t* init);
|
||||
|
||||
|
||||
// Memory Instances
|
||||
|
||||
WASM_DECLARE_REF(memory)
|
||||
|
||||
typedef uint32_t wasm_memory_pages_t;
|
||||
|
||||
static const size_t MEMORY_PAGE_SIZE = 0x10000;
|
||||
|
||||
own wasm_memory_t* wasm_memory_new(wasm_store_t*, const wasm_memorytype_t*);
|
||||
|
||||
own wasm_memorytype_t* wasm_memory_type(const wasm_memory_t*);
|
||||
|
||||
byte_t* wasm_memory_data(wasm_memory_t*);
|
||||
size_t wasm_memory_data_size(const wasm_memory_t*);
|
||||
|
||||
wasm_memory_pages_t wasm_memory_size(const wasm_memory_t*);
|
||||
bool wasm_memory_grow(wasm_memory_t*, wasm_memory_pages_t delta);
|
||||
|
||||
|
||||
// Externals
|
||||
|
||||
WASM_DECLARE_REF(extern)
|
||||
WASM_DECLARE_VEC(extern, *)
|
||||
|
||||
wasm_externkind_t wasm_extern_kind(const wasm_extern_t*);
|
||||
own wasm_externtype_t* wasm_extern_type(const wasm_extern_t*);
|
||||
|
||||
wasm_extern_t* wasm_func_as_extern(wasm_func_t*);
|
||||
wasm_extern_t* wasm_global_as_extern(wasm_global_t*);
|
||||
wasm_extern_t* wasm_table_as_extern(wasm_table_t*);
|
||||
wasm_extern_t* wasm_memory_as_extern(wasm_memory_t*);
|
||||
|
||||
wasm_func_t* wasm_extern_as_func(wasm_extern_t*);
|
||||
wasm_global_t* wasm_extern_as_global(wasm_extern_t*);
|
||||
wasm_table_t* wasm_extern_as_table(wasm_extern_t*);
|
||||
wasm_memory_t* wasm_extern_as_memory(wasm_extern_t*);
|
||||
|
||||
const wasm_extern_t* wasm_func_as_extern_const(const wasm_func_t*);
|
||||
const wasm_extern_t* wasm_global_as_extern_const(const wasm_global_t*);
|
||||
const wasm_extern_t* wasm_table_as_extern_const(const wasm_table_t*);
|
||||
const wasm_extern_t* wasm_memory_as_extern_const(const wasm_memory_t*);
|
||||
|
||||
const wasm_func_t* wasm_extern_as_func_const(const wasm_extern_t*);
|
||||
const wasm_global_t* wasm_extern_as_global_const(const wasm_extern_t*);
|
||||
const wasm_table_t* wasm_extern_as_table_const(const wasm_extern_t*);
|
||||
const wasm_memory_t* wasm_extern_as_memory_const(const wasm_extern_t*);
|
||||
|
||||
|
||||
// Module Instances
|
||||
|
||||
WASM_DECLARE_REF(instance)
|
||||
|
||||
own wasm_instance_t* wasm_instance_new(
|
||||
wasm_store_t*, const wasm_module_t*, const wasm_extern_t* const imports[]);
|
||||
|
||||
void wasm_instance_exports(const wasm_instance_t*, own wasm_extern_vec_t* out);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Convenience
|
||||
|
||||
// Value Type construction short-hands
|
||||
|
||||
static inline own wasm_valtype_t* wasm_valtype_new_i32() {
|
||||
return wasm_valtype_new(WASM_I32);
|
||||
}
|
||||
static inline own wasm_valtype_t* wasm_valtype_new_i64() {
|
||||
return wasm_valtype_new(WASM_I64);
|
||||
}
|
||||
static inline own wasm_valtype_t* wasm_valtype_new_f32() {
|
||||
return wasm_valtype_new(WASM_F32);
|
||||
}
|
||||
static inline own wasm_valtype_t* wasm_valtype_new_f64() {
|
||||
return wasm_valtype_new(WASM_F64);
|
||||
}
|
||||
|
||||
static inline own wasm_valtype_t* wasm_valtype_new_anyref() {
|
||||
return wasm_valtype_new(WASM_ANYREF);
|
||||
}
|
||||
static inline own wasm_valtype_t* wasm_valtype_new_funcref() {
|
||||
return wasm_valtype_new(WASM_FUNCREF);
|
||||
}
|
||||
|
||||
|
||||
// Function Types construction short-hands
|
||||
|
||||
static inline own wasm_functype_t* wasm_functype_new_0_0() {
|
||||
wasm_valtype_vec_t params, results;
|
||||
wasm_valtype_vec_new_empty(¶ms);
|
||||
wasm_valtype_vec_new_empty(&results);
|
||||
return wasm_functype_new(¶ms, &results);
|
||||
}
|
||||
|
||||
static inline own wasm_functype_t* wasm_functype_new_1_0(
|
||||
own wasm_valtype_t* p
|
||||
) {
|
||||
wasm_valtype_t* ps[1] = {p};
|
||||
wasm_valtype_vec_t params, results;
|
||||
wasm_valtype_vec_new(¶ms, 1, ps);
|
||||
wasm_valtype_vec_new_empty(&results);
|
||||
return wasm_functype_new(¶ms, &results);
|
||||
}
|
||||
|
||||
static inline own wasm_functype_t* wasm_functype_new_2_0(
|
||||
own wasm_valtype_t* p1, own wasm_valtype_t* p2
|
||||
) {
|
||||
wasm_valtype_t* ps[2] = {p1, p2};
|
||||
wasm_valtype_vec_t params, results;
|
||||
wasm_valtype_vec_new(¶ms, 2, ps);
|
||||
wasm_valtype_vec_new_empty(&results);
|
||||
return wasm_functype_new(¶ms, &results);
|
||||
}
|
||||
|
||||
static inline own wasm_functype_t* wasm_functype_new_3_0(
|
||||
own wasm_valtype_t* p1, own wasm_valtype_t* p2, own wasm_valtype_t* p3
|
||||
) {
|
||||
wasm_valtype_t* ps[3] = {p1, p2, p3};
|
||||
wasm_valtype_vec_t params, results;
|
||||
wasm_valtype_vec_new(¶ms, 3, ps);
|
||||
wasm_valtype_vec_new_empty(&results);
|
||||
return wasm_functype_new(¶ms, &results);
|
||||
}
|
||||
|
||||
static inline own wasm_functype_t* wasm_functype_new_0_1(
|
||||
own wasm_valtype_t* r
|
||||
) {
|
||||
wasm_valtype_t* rs[1] = {r};
|
||||
wasm_valtype_vec_t params, results;
|
||||
wasm_valtype_vec_new_empty(¶ms);
|
||||
wasm_valtype_vec_new(&results, 1, rs);
|
||||
return wasm_functype_new(¶ms, &results);
|
||||
}
|
||||
|
||||
static inline own wasm_functype_t* wasm_functype_new_1_1(
|
||||
own wasm_valtype_t* p, own wasm_valtype_t* r
|
||||
) {
|
||||
wasm_valtype_t* ps[1] = {p};
|
||||
wasm_valtype_t* rs[1] = {r};
|
||||
wasm_valtype_vec_t params, results;
|
||||
wasm_valtype_vec_new(¶ms, 1, ps);
|
||||
wasm_valtype_vec_new(&results, 1, rs);
|
||||
return wasm_functype_new(¶ms, &results);
|
||||
}
|
||||
|
||||
static inline own wasm_functype_t* wasm_functype_new_2_1(
|
||||
own wasm_valtype_t* p1, own wasm_valtype_t* p2, own wasm_valtype_t* r
|
||||
) {
|
||||
wasm_valtype_t* ps[2] = {p1, p2};
|
||||
wasm_valtype_t* rs[1] = {r};
|
||||
wasm_valtype_vec_t params, results;
|
||||
wasm_valtype_vec_new(¶ms, 2, ps);
|
||||
wasm_valtype_vec_new(&results, 1, rs);
|
||||
return wasm_functype_new(¶ms, &results);
|
||||
}
|
||||
|
||||
static inline own wasm_functype_t* wasm_functype_new_3_1(
|
||||
own wasm_valtype_t* p1, own wasm_valtype_t* p2, own wasm_valtype_t* p3,
|
||||
own wasm_valtype_t* r
|
||||
) {
|
||||
wasm_valtype_t* ps[3] = {p1, p2, p3};
|
||||
wasm_valtype_t* rs[1] = {r};
|
||||
wasm_valtype_vec_t params, results;
|
||||
wasm_valtype_vec_new(¶ms, 3, ps);
|
||||
wasm_valtype_vec_new(&results, 1, rs);
|
||||
return wasm_functype_new(¶ms, &results);
|
||||
}
|
||||
|
||||
static inline own wasm_functype_t* wasm_functype_new_0_2(
|
||||
own wasm_valtype_t* r1, own wasm_valtype_t* r2
|
||||
) {
|
||||
wasm_valtype_t* rs[2] = {r1, r2};
|
||||
wasm_valtype_vec_t params, results;
|
||||
wasm_valtype_vec_new_empty(¶ms);
|
||||
wasm_valtype_vec_new(&results, 2, rs);
|
||||
return wasm_functype_new(¶ms, &results);
|
||||
}
|
||||
|
||||
static inline own wasm_functype_t* wasm_functype_new_1_2(
|
||||
own wasm_valtype_t* p, own wasm_valtype_t* r1, own wasm_valtype_t* r2
|
||||
) {
|
||||
wasm_valtype_t* ps[1] = {p};
|
||||
wasm_valtype_t* rs[2] = {r1, r2};
|
||||
wasm_valtype_vec_t params, results;
|
||||
wasm_valtype_vec_new(¶ms, 1, ps);
|
||||
wasm_valtype_vec_new(&results, 2, rs);
|
||||
return wasm_functype_new(¶ms, &results);
|
||||
}
|
||||
|
||||
static inline own wasm_functype_t* wasm_functype_new_2_2(
|
||||
own wasm_valtype_t* p1, own wasm_valtype_t* p2,
|
||||
own wasm_valtype_t* r1, own wasm_valtype_t* r2
|
||||
) {
|
||||
wasm_valtype_t* ps[2] = {p1, p2};
|
||||
wasm_valtype_t* rs[2] = {r1, r2};
|
||||
wasm_valtype_vec_t params, results;
|
||||
wasm_valtype_vec_new(¶ms, 2, ps);
|
||||
wasm_valtype_vec_new(&results, 2, rs);
|
||||
return wasm_functype_new(¶ms, &results);
|
||||
}
|
||||
|
||||
static inline own wasm_functype_t* wasm_functype_new_3_2(
|
||||
own wasm_valtype_t* p1, own wasm_valtype_t* p2, own wasm_valtype_t* p3,
|
||||
own wasm_valtype_t* r1, own wasm_valtype_t* r2
|
||||
) {
|
||||
wasm_valtype_t* ps[3] = {p1, p2, p3};
|
||||
wasm_valtype_t* rs[2] = {r1, r2};
|
||||
wasm_valtype_vec_t params, results;
|
||||
wasm_valtype_vec_new(¶ms, 3, ps);
|
||||
wasm_valtype_vec_new(&results, 2, rs);
|
||||
return wasm_functype_new(¶ms, &results);
|
||||
}
|
||||
|
||||
|
||||
// Value construction short-hands
|
||||
|
||||
static inline void wasm_val_init_ptr(own wasm_val_t* out, void* p) {
|
||||
#if UINTPTR_MAX == UINT32_MAX
|
||||
out->kind = WASM_I32;
|
||||
out->of.i32 = (intptr_t)p;
|
||||
#elif UINTPTR_MAX == UINT64_MAX
|
||||
out->kind = WASM_I64;
|
||||
out->of.i64 = (intptr_t)p;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void* wasm_val_ptr(const wasm_val_t* val) {
|
||||
#if UINTPTR_MAX == UINT32_MAX
|
||||
return (void*)(intptr_t)val->of.i32;
|
||||
#elif UINTPTR_MAX == UINT64_MAX
|
||||
return (void*)(intptr_t)val->of.i64;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#undef own
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // #ifdef __WASM_H
|
770
third_party/wasm-api/wasm.hh
vendored
Normal file
770
third_party/wasm-api/wasm.hh
vendored
Normal file
@ -0,0 +1,770 @@
|
||||
// WebAssembly C++ API
|
||||
|
||||
#ifndef __WASM_HH
|
||||
#define __WASM_HH
|
||||
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Auxiliaries
|
||||
|
||||
// Machine types
|
||||
|
||||
static_assert(sizeof(float) == sizeof(int32_t), "incompatible float type");
|
||||
static_assert(sizeof(double) == sizeof(int64_t), "incompatible double type");
|
||||
static_assert(sizeof(intptr_t) == sizeof(int32_t) ||
|
||||
sizeof(intptr_t) == sizeof(int64_t), "incompatible pointer type");
|
||||
|
||||
using byte_t = char;
|
||||
using float32_t = float;
|
||||
using float64_t = double;
|
||||
|
||||
|
||||
namespace wasm {
|
||||
|
||||
// Ownership
|
||||
|
||||
template<class T> struct owner { using type = T; };
|
||||
template<class T> struct owner<T*> { using type = std::unique_ptr<T>; };
|
||||
|
||||
template<class T>
|
||||
using own = typename owner<T>::type;
|
||||
|
||||
template<class T>
|
||||
auto make_own(T x) -> own<T> { return own<T>(std::move(x)); }
|
||||
|
||||
|
||||
// Vectors
|
||||
|
||||
template<class T>
|
||||
struct vec_traits {
|
||||
static void construct(size_t size, T data[]) {}
|
||||
static void destruct(size_t size, T data[]) {}
|
||||
static void move(size_t size, T* data, T init[]) {
|
||||
for (size_t i = 0; i < size; ++i) data[i] = std::move(init[i]);
|
||||
}
|
||||
static void copy(size_t size, T data[], const T init[]) {
|
||||
for (size_t i = 0; i < size; ++i) data[i] = init[i];
|
||||
}
|
||||
|
||||
using proxy = T&;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct vec_traits<T*> {
|
||||
static void construct(size_t size, T* data[]) {
|
||||
for (size_t i = 0; i < size; ++i) data[i] = nullptr;
|
||||
}
|
||||
static void destruct(size_t size, T* data[]) {
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
if (data[i]) delete data[i];
|
||||
}
|
||||
}
|
||||
static void move(size_t size, T* data[], own<T*> init[]) {
|
||||
for (size_t i = 0; i < size; ++i) data[i] = init[i].release();
|
||||
}
|
||||
static void copy(size_t size, T* data[], const T* const init[]) {
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
if (init[i]) data[i] = init[i]->copy().release();
|
||||
}
|
||||
}
|
||||
|
||||
class proxy {
|
||||
T*& elem_;
|
||||
public:
|
||||
proxy(T*& elem) : elem_(elem) {}
|
||||
operator T*() { return elem_; }
|
||||
operator const T*() const { return elem_; }
|
||||
auto operator=(own<T*>&& elem) -> proxy& {
|
||||
reset(std::move(elem));
|
||||
return *this;
|
||||
}
|
||||
void reset(own<T*>&& val = own<T*>()) {
|
||||
if (elem_) delete elem_;
|
||||
elem_ = val.release();
|
||||
}
|
||||
auto release() -> T* {
|
||||
auto elem = elem_;
|
||||
elem_ = nullptr;
|
||||
return elem;
|
||||
}
|
||||
auto move() -> own<T*> { return make_own(release()); }
|
||||
auto get() -> T* { return elem_; }
|
||||
auto get() const -> const T* { return elem_; }
|
||||
auto operator->() -> T* { return elem_; }
|
||||
auto operator->() const -> const T* { return elem_; }
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
template<class T>
|
||||
class vec {
|
||||
static const size_t invalid_size = SIZE_MAX;
|
||||
|
||||
size_t size_;
|
||||
std::unique_ptr<T[]> data_;
|
||||
|
||||
#ifdef DEBUG
|
||||
void make_data();
|
||||
void free_data();
|
||||
#else
|
||||
void make_data() {}
|
||||
void free_data() {}
|
||||
#endif
|
||||
|
||||
vec(size_t size) : vec(size, size ? new(std::nothrow) T[size] : nullptr) {
|
||||
make_data();
|
||||
}
|
||||
|
||||
vec(size_t size, T* data) : size_(size), data_(data) {
|
||||
assert(!!size_ == !!data_ || size_ == invalid_size);
|
||||
}
|
||||
|
||||
public:
|
||||
template<class U>
|
||||
vec(vec<U>&& that) : vec(that.size_, that.data_.release()) {}
|
||||
|
||||
~vec() {
|
||||
if (data_) vec_traits<T>::destruct(size_, data_.get());
|
||||
free_data();
|
||||
}
|
||||
|
||||
operator bool() const {
|
||||
return bool(size_ != invalid_size);
|
||||
}
|
||||
|
||||
auto size() const -> size_t {
|
||||
return size_;
|
||||
}
|
||||
|
||||
auto get() const -> const T* {
|
||||
return data_.get();
|
||||
}
|
||||
|
||||
auto get() -> T* {
|
||||
return data_.get();
|
||||
}
|
||||
|
||||
auto release() -> T* {
|
||||
return data_.release();
|
||||
}
|
||||
|
||||
void reset() {
|
||||
if (data_) vec_traits<T>::destruct(size_, data_.get());
|
||||
free_data();
|
||||
size_ = 0;
|
||||
data_.reset();
|
||||
}
|
||||
|
||||
void reset(vec& that) {
|
||||
reset();
|
||||
size_ = that.size_;
|
||||
data_.reset(that.data_.release());
|
||||
}
|
||||
|
||||
auto operator=(vec&& that) -> vec& {
|
||||
reset(that);
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto operator[](size_t i) -> typename vec_traits<T>::proxy {
|
||||
assert(i < size_);
|
||||
return typename vec_traits<T>::proxy(data_[i]);
|
||||
}
|
||||
|
||||
auto operator[](size_t i) const -> const typename vec_traits<T>::proxy {
|
||||
assert(i < size_);
|
||||
return typename vec_traits<T>::proxy(data_[i]);
|
||||
}
|
||||
|
||||
auto copy() const -> vec {
|
||||
auto v = vec(size_);
|
||||
if (v) vec_traits<T>::copy(size_, v.data_.get(), data_.get());
|
||||
return v;
|
||||
}
|
||||
|
||||
static auto make_uninitialized(size_t size = 0) -> vec {
|
||||
auto v = vec(size);
|
||||
if (v) vec_traits<T>::construct(size, v.data_.get());
|
||||
return v;
|
||||
}
|
||||
|
||||
static auto make(size_t size, own<T> init[]) -> vec {
|
||||
auto v = vec(size);
|
||||
if (v) vec_traits<T>::move(size, v.data_.get(), init);
|
||||
return v;
|
||||
}
|
||||
|
||||
static auto make(std::string s) -> vec<char> {
|
||||
auto v = vec(s.length() + 1);
|
||||
if (v) std::strcpy(v.get(), s.data());
|
||||
return v;
|
||||
}
|
||||
|
||||
static auto make() -> vec {
|
||||
return vec(0);
|
||||
}
|
||||
|
||||
template<class... Ts>
|
||||
static auto make(Ts&&... args) -> vec {
|
||||
own<T> data[] = { make_own(std::move(args))... };
|
||||
return make(sizeof...(Ts), data);
|
||||
}
|
||||
|
||||
static auto adopt(size_t size, T data[]) -> vec {
|
||||
return vec(size, data);
|
||||
}
|
||||
|
||||
static auto invalid() -> vec {
|
||||
return vec(invalid_size, nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Runtime Environment
|
||||
|
||||
// Configuration
|
||||
|
||||
class Config {
|
||||
public:
|
||||
Config() = delete;
|
||||
~Config();
|
||||
void operator delete(void*);
|
||||
|
||||
static auto make() -> own<Config*>;
|
||||
|
||||
// Implementations may provide custom methods for manipulating Configs.
|
||||
};
|
||||
|
||||
|
||||
// Engine
|
||||
|
||||
class Engine {
|
||||
public:
|
||||
Engine() = delete;
|
||||
~Engine();
|
||||
void operator delete(void*);
|
||||
|
||||
static auto make(own<Config*>&& = Config::make()) -> own<Engine*>;
|
||||
};
|
||||
|
||||
|
||||
// Store
|
||||
|
||||
class Store {
|
||||
public:
|
||||
Store() = delete;
|
||||
~Store();
|
||||
void operator delete(void*);
|
||||
|
||||
static auto make(Engine*) -> own<Store*>;
|
||||
};
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Type Representations
|
||||
|
||||
// Type attributes
|
||||
|
||||
enum Mutability { CONST, VAR };
|
||||
|
||||
struct Limits {
|
||||
uint32_t min;
|
||||
uint32_t max;
|
||||
|
||||
Limits(uint32_t min, uint32_t max = std::numeric_limits<uint32_t>::max()) :
|
||||
min(min), max(max) {}
|
||||
};
|
||||
|
||||
|
||||
// Value Types
|
||||
|
||||
enum ValKind { I32, I64, F32, F64, ANYREF, FUNCREF };
|
||||
|
||||
inline bool is_num(ValKind k) { return k < ANYREF; }
|
||||
inline bool is_ref(ValKind k) { return k >= ANYREF; }
|
||||
|
||||
|
||||
class ValType {
|
||||
public:
|
||||
ValType() = delete;
|
||||
~ValType();
|
||||
void operator delete(void*);
|
||||
|
||||
static auto make(ValKind) -> own<ValType*>;
|
||||
auto copy() const -> own<ValType*>;
|
||||
|
||||
auto kind() const -> ValKind;
|
||||
auto is_num() const -> bool { return wasm::is_num(kind()); }
|
||||
auto is_ref() const -> bool { return wasm::is_ref(kind()); }
|
||||
};
|
||||
|
||||
|
||||
// External Types
|
||||
|
||||
enum ExternKind {
|
||||
EXTERN_FUNC, EXTERN_GLOBAL, EXTERN_TABLE, EXTERN_MEMORY
|
||||
};
|
||||
|
||||
class FuncType;
|
||||
class GlobalType;
|
||||
class TableType;
|
||||
class MemoryType;
|
||||
|
||||
class ExternType {
|
||||
public:
|
||||
ExternType() = delete;
|
||||
~ExternType();
|
||||
void operator delete(void*);
|
||||
|
||||
auto copy() const-> own<ExternType*>;
|
||||
|
||||
auto kind() const -> ExternKind;
|
||||
|
||||
auto func() -> FuncType*;
|
||||
auto global() -> GlobalType*;
|
||||
auto table() -> TableType*;
|
||||
auto memory() -> MemoryType*;
|
||||
|
||||
auto func() const -> const FuncType*;
|
||||
auto global() const -> const GlobalType*;
|
||||
auto table() const -> const TableType*;
|
||||
auto memory() const -> const MemoryType*;
|
||||
};
|
||||
|
||||
|
||||
// Function Types
|
||||
|
||||
enum class arrow { ARROW };
|
||||
|
||||
class FuncType : public ExternType {
|
||||
public:
|
||||
FuncType() = delete;
|
||||
~FuncType();
|
||||
|
||||
static auto make(
|
||||
vec<ValType*>&& params = vec<ValType*>::make(),
|
||||
vec<ValType*>&& results = vec<ValType*>::make()
|
||||
) -> own<FuncType*>;
|
||||
|
||||
auto copy() const -> own<FuncType*>;
|
||||
|
||||
auto params() const -> const vec<ValType*>&;
|
||||
auto results() const -> const vec<ValType*>&;
|
||||
};
|
||||
|
||||
|
||||
// Global Types
|
||||
|
||||
class GlobalType : public ExternType {
|
||||
public:
|
||||
GlobalType() = delete;
|
||||
~GlobalType();
|
||||
|
||||
static auto make(own<ValType*>&&, Mutability) -> own<GlobalType*>;
|
||||
auto copy() const -> own<GlobalType*>;
|
||||
|
||||
auto content() const -> const ValType*;
|
||||
auto mutability() const -> Mutability;
|
||||
};
|
||||
|
||||
|
||||
// Table Types
|
||||
|
||||
class TableType : public ExternType {
|
||||
public:
|
||||
TableType() = delete;
|
||||
~TableType();
|
||||
|
||||
static auto make(own<ValType*>&&, Limits) -> own<TableType*>;
|
||||
auto copy() const -> own<TableType*>;
|
||||
|
||||
auto element() const -> const ValType*;
|
||||
auto limits() const -> const Limits&;
|
||||
};
|
||||
|
||||
|
||||
// Memory Types
|
||||
|
||||
class MemoryType : public ExternType {
|
||||
public:
|
||||
MemoryType() = delete;
|
||||
~MemoryType();
|
||||
|
||||
static auto make(Limits) -> own<MemoryType*>;
|
||||
auto copy() const -> own<MemoryType*>;
|
||||
|
||||
auto limits() const -> const Limits&;
|
||||
};
|
||||
|
||||
|
||||
// Import Types
|
||||
|
||||
using Name = vec<byte_t>;
|
||||
|
||||
class ImportType {
|
||||
public:
|
||||
ImportType() = delete;
|
||||
~ImportType();
|
||||
void operator delete(void*);
|
||||
|
||||
static auto make(Name&& module, Name&& name, own<ExternType*>&&) ->
|
||||
own<ImportType*>;
|
||||
auto copy() const -> own<ImportType*>;
|
||||
|
||||
auto module() const -> const Name&;
|
||||
auto name() const -> const Name&;
|
||||
auto type() const -> const ExternType*;
|
||||
};
|
||||
|
||||
|
||||
// Export Types
|
||||
|
||||
class ExportType {
|
||||
public:
|
||||
ExportType() = delete;
|
||||
~ExportType();
|
||||
void operator delete(void*);
|
||||
|
||||
static auto make(Name&&, own<ExternType*>&&) -> own<ExportType*>;
|
||||
auto copy() const -> own<ExportType*>;
|
||||
|
||||
auto name() const -> const Name&;
|
||||
auto type() const -> const ExternType*;
|
||||
};
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Runtime Objects
|
||||
|
||||
// References
|
||||
|
||||
class Ref {
|
||||
public:
|
||||
Ref() = delete;
|
||||
~Ref();
|
||||
void operator delete(void*);
|
||||
|
||||
auto copy() const -> own<Ref*>;
|
||||
|
||||
auto get_host_info() const -> void*;
|
||||
void set_host_info(void* info, void (*finalizer)(void*) = nullptr);
|
||||
};
|
||||
|
||||
|
||||
// Values
|
||||
|
||||
class Val {
|
||||
ValKind kind_;
|
||||
union impl {
|
||||
int32_t i32;
|
||||
int64_t i64;
|
||||
float32_t f32;
|
||||
float64_t f64;
|
||||
Ref* ref;
|
||||
} impl_;
|
||||
|
||||
Val(ValKind kind, impl impl) : kind_(kind), impl_(impl) {}
|
||||
|
||||
public:
|
||||
Val() : kind_(ANYREF) { impl_.ref = nullptr; }
|
||||
Val(int32_t i) : kind_(I32) { impl_.i32 = i; }
|
||||
Val(int64_t i) : kind_(I64) { impl_.i64 = i; }
|
||||
Val(float32_t z) : kind_(F32) { impl_.f32 = z; }
|
||||
Val(float64_t z) : kind_(F64) { impl_.f64 = z; }
|
||||
Val(own<Ref*>&& r) : kind_(ANYREF) { impl_.ref = r.release(); }
|
||||
|
||||
Val(Val&& that) : kind_(that.kind_), impl_(that.impl_) {
|
||||
if (is_ref()) that.impl_.ref = nullptr;
|
||||
}
|
||||
|
||||
~Val() {
|
||||
reset();
|
||||
}
|
||||
|
||||
auto is_num() const -> bool { return wasm::is_num(kind_); }
|
||||
auto is_ref() const -> bool { return wasm::is_ref(kind_); }
|
||||
|
||||
static auto i32(int32_t x) -> Val { return Val(x); }
|
||||
static auto i64(int64_t x) -> Val { return Val(x); }
|
||||
static auto f32(float32_t x) -> Val { return Val(x); }
|
||||
static auto f64(float64_t x) -> Val { return Val(x); }
|
||||
static auto ref(own<Ref*>&& x) -> Val { return Val(std::move(x)); }
|
||||
template<class T> inline static auto make(T x) -> Val;
|
||||
template<class T> inline static auto make(own<T>&& x) -> Val;
|
||||
|
||||
void reset() {
|
||||
if (is_ref() && impl_.ref) {
|
||||
delete impl_.ref;
|
||||
impl_.ref = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void reset(Val& that) {
|
||||
reset();
|
||||
kind_ = that.kind_;
|
||||
impl_ = that.impl_;
|
||||
if (is_ref()) that.impl_.ref = nullptr;
|
||||
}
|
||||
|
||||
auto operator=(Val&& that) -> Val& {
|
||||
reset(that);
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto kind() const -> ValKind { return kind_; }
|
||||
auto i32() const -> int32_t { assert(kind_ == I32); return impl_.i32; }
|
||||
auto i64() const -> int64_t { assert(kind_ == I64); return impl_.i64; }
|
||||
auto f32() const -> float32_t { assert(kind_ == F32); return impl_.f32; }
|
||||
auto f64() const -> float64_t { assert(kind_ == F64); return impl_.f64; }
|
||||
auto ref() const -> Ref* { assert(is_ref()); return impl_.ref; }
|
||||
template<class T> inline auto get() const -> T;
|
||||
|
||||
auto release_ref() -> own<Ref*> {
|
||||
assert(is_ref());
|
||||
auto ref = impl_.ref;
|
||||
ref = nullptr;
|
||||
return own<Ref*>(ref);
|
||||
}
|
||||
|
||||
auto copy() const -> Val {
|
||||
if (is_ref() && impl_.ref != nullptr) {
|
||||
impl impl;
|
||||
impl.ref = impl_.ref->copy().release();
|
||||
return Val(kind_, impl);
|
||||
} else {
|
||||
return Val(kind_, impl_);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<> inline auto Val::make<int32_t>(int32_t x) -> Val { return Val(x); }
|
||||
template<> inline auto Val::make<int64_t>(int64_t x) -> Val { return Val(x); }
|
||||
template<> inline auto Val::make<float32_t>(float32_t x) -> Val { return Val(x); }
|
||||
template<> inline auto Val::make<float64_t>(float64_t x) -> Val { return Val(x); }
|
||||
template<> inline auto Val::make<Ref*>(own<Ref*>&& x) -> Val {
|
||||
return Val(std::move(x));
|
||||
}
|
||||
|
||||
template<> inline auto Val::make<uint32_t>(uint32_t x) -> Val {
|
||||
return Val(static_cast<int32_t>(x));
|
||||
}
|
||||
template<> inline auto Val::make<uint64_t>(uint64_t x) -> Val {
|
||||
return Val(static_cast<int64_t>(x));
|
||||
}
|
||||
|
||||
template<> inline auto Val::get<int32_t>() const -> int32_t { return i32(); }
|
||||
template<> inline auto Val::get<int64_t>() const -> int64_t { return i64(); }
|
||||
template<> inline auto Val::get<float32_t>() const -> float32_t { return f32(); }
|
||||
template<> inline auto Val::get<float64_t>() const -> float64_t { return f64(); }
|
||||
template<> inline auto Val::get<Ref*>() const -> Ref* { return ref(); }
|
||||
|
||||
template<> inline auto Val::get<uint32_t>() const -> uint32_t {
|
||||
return static_cast<uint32_t>(i32());
|
||||
}
|
||||
template<> inline auto Val::get<uint64_t>() const -> uint64_t {
|
||||
return static_cast<uint64_t>(i64());
|
||||
}
|
||||
|
||||
|
||||
// Traps
|
||||
|
||||
using Message = vec<byte_t>; // null terminated
|
||||
|
||||
class Trap : public Ref {
|
||||
public:
|
||||
Trap() = delete;
|
||||
~Trap();
|
||||
|
||||
static auto make(Store*, const Message& msg) -> own<Trap*>;
|
||||
auto copy() const -> own<Trap*>;
|
||||
|
||||
auto message() const -> Message;
|
||||
};
|
||||
|
||||
|
||||
// Shared objects
|
||||
|
||||
template<class T>
|
||||
class Shared {
|
||||
public:
|
||||
Shared() = delete;
|
||||
~Shared();
|
||||
void operator delete(void*);
|
||||
};
|
||||
|
||||
|
||||
// Modules
|
||||
|
||||
class Module : public Ref {
|
||||
public:
|
||||
Module() = delete;
|
||||
~Module();
|
||||
|
||||
static auto validate(Store*, const vec<byte_t>& binary) -> bool;
|
||||
static auto make(Store*, const vec<byte_t>& binary) -> own<Module*>;
|
||||
auto copy() const -> own<Module*>;
|
||||
|
||||
auto imports() const -> vec<ImportType*>;
|
||||
auto exports() const -> vec<ExportType*>;
|
||||
|
||||
auto share() const -> own<Shared<Module>*>;
|
||||
static auto obtain(Store*, const Shared<Module>*) -> own<Module*>;
|
||||
|
||||
auto serialize() const -> vec<byte_t>;
|
||||
static auto deserialize(Store*, const vec<byte_t>&) -> own<Module*>;
|
||||
};
|
||||
|
||||
|
||||
// Foreign Objects
|
||||
|
||||
class Foreign : public Ref {
|
||||
public:
|
||||
Foreign() = delete;
|
||||
~Foreign();
|
||||
|
||||
static auto make(Store*) -> own<Foreign*>;
|
||||
auto copy() const -> own<Foreign*>;
|
||||
};
|
||||
|
||||
|
||||
// Externals
|
||||
|
||||
class Func;
|
||||
class Global;
|
||||
class Table;
|
||||
class Memory;
|
||||
|
||||
class Extern : public Ref {
|
||||
public:
|
||||
Extern() = delete;
|
||||
~Extern();
|
||||
|
||||
auto copy() const -> own<Extern*>;
|
||||
|
||||
auto kind() const -> ExternKind;
|
||||
auto type() const -> own<ExternType*>;
|
||||
|
||||
auto func() -> Func*;
|
||||
auto global() -> Global*;
|
||||
auto table() -> Table*;
|
||||
auto memory() -> Memory*;
|
||||
|
||||
auto func() const -> const Func*;
|
||||
auto global() const -> const Global*;
|
||||
auto table() const -> const Table*;
|
||||
auto memory() const -> const Memory*;
|
||||
};
|
||||
|
||||
|
||||
// Function Instances
|
||||
|
||||
class Func : public Extern {
|
||||
public:
|
||||
Func() = delete;
|
||||
~Func();
|
||||
|
||||
using callback = auto (*)(const Val[], Val[]) -> own<Trap*>;
|
||||
using callback_with_env = auto (*)(void*, const Val[], Val[]) -> own<Trap*>;
|
||||
|
||||
static auto make(Store*, const FuncType*, callback) -> own<Func*>;
|
||||
static auto make(Store*, const FuncType*, callback_with_env,
|
||||
void*, void (*finalizer)(void*) = nullptr) -> own<Func*>;
|
||||
auto copy() const -> own<Func*>;
|
||||
|
||||
auto type() const -> own<FuncType*>;
|
||||
auto param_arity() const -> size_t;
|
||||
auto result_arity() const -> size_t;
|
||||
|
||||
auto call(const Val[] = nullptr, Val[] = nullptr) const -> own<Trap*>;
|
||||
};
|
||||
|
||||
|
||||
// Global Instances
|
||||
|
||||
class Global : public Extern {
|
||||
public:
|
||||
Global() = delete;
|
||||
~Global();
|
||||
|
||||
static auto make(Store*, const GlobalType*, const Val&) -> own<Global*>;
|
||||
auto copy() const -> own<Global*>;
|
||||
|
||||
auto type() const -> own<GlobalType*>;
|
||||
auto get() const -> Val;
|
||||
void set(const Val&);
|
||||
};
|
||||
|
||||
|
||||
// Table Instances
|
||||
|
||||
class Table : public Extern {
|
||||
public:
|
||||
Table() = delete;
|
||||
~Table();
|
||||
|
||||
using size_t = uint32_t;
|
||||
|
||||
static auto make(
|
||||
Store*, const TableType*, const Ref* init = nullptr) -> own<Table*>;
|
||||
auto copy() const -> own<Table*>;
|
||||
|
||||
auto type() const -> own<TableType*>;
|
||||
auto get(size_t index) const -> own<Ref*>;
|
||||
auto set(size_t index, const Ref*) -> bool;
|
||||
auto size() const -> size_t;
|
||||
auto grow(size_t delta, const Ref* init = nullptr) -> bool;
|
||||
};
|
||||
|
||||
|
||||
// Memory Instances
|
||||
|
||||
class Memory : public Extern {
|
||||
public:
|
||||
Memory() = delete;
|
||||
~Memory();
|
||||
|
||||
static auto make(Store*, const MemoryType*) -> own<Memory*>;
|
||||
auto copy() const -> own<Memory*>;
|
||||
|
||||
using pages_t = uint32_t;
|
||||
|
||||
static const size_t page_size = 0x10000;
|
||||
|
||||
auto type() const -> own<MemoryType*>;
|
||||
auto data() const -> byte_t*;
|
||||
auto data_size() const -> size_t;
|
||||
auto size() const -> pages_t;
|
||||
auto grow(pages_t delta) -> bool;
|
||||
};
|
||||
|
||||
|
||||
// Module Instances
|
||||
|
||||
class Instance : public Ref {
|
||||
public:
|
||||
Instance() = delete;
|
||||
~Instance();
|
||||
|
||||
static auto make(
|
||||
Store*, const Module*, const Extern* const[]) -> own<Instance*>;
|
||||
auto copy() const -> own<Instance*>;
|
||||
|
||||
auto exports() const -> vec<Extern*>;
|
||||
};
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
} // namespave wasm
|
||||
|
||||
#endif // #ifdef __WASM_HH
|
Loading…
Reference in New Issue
Block a user