Implement RFC 11: Redesigning Wasmtime's APIs (#2897)
Implement Wasmtime's new API as designed by RFC 11. This is quite a large commit which has had lots of discussion externally, so for more information it's best to read the RFC thread and the PR thread.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
# Doxyfile 1.8.17
|
||||
# Doxyfile 1.9.1
|
||||
|
||||
# This file describes the settings to be used by the documentation system
|
||||
# doxygen (www.doxygen.org) for a project.
|
||||
@@ -32,7 +32,7 @@ DOXYFILE_ENCODING = UTF-8
|
||||
# title of most generated pages and in a few other places.
|
||||
# The default value is: My Project.
|
||||
|
||||
PROJECT_NAME = "Wasmtime"
|
||||
PROJECT_NAME = Wasmtime
|
||||
|
||||
# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
|
||||
# could be handy for archiving the generated documentation or if some version
|
||||
@@ -227,6 +227,14 @@ QT_AUTOBRIEF = NO
|
||||
|
||||
MULTILINE_CPP_IS_BRIEF = NO
|
||||
|
||||
# By default Python docstrings are displayed as preformatted text and doxygen's
|
||||
# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the
|
||||
# doxygen's special commands can be used and the contents of the docstring
|
||||
# documentation blocks is shown as doxygen documentation.
|
||||
# The default value is: YES.
|
||||
|
||||
PYTHON_DOCSTRING = YES
|
||||
|
||||
# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
|
||||
# documentation from any documented member that it re-implements.
|
||||
# The default value is: YES.
|
||||
@@ -263,12 +271,6 @@ TAB_SIZE = 4
|
||||
|
||||
ALIASES =
|
||||
|
||||
# This tag can be used to specify a number of word-keyword mappings (TCL only).
|
||||
# A mapping has the form "name=value". For example adding "class=itcl::class"
|
||||
# will allow you to use the command class in the itcl::class meaning.
|
||||
|
||||
TCL_SUBST =
|
||||
|
||||
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
|
||||
# only. Doxygen will then generate output that is more tailored for C. For
|
||||
# instance, some of the names that are used will be different. The list of all
|
||||
@@ -310,18 +312,21 @@ OPTIMIZE_OUTPUT_SLICE = NO
|
||||
# extension. Doxygen has a built-in mapping, but you can override or extend it
|
||||
# using this tag. The format is ext=language, where ext is a file extension, and
|
||||
# language is one of the parsers supported by doxygen: IDL, Java, JavaScript,
|
||||
# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice,
|
||||
# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, VHDL,
|
||||
# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
|
||||
# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
|
||||
# tries to guess whether the code is fixed or free formatted code, this is the
|
||||
# default for Fortran type files), VHDL, tcl. For instance to make doxygen treat
|
||||
# .inc files as Fortran files (default is PHP), and .f files as C (default is
|
||||
# Fortran), use: inc=Fortran f=C.
|
||||
# default for Fortran type files). For instance to make doxygen treat .inc files
|
||||
# as Fortran files (default is PHP), and .f files as C (default is Fortran),
|
||||
# use: inc=Fortran f=C.
|
||||
#
|
||||
# Note: For files without extension you can use no_extension as a placeholder.
|
||||
#
|
||||
# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
|
||||
# the files are not read by doxygen.
|
||||
# the files are not read by doxygen. When specifying no_extension you should add
|
||||
# * to the FILE_PATTERNS.
|
||||
#
|
||||
# Note see also the list of default file extension mappings.
|
||||
|
||||
EXTENSION_MAPPING =
|
||||
|
||||
@@ -455,6 +460,19 @@ TYPEDEF_HIDES_STRUCT = NO
|
||||
|
||||
LOOKUP_CACHE_SIZE = 0
|
||||
|
||||
# The NUM_PROC_THREADS specifies the number threads doxygen is allowed to use
|
||||
# during processing. When set to 0 doxygen will based this on the number of
|
||||
# cores available in the system. You can set it explicitly to a value larger
|
||||
# than 0 to get more control over the balance between CPU load and processing
|
||||
# speed. At this moment only the input processing can be done using multiple
|
||||
# threads. Since this is still an experimental feature the default is set to 1,
|
||||
# which efficively disables parallel processing. Please report any issues you
|
||||
# encounter. Generating dot graphs in parallel is controlled by the
|
||||
# DOT_NUM_THREADS setting.
|
||||
# Minimum value: 0, maximum value: 32, default value: 1.
|
||||
|
||||
NUM_PROC_THREADS = 1
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Build related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
@@ -518,6 +536,13 @@ EXTRACT_LOCAL_METHODS = NO
|
||||
|
||||
EXTRACT_ANON_NSPACES = NO
|
||||
|
||||
# If this flag is set to YES, the name of an unnamed parameter in a declaration
|
||||
# will be determined by the corresponding definition. By default unnamed
|
||||
# parameters remain unnamed in the output.
|
||||
# The default value is: YES.
|
||||
|
||||
RESOLVE_UNNAMED_PARAMS = YES
|
||||
|
||||
# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
|
||||
# undocumented members inside documented classes or files. If set to NO these
|
||||
# members will be included in the various overviews, but no documentation
|
||||
@@ -555,11 +580,18 @@ HIDE_IN_BODY_DOCS = NO
|
||||
|
||||
INTERNAL_DOCS = NO
|
||||
|
||||
# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
|
||||
# names in lower-case letters. If set to YES, upper-case letters are also
|
||||
# allowed. This is useful if you have classes or files whose names only differ
|
||||
# in case and if your file system supports case sensitive file names. Windows
|
||||
# (including Cygwin) ands Mac users are advised to set this option to NO.
|
||||
# With the correct setting of option CASE_SENSE_NAMES doxygen will better be
|
||||
# able to match the capabilities of the underlying filesystem. In case the
|
||||
# filesystem is case sensitive (i.e. it supports files in the same directory
|
||||
# whose names only differ in casing), the option must be set to YES to properly
|
||||
# deal with such files in case they appear in the input. For filesystems that
|
||||
# are not case sensitive the option should be be set to NO to properly deal with
|
||||
# output files written for symbols that only differ in casing, such as for two
|
||||
# classes, one named CLASS and the other named Class, and to also support
|
||||
# references to files without having to specify the exact matching casing. On
|
||||
# Windows (including Cygwin) and MacOS, users should typically set this option
|
||||
# to NO, whereas on Linux or other Unix flavors it should typically be set to
|
||||
# YES.
|
||||
# The default value is: system dependent.
|
||||
|
||||
CASE_SENSE_NAMES = YES
|
||||
@@ -798,7 +830,10 @@ WARN_IF_DOC_ERROR = YES
|
||||
WARN_NO_PARAMDOC = NO
|
||||
|
||||
# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
|
||||
# a warning is encountered.
|
||||
# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS
|
||||
# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but
|
||||
# at the end of the doxygen process doxygen will return with a non-zero status.
|
||||
# Possible values are: NO, YES and FAIL_ON_WARNINGS.
|
||||
# The default value is: NO.
|
||||
|
||||
WARN_AS_ERROR = YES
|
||||
@@ -829,13 +864,13 @@ WARN_LOGFILE =
|
||||
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
|
||||
# Note: If this tag is empty the current directory is searched.
|
||||
|
||||
INPUT =
|
||||
INPUT = include wasm-c-api/include
|
||||
|
||||
# This tag can be used to specify the character encoding of the source files
|
||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
||||
# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
|
||||
# documentation (see: https://www.gnu.org/software/libiconv/) for the list of
|
||||
# possible encodings.
|
||||
# documentation (see:
|
||||
# https://www.gnu.org/software/libiconv/) for the list of possible encodings.
|
||||
# The default value is: UTF-8.
|
||||
|
||||
INPUT_ENCODING = UTF-8
|
||||
@@ -848,13 +883,15 @@ INPUT_ENCODING = UTF-8
|
||||
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
|
||||
# read by doxygen.
|
||||
#
|
||||
# Note the list of default checked file patterns might differ from the list of
|
||||
# default file extension mappings.
|
||||
#
|
||||
# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
|
||||
# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
|
||||
# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
|
||||
# *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment),
|
||||
# *.doc (to be provided as doxygen C comment), *.txt (to be provided as doxygen
|
||||
# C comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f, *.for, *.tcl, *.vhd,
|
||||
# *.vhdl, *.ucf, *.qsf and *.ice.
|
||||
# *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd, *.vhdl,
|
||||
# *.ucf, *.qsf and *.ice.
|
||||
|
||||
FILE_PATTERNS = *.h
|
||||
|
||||
@@ -899,13 +936,14 @@ EXCLUDE_PATTERNS =
|
||||
# exclude all test directories use the pattern */test/*
|
||||
|
||||
EXCLUDE_SYMBOLS = assertions \
|
||||
WASM_DECLARE_* \
|
||||
WASM_API_EXTERN \
|
||||
WASI_API_EXTERN \
|
||||
WASMTIME_DECLARE_OWN \
|
||||
WASI_DECLARE_OWN \
|
||||
WASMTIME_CONFIG_PROP \
|
||||
own
|
||||
WASM_DECLARE_* \
|
||||
WASM_API_EXTERN \
|
||||
WASI_API_EXTERN \
|
||||
WASMTIME_DECLARE_OWN \
|
||||
WASI_DECLARE_OWN \
|
||||
WASMTIME_CONFIG_PROP \
|
||||
own \
|
||||
wasm_*_enum
|
||||
|
||||
# The EXAMPLE_PATH tag can be used to specify one or more files or directories
|
||||
# that contain example code fragments that are included (see the \include
|
||||
@@ -1075,35 +1113,6 @@ USE_HTAGS = NO
|
||||
|
||||
VERBATIM_HEADERS = YES
|
||||
|
||||
# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the
|
||||
# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the
|
||||
# cost of reduced performance. This can be particularly helpful with template
|
||||
# rich C++ code for which doxygen's built-in parser lacks the necessary type
|
||||
# information.
|
||||
# Note: The availability of this option depends on whether or not doxygen was
|
||||
# generated with the -Duse_libclang=ON option for CMake.
|
||||
# The default value is: NO.
|
||||
|
||||
CLANG_ASSISTED_PARSING = NO
|
||||
|
||||
# If clang assisted parsing is enabled you can provide the compiler with command
|
||||
# line options that you would normally use when invoking the compiler. Note that
|
||||
# the include paths will already be set by doxygen for the files and directories
|
||||
# specified with INPUT and INCLUDE_PATH.
|
||||
# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
|
||||
|
||||
CLANG_OPTIONS =
|
||||
|
||||
# If clang assisted parsing is enabled you can provide the clang parser with the
|
||||
# path to the compilation database (see:
|
||||
# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) used when the files
|
||||
# were built. This is equivalent to specifying the "-p" option to a clang tool,
|
||||
# such as clang-check. These options will then be passed to the parser.
|
||||
# Note: The availability of this option depends on whether or not doxygen was
|
||||
# generated with the -Duse_libclang=ON option for CMake.
|
||||
|
||||
CLANG_DATABASE_PATH =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the alphabetical class index
|
||||
#---------------------------------------------------------------------------
|
||||
@@ -1115,13 +1124,6 @@ CLANG_DATABASE_PATH =
|
||||
|
||||
ALPHABETICAL_INDEX = YES
|
||||
|
||||
# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
|
||||
# which the alphabetical index list will be split.
|
||||
# Minimum value: 1, maximum value: 20, default value: 5.
|
||||
# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
|
||||
|
||||
COLS_IN_ALPHA_INDEX = 5
|
||||
|
||||
# In case all classes in a project start with a common prefix, all classes will
|
||||
# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
|
||||
# can be used to specify a prefix (or a list of prefixes) that should be ignored
|
||||
@@ -1292,10 +1294,11 @@ HTML_INDEX_NUM_ENTRIES = 100
|
||||
|
||||
# If the GENERATE_DOCSET tag is set to YES, additional index files will be
|
||||
# generated that can be used as input for Apple's Xcode 3 integrated development
|
||||
# environment (see: https://developer.apple.com/xcode/), introduced with OSX
|
||||
# 10.5 (Leopard). To create a documentation set, doxygen will generate a
|
||||
# Makefile in the HTML output directory. Running make will produce the docset in
|
||||
# that directory and running make install will install the docset in
|
||||
# environment (see:
|
||||
# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To
|
||||
# create a documentation set, doxygen will generate a Makefile in the HTML
|
||||
# output directory. Running make will produce the docset in that directory and
|
||||
# running make install will install the docset in
|
||||
# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
|
||||
# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy
|
||||
# genXcode/_index.html for more information.
|
||||
@@ -1337,8 +1340,8 @@ DOCSET_PUBLISHER_NAME = Publisher
|
||||
# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
|
||||
# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
|
||||
# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
|
||||
# (see: https://www.microsoft.com/en-us/download/details.aspx?id=21138) on
|
||||
# Windows.
|
||||
# (see:
|
||||
# https://www.microsoft.com/en-us/download/details.aspx?id=21138) on Windows.
|
||||
#
|
||||
# The HTML Help Workshop contains a compiler that can convert all HTML output
|
||||
# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
|
||||
@@ -1368,7 +1371,7 @@ CHM_FILE =
|
||||
HHC_LOCATION =
|
||||
|
||||
# The GENERATE_CHI flag controls if a separate .chi index file is generated
|
||||
# (YES) or that it should be included in the master .chm file (NO).
|
||||
# (YES) or that it should be included in the main .chm file (NO).
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
|
||||
|
||||
@@ -1413,7 +1416,8 @@ QCH_FILE =
|
||||
|
||||
# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
|
||||
# Project output. For more information please see Qt Help Project / Namespace
|
||||
# (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
|
||||
# (see:
|
||||
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
|
||||
# The default value is: org.doxygen.Project.
|
||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||
|
||||
@@ -1421,8 +1425,8 @@ QHP_NAMESPACE = org.doxygen.Project
|
||||
|
||||
# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
|
||||
# Help Project output. For more information please see Qt Help Project / Virtual
|
||||
# Folders (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-
|
||||
# folders).
|
||||
# Folders (see:
|
||||
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders).
|
||||
# The default value is: doc.
|
||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||
|
||||
@@ -1430,16 +1434,16 @@ QHP_VIRTUAL_FOLDER = doc
|
||||
|
||||
# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
|
||||
# filter to add. For more information please see Qt Help Project / Custom
|
||||
# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
|
||||
# filters).
|
||||
# Filters (see:
|
||||
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
|
||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||
|
||||
QHP_CUST_FILTER_NAME =
|
||||
|
||||
# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
|
||||
# custom filter to add. For more information please see Qt Help Project / Custom
|
||||
# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
|
||||
# filters).
|
||||
# Filters (see:
|
||||
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
|
||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||
|
||||
QHP_CUST_FILTER_ATTRS =
|
||||
@@ -1451,9 +1455,9 @@ QHP_CUST_FILTER_ATTRS =
|
||||
|
||||
QHP_SECT_FILTER_ATTRS =
|
||||
|
||||
# The QHG_LOCATION tag can be used to specify the location of Qt's
|
||||
# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
|
||||
# generated .qhp file.
|
||||
# The QHG_LOCATION tag can be used to specify the location (absolute path
|
||||
# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to
|
||||
# run qhelpgenerator on the generated .qhp file.
|
||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||
|
||||
QHG_LOCATION =
|
||||
@@ -1504,7 +1508,7 @@ DISABLE_INDEX = NO
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
GENERATE_TREEVIEW = NO
|
||||
GENERATE_TREEVIEW = YES
|
||||
|
||||
# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
|
||||
# doxygen will group on one line in the generated HTML documentation.
|
||||
@@ -1530,6 +1534,17 @@ TREEVIEW_WIDTH = 250
|
||||
|
||||
EXT_LINKS_IN_WINDOW = NO
|
||||
|
||||
# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg
|
||||
# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see
|
||||
# https://inkscape.org) to generate formulas as SVG images instead of PNGs for
|
||||
# the HTML output. These images will generally look nicer at scaled resolutions.
|
||||
# Possible values are: png (the default) and svg (looks nicer but requires the
|
||||
# pdf2svg or inkscape tool).
|
||||
# The default value is: png.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
HTML_FORMULA_FORMAT = png
|
||||
|
||||
# Use this tag to change the font size of LaTeX formulas included as images in
|
||||
# the HTML documentation. When you change the font size after a successful
|
||||
# doxygen run you need to manually remove any form_*.png images from the HTML
|
||||
@@ -1569,7 +1584,7 @@ USE_MATHJAX = NO
|
||||
|
||||
# When MathJax is enabled you can set the default output format to be used for
|
||||
# the MathJax output. See the MathJax site (see:
|
||||
# http://docs.mathjax.org/en/latest/output.html) for more details.
|
||||
# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details.
|
||||
# Possible values are: HTML-CSS (which is slower, but has the best
|
||||
# compatibility), NativeMML (i.e. MathML) and SVG.
|
||||
# The default value is: HTML-CSS.
|
||||
@@ -1585,7 +1600,7 @@ MATHJAX_FORMAT = HTML-CSS
|
||||
# Content Delivery Network so you can quickly see the result without installing
|
||||
# MathJax. However, it is strongly recommended to install a local copy of
|
||||
# MathJax from https://www.mathjax.org before deployment.
|
||||
# The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/.
|
||||
# The default value is: https://cdn.jsdelivr.net/npm/mathjax@2.
|
||||
# This tag requires that the tag USE_MATHJAX is set to YES.
|
||||
|
||||
MATHJAX_RELPATH = https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/
|
||||
@@ -1599,7 +1614,8 @@ MATHJAX_EXTENSIONS =
|
||||
|
||||
# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
|
||||
# of code that will be used on startup of the MathJax code. See the MathJax site
|
||||
# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
|
||||
# (see:
|
||||
# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an
|
||||
# example see the documentation.
|
||||
# This tag requires that the tag USE_MATHJAX is set to YES.
|
||||
|
||||
@@ -1646,7 +1662,8 @@ SERVER_BASED_SEARCH = NO
|
||||
#
|
||||
# Doxygen ships with an example indexer (doxyindexer) and search engine
|
||||
# (doxysearch.cgi) which are based on the open source search engine library
|
||||
# Xapian (see: https://xapian.org/).
|
||||
# Xapian (see:
|
||||
# https://xapian.org/).
|
||||
#
|
||||
# See the section "External Indexing and Searching" for details.
|
||||
# The default value is: NO.
|
||||
@@ -1659,8 +1676,9 @@ EXTERNAL_SEARCH = NO
|
||||
#
|
||||
# Doxygen ships with an example indexer (doxyindexer) and search engine
|
||||
# (doxysearch.cgi) which are based on the open source search engine library
|
||||
# Xapian (see: https://xapian.org/). See the section "External Indexing and
|
||||
# Searching" for details.
|
||||
# Xapian (see:
|
||||
# https://xapian.org/). See the section "External Indexing and Searching" for
|
||||
# details.
|
||||
# This tag requires that the tag SEARCHENGINE is set to YES.
|
||||
|
||||
SEARCHENGINE_URL =
|
||||
@@ -1824,9 +1842,11 @@ LATEX_EXTRA_FILES =
|
||||
|
||||
PDF_HYPERLINKS = YES
|
||||
|
||||
# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
|
||||
# the PDF file directly from the LaTeX files. Set this option to YES, to get a
|
||||
# higher quality PDF documentation.
|
||||
# If the USE_PDFLATEX tag is set to YES, doxygen will use the engine as
|
||||
# specified with LATEX_CMD_NAME to generate the PDF file directly from the LaTeX
|
||||
# files. Set this option to YES, to get a higher quality PDF documentation.
|
||||
#
|
||||
# See also section LATEX_CMD_NAME for selecting the engine.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
@@ -2142,7 +2162,8 @@ SEARCH_INCLUDES = YES
|
||||
# preprocessor.
|
||||
# This tag requires that the tag SEARCH_INCLUDES is set to YES.
|
||||
|
||||
INCLUDE_PATH = wasm-c-api/include include
|
||||
INCLUDE_PATH = wasm-c-api/include \
|
||||
include
|
||||
|
||||
# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
|
||||
# patterns (like *.h and *.hpp) to filter out the header-files in the
|
||||
@@ -2150,7 +2171,7 @@ INCLUDE_PATH = wasm-c-api/include include
|
||||
# used.
|
||||
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
||||
|
||||
INCLUDE_FILE_PATTERNS =
|
||||
INCLUDE_FILE_PATTERNS = *.h
|
||||
|
||||
# The PREDEFINED tag can be used to specify one or more macro names that are
|
||||
# defined before the preprocessor is started (similar to the -D option of e.g.
|
||||
@@ -2258,9 +2279,9 @@ HIDE_UNDOC_RELATIONS = YES
|
||||
# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
|
||||
# Bell Labs. The other options in this section have no effect if this option is
|
||||
# set to NO
|
||||
# The default value is: YES.
|
||||
# The default value is: NO.
|
||||
|
||||
HAVE_DOT = YES
|
||||
HAVE_DOT = NO
|
||||
|
||||
# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
|
||||
# to run in parallel. When set to 0 doxygen will base this on the number of
|
||||
@@ -2337,10 +2358,32 @@ UML_LOOK = NO
|
||||
# but if the number exceeds 15, the total amount of fields shown is limited to
|
||||
# 10.
|
||||
# Minimum value: 0, maximum value: 100, default value: 10.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
# This tag requires that the tag UML_LOOK is set to YES.
|
||||
|
||||
UML_LIMIT_NUM_FIELDS = 10
|
||||
|
||||
# If the DOT_UML_DETAILS tag is set to NO, doxygen will show attributes and
|
||||
# methods without types and arguments in the UML graphs. If the DOT_UML_DETAILS
|
||||
# tag is set to YES, doxygen will add type and arguments for attributes and
|
||||
# methods in the UML graphs. If the DOT_UML_DETAILS tag is set to NONE, doxygen
|
||||
# will not generate fields with class member information in the UML graphs. The
|
||||
# class diagrams will look similar to the default class diagrams but using UML
|
||||
# notation for the relationships.
|
||||
# Possible values are: NO, YES and NONE.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag UML_LOOK is set to YES.
|
||||
|
||||
DOT_UML_DETAILS = NO
|
||||
|
||||
# The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters
|
||||
# to display on a single line. If the actual line length exceeds this threshold
|
||||
# significantly it will wrapped across multiple lines. Some heuristics are apply
|
||||
# to avoid ugly line breaks.
|
||||
# Minimum value: 0, maximum value: 1000, default value: 17.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
|
||||
DOT_WRAP_THRESHOLD = 17
|
||||
|
||||
# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
|
||||
# collaboration graphs will show the relations between templates and their
|
||||
# instances.
|
||||
@@ -2414,9 +2457,7 @@ DIRECTORY_GRAPH = YES
|
||||
# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
|
||||
# to make the SVG files visible in IE 9+ (other browsers do not have this
|
||||
# requirement).
|
||||
# Possible values are: png, png:cairo, png:cairo:cairo, png:cairo:gd, png:gd,
|
||||
# png:gd:gd, jpg, jpg:cairo, jpg:cairo:gd, jpg:gd, jpg:gd:gd, gif, gif:cairo,
|
||||
# gif:cairo:gd, gif:gd, gif:gd:gd, svg, png:gd, png:gd:gd, png:cairo,
|
||||
# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo,
|
||||
# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
|
||||
# png:gdiplus:gdiplus.
|
||||
# The default value is: png.
|
||||
@@ -2532,9 +2573,11 @@ DOT_MULTI_TARGETS = NO
|
||||
|
||||
GENERATE_LEGEND = YES
|
||||
|
||||
# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
|
||||
# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate
|
||||
# files that are used to generate the various graphs.
|
||||
#
|
||||
# Note: This setting is not only used for dot files but also for msc and
|
||||
# plantuml temporary files.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
|
||||
DOT_CLEANUP = YES
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -32,9 +32,9 @@ extern "C" {
|
||||
* \brief Convenience alias for #wasi_config_t
|
||||
*
|
||||
* \struct wasi_config_t
|
||||
* \brief Opaque type used to create a #wasi_instance_t.
|
||||
* \brief TODO
|
||||
*
|
||||
* \fn void wasi_config_delete(own wasi_config_t *);
|
||||
* \fn void wasi_config_delete(wasi_config_t *);
|
||||
* \brief Deletes a configuration object.
|
||||
*/
|
||||
WASI_DECLARE_OWN(config)
|
||||
@@ -146,64 +146,6 @@ WASI_API_EXTERN void wasi_config_inherit_stderr(wasi_config_t* config);
|
||||
*/
|
||||
WASI_API_EXTERN bool wasi_config_preopen_dir(wasi_config_t* config, const char* path, const char* guest_path);
|
||||
|
||||
/**
|
||||
* \typedef wasi_instance_t
|
||||
* \brief Convenience alias for #wasi_instance_t
|
||||
*
|
||||
* \struct wasi_instance_t
|
||||
* \brief Opaque type representing a WASI instance.
|
||||
*
|
||||
* \fn void wasi_instance_delete(own wasi_instance_t *);
|
||||
* \brief Deletes an instance object.
|
||||
*/
|
||||
WASI_DECLARE_OWN(instance)
|
||||
|
||||
/**
|
||||
* \brief Creates a new WASI instance from the specified configuration.
|
||||
*
|
||||
* \param store the store which functions will be attached to
|
||||
* \param name the WASI module name that is being instantiated, currently either
|
||||
* `wasi_unstable` or `wasi_snapshot_preview`.
|
||||
* \param config the configuration object which has settings for how WASI APIs
|
||||
* will behave.
|
||||
* \param trap a location, if `NULL` is returned, that contains information
|
||||
* about why instantiation failed.
|
||||
*
|
||||
* \return a #wasi_instance_t owned by the caller on success or `NULL` on
|
||||
* failure.
|
||||
*
|
||||
* Note that this function takes ownership of the `config` argument whether this
|
||||
* function succeeds or not. Ownership of the #wasi_instance_t and #wasm_trap_t
|
||||
* are transferred to the caller.
|
||||
*
|
||||
* With a #wasi_instance_t you'll likely call either
|
||||
* #wasmtime_linker_define_wasi or #wasi_instance_bind_import afterwards.
|
||||
*/
|
||||
WASI_API_EXTERN own wasi_instance_t* wasi_instance_new(
|
||||
wasm_store_t* store,
|
||||
const char* name,
|
||||
own wasi_config_t* config,
|
||||
own wasm_trap_t** trap
|
||||
);
|
||||
|
||||
/**
|
||||
* \brief Extracts a matching item for the given import from a #wasi_instance_t.
|
||||
*
|
||||
* \param instance the WASI instance an export is extracted from
|
||||
* \param import the desired import type that is being extracted, typically
|
||||
* acquired from #wasm_module_imports.
|
||||
*
|
||||
* \return a #wasm_extern_t which can be used to satisfy the `import`
|
||||
* requested, or `NULL` if the provided `instance` cannot satisfy `import`.
|
||||
*
|
||||
* This function does not take ownership of its arguments, and the lifetime of
|
||||
* the #wasm_extern_t is tied to the #wasi_instance_t argument.
|
||||
*/
|
||||
WASI_API_EXTERN const wasm_extern_t* wasi_instance_bind_import(
|
||||
const wasi_instance_t* instance,
|
||||
const wasm_importtype_t* import
|
||||
);
|
||||
|
||||
#undef own
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
264
crates/c-api/include/wasmtime/config.h
Normal file
264
crates/c-api/include/wasmtime/config.h
Normal file
@@ -0,0 +1,264 @@
|
||||
/**
|
||||
* \file wasmtime/config.h
|
||||
*
|
||||
* \brief Wasmtime-specific extensions to #wasm_config_t
|
||||
*/
|
||||
|
||||
#ifndef WASMTIME_CONFIG_H
|
||||
#define WASMTIME_CONFIG_H
|
||||
|
||||
#include <wasm.h>
|
||||
#include <wasmtime/error.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Specifier for how Wasmtime will compile code, values are in
|
||||
* #wasmtime_strategy_enum
|
||||
*/
|
||||
typedef uint8_t wasmtime_strategy_t;
|
||||
|
||||
/**
|
||||
* \brief Different ways that Wasmtime can compile WebAssembly
|
||||
*
|
||||
* The default value is #WASMTIME_STRATEGY_AUTO.
|
||||
*/
|
||||
enum wasmtime_strategy_enum { // Strategy
|
||||
/// Wasmtime will automatically determine whether to use Cranelift or
|
||||
/// Lightbeam, and currently it will always pick Cranelift. This default may
|
||||
/// change over time though.
|
||||
WASMTIME_STRATEGY_AUTO,
|
||||
|
||||
/// Indicates that Cranelift will unconditionally use Cranelift to compile
|
||||
/// WebAssembly code.
|
||||
WASMTIME_STRATEGY_CRANELIFT,
|
||||
|
||||
/// Indicates that Cranelift will unconditionally use Lightbeam to compile
|
||||
/// WebAssembly code. Note that Lightbeam isn't always enabled at compile
|
||||
/// time, and if that's the case an error will be returned.
|
||||
WASMTIME_STRATEGY_LIGHTBEAM,
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Specifier of what optimization level to use for generated JIT code.
|
||||
*
|
||||
* See #wasmtime_opt_level_enum for possible values.
|
||||
*/
|
||||
typedef uint8_t wasmtime_opt_level_t;
|
||||
|
||||
/**
|
||||
* \brief Different ways Wasmtime can optimize generated code.
|
||||
*
|
||||
* The default value is #WASMTIME_OPT_LEVEL_SPEED.
|
||||
*/
|
||||
enum wasmtime_opt_level_enum { // OptLevel
|
||||
/// Generated code will not be optimized at all.
|
||||
WASMTIME_OPT_LEVEL_NONE,
|
||||
/// Generated code will be optimized purely for speed.
|
||||
WASMTIME_OPT_LEVEL_SPEED,
|
||||
/// Generated code will be optimized, but some speed optimizations are
|
||||
/// disabled if they cause the generated code to be significantly larger.
|
||||
WASMTIME_OPT_LEVEL_SPEED_AND_SIZE,
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Different ways wasmtime can enable profiling JIT code.
|
||||
*
|
||||
* See #wasmtime_profiling_strategy_enum for possible values.
|
||||
*/
|
||||
typedef uint8_t wasmtime_profiling_strategy_t;
|
||||
|
||||
/**
|
||||
* \brief Different ways to profile JIT code.
|
||||
*
|
||||
* The default is #WASMTIME_PROFILING_STRATEGY_NONE.
|
||||
*/
|
||||
enum wasmtime_profiling_strategy_enum { // ProfilingStrategy
|
||||
/// No profiling is enabled at runtime.
|
||||
WASMTIME_PROFILING_STRATEGY_NONE,
|
||||
/// Linux's "jitdump" support in `perf` is enabled and when Wasmtime is run
|
||||
/// under `perf` necessary calls will be made to profile generated JIT code.
|
||||
WASMTIME_PROFILING_STRATEGY_JITDUMP,
|
||||
/// Support for VTune will be enabled and the VTune runtime will be informed,
|
||||
/// at runtime, about JIT code.
|
||||
///
|
||||
/// Note that this isn't always enabled at build time.
|
||||
WASMTIME_PROFILING_STRATEGY_VTUNE,
|
||||
};
|
||||
|
||||
#define WASMTIME_CONFIG_PROP(ret, name, ty) \
|
||||
WASM_API_EXTERN ret wasmtime_config_##name##_set(wasm_config_t*, ty);
|
||||
|
||||
/**
|
||||
* \brief Configures whether DWARF debug information is constructed at runtime
|
||||
* to describe JIT code.
|
||||
*
|
||||
* This setting is `false` by default. When enabled it will attempt to inform
|
||||
* native debuggers about DWARF debugging information for JIT code to more
|
||||
* easily debug compiled WebAssembly via native debuggers. This can also
|
||||
* sometimes improve the quality of output when profiling is enabled.
|
||||
*/
|
||||
WASMTIME_CONFIG_PROP(void, debug_info, bool)
|
||||
|
||||
/**
|
||||
* \brief Enables WebAssembly code to be interrupted.
|
||||
*
|
||||
* This setting is `false` by default. When enabled it will enable getting an
|
||||
* interrupt handle via #wasmtime_interrupt_handle_new which can be used to
|
||||
* interrupt currently-executing WebAssembly code.
|
||||
*/
|
||||
WASMTIME_CONFIG_PROP(void, interruptable, bool)
|
||||
|
||||
/**
|
||||
* \brief Whether or not fuel is enabled for generated code.
|
||||
*
|
||||
* This setting is `false` by default. When enabled it will enable fuel counting
|
||||
* meaning that fuel will be consumed every time a wasm instruction is executed,
|
||||
* and trap when reaching zero.
|
||||
*/
|
||||
WASMTIME_CONFIG_PROP(void, consume_fuel, bool)
|
||||
|
||||
/**
|
||||
* \brief Configures the maximum stack size, in bytes, that JIT code can use.
|
||||
*
|
||||
* This setting is 2MB by default. Configuring this setting will limit the
|
||||
* amount of native stack space that JIT code can use while it is executing. If
|
||||
* you're hitting stack overflow you can try making this setting larger, or if
|
||||
* you'd like to limit wasm programs to less stack you can also configure this.
|
||||
*
|
||||
* Note that this setting is not interpreted with 100% precision. Additionally
|
||||
* the amount of stack space that wasm takes is always relative to the first
|
||||
* invocation of wasm on the stack, so recursive calls with host frames in the
|
||||
* middle will all need to fit within this setting.
|
||||
*/
|
||||
WASMTIME_CONFIG_PROP(void, max_wasm_stack, size_t)
|
||||
|
||||
/**
|
||||
* \brief Configures whether the WebAssembly threading proposal is enabled.
|
||||
*
|
||||
* This setting is `false` by default.
|
||||
*
|
||||
* Note that threads are largely unimplemented in Wasmtime at this time.
|
||||
*/
|
||||
WASMTIME_CONFIG_PROP(void, wasm_threads, bool)
|
||||
|
||||
/**
|
||||
* \brief Configures whether the WebAssembly reference types proposal is
|
||||
* enabled.
|
||||
*
|
||||
* This setting is `false` by default.
|
||||
*/
|
||||
WASMTIME_CONFIG_PROP(void, wasm_reference_types, bool)
|
||||
|
||||
/**
|
||||
* \brief Configures whether the WebAssembly SIMD proposal is
|
||||
* enabled.
|
||||
*
|
||||
* This setting is `false` by default.
|
||||
*/
|
||||
WASMTIME_CONFIG_PROP(void, wasm_simd, bool)
|
||||
|
||||
/**
|
||||
* \brief Configures whether the WebAssembly bulk memory proposal is
|
||||
* enabled.
|
||||
*
|
||||
* This setting is `false` by default.
|
||||
*/
|
||||
WASMTIME_CONFIG_PROP(void, wasm_bulk_memory, bool)
|
||||
|
||||
/**
|
||||
* \brief Configures whether the WebAssembly multi value proposal is
|
||||
* enabled.
|
||||
*
|
||||
* This setting is `true` by default.
|
||||
*/
|
||||
WASMTIME_CONFIG_PROP(void, wasm_multi_value, bool)
|
||||
|
||||
/**
|
||||
* \brief Configures whether the WebAssembly module linking proposal is
|
||||
* enabled.
|
||||
*
|
||||
* This setting is `false` by default.
|
||||
*/
|
||||
WASMTIME_CONFIG_PROP(void, wasm_module_linking, bool)
|
||||
|
||||
/**
|
||||
* \brief Configures how JIT code will be compiled.
|
||||
*
|
||||
* This setting is #WASMTIME_STRATEGY_AUTO by default.
|
||||
*
|
||||
* If the compilation strategy selected could not be enabled then an error is
|
||||
* returned.
|
||||
*/
|
||||
WASMTIME_CONFIG_PROP(wasmtime_error_t*, strategy, wasmtime_strategy_t)
|
||||
|
||||
/**
|
||||
* \brief Configures whether Cranelift's debug verifier is enabled.
|
||||
*
|
||||
* This setting in `false` by default.
|
||||
*
|
||||
* When cranelift is used for compilation this enables expensive debug checks
|
||||
* within Cranelift itself to verify it's correct.
|
||||
*/
|
||||
WASMTIME_CONFIG_PROP(void, cranelift_debug_verifier, bool)
|
||||
|
||||
/**
|
||||
* \brief Configures Cranelift's optimization level for JIT code.
|
||||
*
|
||||
* This setting in #WASMTIME_OPT_LEVEL_SPEED by default.
|
||||
*/
|
||||
WASMTIME_CONFIG_PROP(void, cranelift_opt_level, wasmtime_opt_level_t)
|
||||
|
||||
/**
|
||||
* \brief Configures the profiling strategy used for JIT code.
|
||||
*
|
||||
* This setting in #WASMTIME_PROFILING_STRATEGY_NONE by default.
|
||||
*/
|
||||
WASMTIME_CONFIG_PROP(wasmtime_error_t*, profiler, wasmtime_profiling_strategy_t)
|
||||
|
||||
/**
|
||||
* \brief Configures the maximum size for memory to be considered "static"
|
||||
*
|
||||
* For more information see the Rust documentation at
|
||||
* https://bytecodealliance.github.io/wasmtime/api/wasmtime/struct.Config.html#method.static_memory_maximum_size.
|
||||
*/
|
||||
WASMTIME_CONFIG_PROP(void, static_memory_maximum_size, uint64_t)
|
||||
|
||||
/**
|
||||
* \brief Configures the guard region size for "static" memory.
|
||||
*
|
||||
* For more information see the Rust documentation at
|
||||
* https://bytecodealliance.github.io/wasmtime/api/wasmtime/struct.Config.html#method.static_memory_guard_size.
|
||||
*/
|
||||
WASMTIME_CONFIG_PROP(void, static_memory_guard_size, uint64_t)
|
||||
|
||||
/**
|
||||
* \brief Configures the guard region size for "dynamic" memory.
|
||||
*
|
||||
* For more information see the Rust documentation at
|
||||
* https://bytecodealliance.github.io/wasmtime/api/wasmtime/struct.Config.html#method.dynamic_memory_guard_size.
|
||||
*/
|
||||
WASMTIME_CONFIG_PROP(void, dynamic_memory_guard_size, uint64_t)
|
||||
|
||||
/**
|
||||
* \brief Enables Wasmtime's cache and loads configuration from the specified
|
||||
* path.
|
||||
*
|
||||
* By default the Wasmtime compilation cache is disabled. The configuration path
|
||||
* here can be `NULL` to use the default settings, and otherwise the argument
|
||||
* here must be a file on the filesystem with TOML configuration -
|
||||
* https://bytecodealliance.github.io/wasmtime/cli-cache.html.
|
||||
*
|
||||
* An error is returned if the cache configuration could not be loaded or if the
|
||||
* cache could not be enabled.
|
||||
*/
|
||||
WASM_API_EXTERN wasmtime_error_t* wasmtime_config_cache_config_load(wasm_config_t*, const char*);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // WASMTIME_CONFIG_H
|
||||
|
||||
55
crates/c-api/include/wasmtime/error.h
Normal file
55
crates/c-api/include/wasmtime/error.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* \file wasmtime/error.h
|
||||
*
|
||||
* \brief Definition and accessors of #wasmtime_error_t
|
||||
*/
|
||||
|
||||
#ifndef WASMTIME_ERROR_H
|
||||
#define WASMTIME_ERROR_H
|
||||
|
||||
#include <wasm.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \typedef wasmtime_error_t
|
||||
* \brief Convenience alias for #wasmtime_error
|
||||
*
|
||||
* \struct wasmtime_error
|
||||
* \brief Errors generated by Wasmtime.
|
||||
* \headerfile wasmtime/error.h
|
||||
*
|
||||
* This opaque type represents an error that happened as part of one of the
|
||||
* functions below. Errors primarily have an error message associated with them
|
||||
* at this time, which you can acquire by calling #wasmtime_error_message.
|
||||
*
|
||||
* Errors are safe to share across threads and must be deleted with
|
||||
* #wasmtime_error_delete.
|
||||
*/
|
||||
typedef struct wasmtime_error wasmtime_error_t;
|
||||
|
||||
/**
|
||||
* \brief Deletes an error.
|
||||
*/
|
||||
WASM_API_EXTERN void wasmtime_error_delete(wasmtime_error_t *error);
|
||||
|
||||
/**
|
||||
* \brief Returns the string description of this error.
|
||||
*
|
||||
* This will "render" the error to a string and then return the string
|
||||
* representation of the error to the caller. The `message` argument should be
|
||||
* uninitialized before this function is called and the caller is responsible
|
||||
* for deallocating it with #wasm_byte_vec_delete afterwards.
|
||||
*/
|
||||
WASM_API_EXTERN void wasmtime_error_message(
|
||||
const wasmtime_error_t *error,
|
||||
wasm_name_t *message
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // WASMTIME_ERROR_H
|
||||
172
crates/c-api/include/wasmtime/extern.h
Normal file
172
crates/c-api/include/wasmtime/extern.h
Normal file
@@ -0,0 +1,172 @@
|
||||
/**
|
||||
* \file wasmtime/extern.h
|
||||
*
|
||||
* \brief Definition of #wasmtime_extern_t and external items.
|
||||
*/
|
||||
|
||||
#ifndef WASMTIME_EXTERN_H
|
||||
#define WASMTIME_EXTERN_H
|
||||
|
||||
#include <wasmtime/module.h>
|
||||
#include <wasmtime/store.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/// \brief Representation of a function in Wasmtime.
|
||||
///
|
||||
/// Functions are represented with a 64-bit identifying integer in Wasmtime.
|
||||
/// They do not have any destructor associated with them. Functions cannot
|
||||
/// interoperate between #wasmtime_store_t instances and if the wrong function
|
||||
/// is passed to the wrong store then it may trigger an assertion to abort the
|
||||
/// process.
|
||||
typedef struct wasmtime_func {
|
||||
/// Internal identifier of what store this belongs to, never zero.
|
||||
uint64_t store_id;
|
||||
/// Internal index within the store.
|
||||
size_t index;
|
||||
} wasmtime_func_t;
|
||||
|
||||
/// \brief Representation of a table in Wasmtime.
|
||||
///
|
||||
/// Tables are represented with a 64-bit identifying integer in Wasmtime.
|
||||
/// They do not have any destructor associated with them. Tables cannot
|
||||
/// interoperate between #wasmtime_store_t instances and if the wrong table
|
||||
/// is passed to the wrong store then it may trigger an assertion to abort the
|
||||
/// process.
|
||||
typedef struct wasmtime_table {
|
||||
/// Internal identifier of what store this belongs to, never zero.
|
||||
uint64_t store_id;
|
||||
/// Internal index within the store.
|
||||
size_t index;
|
||||
} wasmtime_table_t;
|
||||
|
||||
/// \brief Representation of a memory in Wasmtime.
|
||||
///
|
||||
/// Memories are represented with a 64-bit identifying integer in Wasmtime.
|
||||
/// They do not have any destructor associated with them. Memories cannot
|
||||
/// interoperate between #wasmtime_store_t instances and if the wrong memory
|
||||
/// is passed to the wrong store then it may trigger an assertion to abort the
|
||||
/// process.
|
||||
typedef struct wasmtime_memory {
|
||||
/// Internal identifier of what store this belongs to, never zero.
|
||||
uint64_t store_id;
|
||||
/// Internal index within the store.
|
||||
size_t index;
|
||||
} wasmtime_memory_t;
|
||||
|
||||
/// \brief Representation of a instance in Wasmtime.
|
||||
///
|
||||
/// Instances are represented with a 64-bit identifying integer in Wasmtime.
|
||||
/// They do not have any destructor associated with them. Instances cannot
|
||||
/// interoperate between #wasmtime_store_t instances and if the wrong instance
|
||||
/// is passed to the wrong store then it may trigger an assertion to abort the
|
||||
/// process.
|
||||
typedef struct wasmtime_instance {
|
||||
/// Internal identifier of what store this belongs to, never zero.
|
||||
uint64_t store_id;
|
||||
/// Internal index within the store.
|
||||
size_t index;
|
||||
} wasmtime_instance_t;
|
||||
|
||||
/// \brief Representation of a global in Wasmtime.
|
||||
///
|
||||
/// Globals are represented with a 64-bit identifying integer in Wasmtime.
|
||||
/// They do not have any destructor associated with them. Globals cannot
|
||||
/// interoperate between #wasmtime_store_t instances and if the wrong global
|
||||
/// is passed to the wrong store then it may trigger an assertion to abort the
|
||||
/// process.
|
||||
typedef struct wasmtime_global {
|
||||
/// Internal identifier of what store this belongs to, never zero.
|
||||
uint64_t store_id;
|
||||
/// Internal index within the store.
|
||||
size_t index;
|
||||
} wasmtime_global_t;
|
||||
|
||||
/// \brief Disciminant of #wasmtime_extern_t
|
||||
typedef uint8_t wasmtime_extern_kind_t;
|
||||
|
||||
/// \brief Value of #wasmtime_extern_kind_t meaning that #wasmtime_extern_t is a
|
||||
/// function
|
||||
#define WASMTIME_EXTERN_FUNC 0
|
||||
/// \brief Value of #wasmtime_extern_kind_t meaning that #wasmtime_extern_t is a
|
||||
/// global
|
||||
#define WASMTIME_EXTERN_GLOBAL 1
|
||||
/// \brief Value of #wasmtime_extern_kind_t meaning that #wasmtime_extern_t is a
|
||||
/// table
|
||||
#define WASMTIME_EXTERN_TABLE 2
|
||||
/// \brief Value of #wasmtime_extern_kind_t meaning that #wasmtime_extern_t is a
|
||||
/// memory
|
||||
#define WASMTIME_EXTERN_MEMORY 3
|
||||
/// \brief Value of #wasmtime_extern_kind_t meaning that #wasmtime_extern_t is
|
||||
/// an instance
|
||||
#define WASMTIME_EXTERN_INSTANCE 4
|
||||
/// \brief Value of #wasmtime_extern_kind_t meaning that #wasmtime_extern_t is
|
||||
/// a module
|
||||
#define WASMTIME_EXTERN_MODULE 5
|
||||
|
||||
/**
|
||||
* \typedef wasmtime_extern_union_t
|
||||
* \brief Convenience alias for #wasmtime_extern_union
|
||||
*
|
||||
* \union wasmtime_extern_union
|
||||
* \brief Container for different kinds of extern items.
|
||||
*
|
||||
* This type is contained in #wasmtime_extern_t and contains the payload for the
|
||||
* various kinds of items an extern wasm item can be.
|
||||
*/
|
||||
typedef union wasmtime_extern_union {
|
||||
/// Field used if #wasmtime_extern_t::kind is #WASMTIME_EXTERN_FUNC
|
||||
wasmtime_func_t func;
|
||||
/// Field used if #wasmtime_extern_t::kind is #WASMTIME_EXTERN_GLOBAL
|
||||
wasmtime_global_t global;
|
||||
/// Field used if #wasmtime_extern_t::kind is #WASMTIME_EXTERN_TABLE
|
||||
wasmtime_table_t table;
|
||||
/// Field used if #wasmtime_extern_t::kind is #WASMTIME_EXTERN_MEMORY
|
||||
wasmtime_memory_t memory;
|
||||
/// Field used if #wasmtime_extern_t::kind is #WASMTIME_EXTERN_INSTANCE
|
||||
wasmtime_instance_t instance;
|
||||
/// Field used if #wasmtime_extern_t::kind is #WASMTIME_EXTERN_MODULE
|
||||
///
|
||||
/// Note that this may be an owned pointer depending on the ownership of the
|
||||
/// #wasmtime_extern_t container value.
|
||||
wasmtime_module_t *module;
|
||||
} wasmtime_extern_union_t;
|
||||
|
||||
/**
|
||||
* \typedef wasmtime_extern_t
|
||||
* \brief Convenience alias for #wasmtime_extern_t
|
||||
*
|
||||
* \union wasmtime_extern
|
||||
* \brief Container for different kinds of extern items.
|
||||
*
|
||||
* Note that this structure may contain an owned value, namely
|
||||
* #wasmtime_module_t, depending on the context in which this is used. APIs
|
||||
* which consume a #wasmtime_extern_t do not take ownership, but APIs that
|
||||
* return #wasmtime_extern_t require that #wasmtime_extern_delete is called to
|
||||
* deallocate the value.
|
||||
*/
|
||||
typedef struct wasmtime_extern {
|
||||
/// Discriminant of which field of #of is valid.
|
||||
wasmtime_extern_kind_t kind;
|
||||
/// Container for the extern item's value.
|
||||
wasmtime_extern_union_t of;
|
||||
} wasmtime_extern_t;
|
||||
|
||||
/// \brief Deletes a #wasmtime_extern_t.
|
||||
void wasmtime_extern_delete(wasmtime_extern_t *val);
|
||||
|
||||
/// \brief Returns the type of the #wasmtime_extern_t defined within the given
|
||||
/// store.
|
||||
///
|
||||
/// Does not take ownership of `context` or `val`, but the returned
|
||||
/// #wasm_externtype_t is an owned value that needs to be deleted.
|
||||
wasm_externtype_t *wasmtime_extern_type(wasmtime_context_t *context, wasmtime_extern_t *val);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // WASMTIME_EXTERN_H
|
||||
|
||||
179
crates/c-api/include/wasmtime/func.h
Normal file
179
crates/c-api/include/wasmtime/func.h
Normal file
@@ -0,0 +1,179 @@
|
||||
/**
|
||||
* \file wasmtime/func.h
|
||||
*
|
||||
* Wasmtime definitions of how to interact with host and wasm functions.
|
||||
*/
|
||||
|
||||
#ifndef WASMTIME_FUNC_H
|
||||
#define WASMTIME_FUNC_H
|
||||
|
||||
#include <wasm.h>
|
||||
#include <wasmtime/val.h>
|
||||
#include <wasmtime/store.h>
|
||||
#include <wasmtime/extern.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \typedef wasmtime_caller_t
|
||||
* \brief Alias to #wasmtime_caller
|
||||
*
|
||||
* \brief Structure used to learn about the caller of a host-defined function.
|
||||
* \struct wasmtime_caller
|
||||
*
|
||||
* This structure is an argument to #wasmtime_func_callback_t. The purpose
|
||||
* of this structure is acquire a #wasmtime_context_t pointer to interact with
|
||||
* objects, but it can also be used for inspect the state of the caller (such as
|
||||
* getting memories and functions) with #wasmtime_caller_export_get.
|
||||
*
|
||||
* This object is never owned and does not need to be deleted.
|
||||
*/
|
||||
typedef struct wasmtime_caller wasmtime_caller_t;
|
||||
|
||||
/**
|
||||
* \brief Callback signature for #wasmtime_func_new.
|
||||
*
|
||||
* This is the function signature for host functions that can be made accessible
|
||||
* to WebAssembly. The arguments to this function are:
|
||||
*
|
||||
* \param env user-provided argument passed to #wasmtime_func_new
|
||||
* \param caller a temporary object that can only be used during this function
|
||||
* call. Used to acquire #wasmtime_context_t or caller's state
|
||||
* \param args the arguments provided to this function invocation
|
||||
* \param nargs how many arguments are provided
|
||||
* \param results where to write the results of this function
|
||||
* \param nresults how many results must be produced
|
||||
*
|
||||
* Callbacks are guaranteed to get called with the right types of arguments, but
|
||||
* they must produce the correct number and types of results. Failure to do so
|
||||
* will cause traps to get raised on the wasm side.
|
||||
*
|
||||
* This callback can optionally return a #wasm_trap_t indicating that a trap
|
||||
* should be raised in WebAssembly. It's expected that in this case the caller
|
||||
* relinquishes ownership of the trap and it is passed back to the engine.
|
||||
*/
|
||||
typedef wasm_trap_t* (*wasmtime_func_callback_t)(
|
||||
void *env,
|
||||
wasmtime_caller_t* caller,
|
||||
const wasmtime_val_t *args,
|
||||
size_t nargs,
|
||||
wasmtime_val_t *results,
|
||||
size_t nresults);
|
||||
|
||||
/**
|
||||
* \brief Creates a new host-defined function.
|
||||
*
|
||||
* Inserts a host-defined function into the `store` provided which can be used
|
||||
* to then instantiate a module with or define within a #wasmtime_linker_t.
|
||||
*
|
||||
* \param store the store in which to create the function
|
||||
* \param type the wasm type of the function that's being created
|
||||
* \param callback the host-defined callback to invoke
|
||||
* \param env host-specific data passed to the callback invocation, can be
|
||||
* `NULL`
|
||||
* \param finalizer optional finalizer for `env`, can be `NULL`
|
||||
* \param ret the #wasmtime_func_t return value to be filled in.
|
||||
*
|
||||
* The returned function can only be used with the specified `store`.
|
||||
*/
|
||||
WASM_API_EXTERN void wasmtime_func_new(
|
||||
wasmtime_context_t *store,
|
||||
const wasm_functype_t* type,
|
||||
wasmtime_func_callback_t callback,
|
||||
void *env,
|
||||
void (*finalizer)(void*),
|
||||
wasmtime_func_t *ret
|
||||
);
|
||||
|
||||
/**
|
||||
* \brief Returns the type of the function specified
|
||||
*
|
||||
* The returned #wasm_functype_t is owned by the caller.
|
||||
*/
|
||||
WASM_API_EXTERN wasm_functype_t* wasmtime_func_type(
|
||||
const wasmtime_context_t *store,
|
||||
const wasmtime_func_t *func
|
||||
);
|
||||
|
||||
/**
|
||||
* \brief Call a WebAssembly function.
|
||||
*
|
||||
* This function is used to invoke a function defined within a store. For
|
||||
* example this might be used after extracting a function from a
|
||||
* #wasmtime_instance_t.
|
||||
*
|
||||
* \param store the store which owns `func`
|
||||
* \param func the function to call
|
||||
* \param args the arguments to the function call
|
||||
* \param nargs the number of arguments provided
|
||||
* \param results where to write the results of the function call
|
||||
* \param nresults the number of results expected
|
||||
* \param trap where to store a trap, if one happens.
|
||||
*
|
||||
* There are three possible return states from this function:
|
||||
*
|
||||
* 1. The returned error is non-null. This means `results`
|
||||
* wasn't written to and `trap` will have `NULL` written to it. This state
|
||||
* means that programmer error happened when calling the function, for
|
||||
* example when the size of the arguments/results was wrong, the types of the
|
||||
* arguments were wrong, or arguments may come from the wrong store.
|
||||
* 2. The trap pointer is filled in. This means the returned error is `NULL` and
|
||||
* `results` was not written to. This state means that the function was
|
||||
* executing but hit a wasm trap while executing.
|
||||
* 3. The error and trap returned are both `NULL` and `results` are written to.
|
||||
* This means that the function call succeeded and the specified results were
|
||||
* produced.
|
||||
*
|
||||
* The `trap` pointer cannot be `NULL`. The `args` and `results` pointers may be
|
||||
* `NULL` if the corresponding length is zero.
|
||||
*
|
||||
* Does not take ownership of #wasmtime_val_t arguments. Gives ownership of
|
||||
* #wasmtime_val_t results.
|
||||
*/
|
||||
WASM_API_EXTERN wasmtime_error_t *wasmtime_func_call(
|
||||
wasmtime_context_t *store,
|
||||
const wasmtime_func_t *func,
|
||||
const wasmtime_val_t *args,
|
||||
size_t nargs,
|
||||
wasmtime_val_t *results,
|
||||
size_t nresults,
|
||||
wasm_trap_t **trap
|
||||
);
|
||||
|
||||
/**
|
||||
* \brief Loads a #wasmtime_extern_t from the caller's context
|
||||
*
|
||||
* This function will attempt to look up the export named `name` on the caller
|
||||
* instance provided. If it is found then the #wasmtime_extern_t for that is
|
||||
* returned, otherwise `NULL` is returned.
|
||||
*
|
||||
* Note that this only works for exported memories right now for WASI
|
||||
* compatibility.
|
||||
*
|
||||
* \param caller the caller object to look up the export from
|
||||
* \param name the name that's being looked up
|
||||
* \param name_len the byte length of `name`
|
||||
* \param item where to store the return value
|
||||
*
|
||||
* Returns a nonzero value if the export was found, or 0 if the export wasn't
|
||||
* found. If the export wasn't found then `item` isn't written to.
|
||||
*/
|
||||
WASM_API_EXTERN bool wasmtime_caller_export_get(
|
||||
wasmtime_caller_t *caller,
|
||||
const char *name,
|
||||
size_t name_len,
|
||||
wasmtime_extern_t *item
|
||||
);
|
||||
|
||||
/**
|
||||
* \brief Returns the store context of the caller object.
|
||||
*/
|
||||
WASM_API_EXTERN wasmtime_context_t* wasmtime_caller_context(wasmtime_caller_t* caller);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // WASMTIME_FUNC_H
|
||||
91
crates/c-api/include/wasmtime/global.h
Normal file
91
crates/c-api/include/wasmtime/global.h
Normal file
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
* \file wasmtime/global.h
|
||||
*
|
||||
* Wasmtime APIs for interacting with WebAssembly globals.
|
||||
*/
|
||||
|
||||
#ifndef WASMTIME_GLOBAL_H
|
||||
#define WASMTIME_GLOBAL_H
|
||||
|
||||
#include <wasm.h>
|
||||
#include <wasmtime/extern.h>
|
||||
#include <wasmtime/store.h>
|
||||
#include <wasmtime/val.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Creates a new global value.
|
||||
*
|
||||
* Creates a new host-defined global value within the provided `store`
|
||||
*
|
||||
* \param store the store in which to create the global
|
||||
* \param type the wasm type of the global being created
|
||||
* \param val the initial value of the global
|
||||
* \param ret a return pointer for the created global.
|
||||
*
|
||||
* This function may return an error if the `val` argument does not match the
|
||||
* specified type of the global, or if `val` comes from a different store than
|
||||
* the one provided.
|
||||
*
|
||||
* This function does not take ownership of any of its arguments but error is
|
||||
* owned by the caller.
|
||||
*/
|
||||
WASM_API_EXTERN wasmtime_error_t *wasmtime_global_new(
|
||||
wasmtime_context_t *store,
|
||||
const wasm_globaltype_t *type,
|
||||
const wasmtime_val_t *val,
|
||||
wasmtime_global_t *ret
|
||||
);
|
||||
|
||||
/**
|
||||
* \brief Returns the wasm type of the specified global.
|
||||
*
|
||||
* The returned #wasm_globaltype_t is owned by the caller.
|
||||
*/
|
||||
WASM_API_EXTERN wasm_globaltype_t* wasmtime_global_type(
|
||||
const wasmtime_context_t *store,
|
||||
const wasmtime_global_t *global
|
||||
);
|
||||
|
||||
/**
|
||||
* \brief Get the value of the specified global.
|
||||
*
|
||||
* \param store the store that owns `global`
|
||||
* \param global the global to get
|
||||
* \param out where to store the value in this global.
|
||||
*
|
||||
* This function returns ownership of the contents of `out`, so
|
||||
* #wasmtime_val_delete may need to be called on the value.
|
||||
*/
|
||||
WASM_API_EXTERN void wasmtime_global_get(
|
||||
wasmtime_context_t *store,
|
||||
const wasmtime_global_t *global,
|
||||
wasmtime_val_t *out
|
||||
);
|
||||
|
||||
/**
|
||||
* \brief Sets a global to a new value.
|
||||
*
|
||||
* \param store the store that owns `global`
|
||||
* \param global the global to set
|
||||
* \param val the value to store in the global
|
||||
*
|
||||
* This function may return an error if `global` is not mutable or if `val` has
|
||||
* the wrong type for `global`.
|
||||
*
|
||||
* THis does not take ownership of any argument but returns ownership of the error.
|
||||
*/
|
||||
WASM_API_EXTERN wasmtime_error_t *wasmtime_global_set(
|
||||
wasmtime_context_t *store,
|
||||
const wasmtime_global_t *global,
|
||||
const wasmtime_val_t *val
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // WASMTIME_GLOBAL_H
|
||||
158
crates/c-api/include/wasmtime/instance.h
Normal file
158
crates/c-api/include/wasmtime/instance.h
Normal file
@@ -0,0 +1,158 @@
|
||||
/**
|
||||
* \file wasmtime/instance.h
|
||||
*
|
||||
* Wasmtime APIs for interacting with wasm instances.
|
||||
*/
|
||||
|
||||
#ifndef WASMTIME_INSTANCE_H
|
||||
#define WASMTIME_INSTANCE_H
|
||||
|
||||
#include <wasm.h>
|
||||
#include <wasmtime/extern.h>
|
||||
#include <wasmtime/module.h>
|
||||
#include <wasmtime/store.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief An opaque object representing the type of an instance.
|
||||
*/
|
||||
typedef struct wasmtime_instancetype wasmtime_instancetype_t;
|
||||
|
||||
/// \brief Deletes an instance type
|
||||
WASM_API_EXTERN void wasmtime_instancetype_delete(wasmtime_instancetype_t *ty);
|
||||
|
||||
/**
|
||||
* \brief Returns the list of exports that this instance type provides.
|
||||
*
|
||||
* This function does not take ownership of the provided instance type but
|
||||
* ownership of `out` is passed to the caller. Note that `out` is treated as
|
||||
* uninitialized when passed to this function.
|
||||
*/
|
||||
WASM_API_EXTERN void wasmtime_instancetype_exports(const wasmtime_instancetype_t*, wasm_exporttype_vec_t* out);
|
||||
|
||||
/**
|
||||
* \brief Converts a #wasmtime_instancetype_t to a #wasm_externtype_t
|
||||
*
|
||||
* The returned value is owned by the #wasmtime_instancetype_t argument and should not
|
||||
* be deleted.
|
||||
*/
|
||||
WASM_API_EXTERN wasm_externtype_t* wasmtime_instancetype_as_externtype(wasmtime_instancetype_t*);
|
||||
|
||||
/**
|
||||
* \brief Attempts to convert a #wasm_externtype_t to a #wasmtime_instancetype_t
|
||||
*
|
||||
* The returned value is owned by the #wasmtime_instancetype_t argument and should not
|
||||
* be deleted. Returns `NULL` if the provided argument is not a
|
||||
* #wasmtime_instancetype_t.
|
||||
*/
|
||||
WASM_API_EXTERN wasmtime_instancetype_t* wasmtime_externtype_as_instancetype(wasm_externtype_t*);
|
||||
|
||||
/**
|
||||
* \brief Instantiate a wasm module.
|
||||
*
|
||||
* This function will instantiate a WebAssembly module with the provided
|
||||
* imports, creating a WebAssembly instance. The returned instance can then
|
||||
* afterwards be inspected for exports.
|
||||
*
|
||||
* \param store the store in which to create the instance
|
||||
* \param module the module that's being instantiated
|
||||
* \param imports the imports provided to the module
|
||||
* \param nimports the size of `imports`
|
||||
* \param instance where to store the returned instance
|
||||
* \param trap where to store the returned trap
|
||||
*
|
||||
* This function requires that `imports` is the same size as the imports that
|
||||
* `module` has. Additionally the `imports` array must be 1:1 lined up with the
|
||||
* imports of the `module` specified. This is intended to be relatively low
|
||||
* level, and #wasmtime_linker_instantiate is provided for a more ergonomic
|
||||
* name-based resolution API.
|
||||
*
|
||||
* The states of return values from this function are similar to
|
||||
* #wasmtime_func_call where an error can be returned meaning something like a
|
||||
* link error in this context. A trap can be returned (meaning no error or
|
||||
* instance is returned), or an instance can be returned (meaning no error or
|
||||
* trap is returned).
|
||||
*
|
||||
* Note that this function requires that all `imports` specified must be owned
|
||||
* by the `store` provided as well.
|
||||
*
|
||||
* This function does not take ownership of any of its arguments, but all return
|
||||
* values are owned by the caller.
|
||||
*/
|
||||
WASM_API_EXTERN wasmtime_error_t *wasmtime_instance_new(
|
||||
wasmtime_context_t *store,
|
||||
const wasmtime_module_t *module,
|
||||
const wasmtime_extern_t* imports,
|
||||
size_t nimports,
|
||||
wasmtime_instance_t *instance,
|
||||
wasm_trap_t **trap
|
||||
);
|
||||
|
||||
/**
|
||||
* \brief Returns the type of the specified instance.
|
||||
*
|
||||
* The returned type is owned by the caller.
|
||||
*/
|
||||
WASM_API_EXTERN wasmtime_instancetype_t *wasmtime_instance_type(
|
||||
const wasmtime_context_t *store,
|
||||
const wasmtime_instance_t *instance
|
||||
);
|
||||
|
||||
/**
|
||||
* \brief Get an export by name from an instance.
|
||||
*
|
||||
* \param store the store that owns `instance`
|
||||
* \param instance the instance to lookup within
|
||||
* \param name the export name to lookup
|
||||
* \param name_len the byte length of `name`
|
||||
* \param item where to store the returned value
|
||||
*
|
||||
* Returns nonzero if the export was found, and `item` is filled in. Otherwise
|
||||
* returns 0.
|
||||
*
|
||||
* Doesn't take ownership of any arguments but does return ownership of the
|
||||
* #wasmtime_extern_t.
|
||||
*/
|
||||
WASM_API_EXTERN bool wasmtime_instance_export_get(
|
||||
wasmtime_context_t *store,
|
||||
const wasmtime_instance_t *instance,
|
||||
const char *name,
|
||||
size_t name_len,
|
||||
wasmtime_extern_t *item
|
||||
);
|
||||
|
||||
/**
|
||||
* \brief Get an export by index from an instance.
|
||||
*
|
||||
* \param store the store that owns `instance`
|
||||
* \param instance the instance to lookup within
|
||||
* \param index the index to lookup
|
||||
* \param name where to store the name of the export
|
||||
* \param name_len where to store the byte length of the name
|
||||
* \param item where to store the export itself
|
||||
*
|
||||
* Returns nonzero if the export was found, and `name`, `name_len`, and `item`
|
||||
* are filled in. Otherwise returns 0.
|
||||
*
|
||||
* Doesn't take ownership of any arguments but does return ownership of the
|
||||
* #wasmtime_extern_t. The `name` pointer return value is owned by the `store`
|
||||
* and must be immediately used before calling any other APIs on
|
||||
* #wasmtime_context_t.
|
||||
*/
|
||||
WASM_API_EXTERN bool wasmtime_instance_export_nth(
|
||||
wasmtime_context_t *store,
|
||||
const wasmtime_instance_t *instance,
|
||||
size_t index,
|
||||
char **name,
|
||||
size_t *name_len,
|
||||
wasmtime_extern_t *item
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // WASMTIME_INSTANCE_H
|
||||
239
crates/c-api/include/wasmtime/linker.h
Normal file
239
crates/c-api/include/wasmtime/linker.h
Normal file
@@ -0,0 +1,239 @@
|
||||
/**
|
||||
* \file wasmtime/linker.h
|
||||
*
|
||||
* Wasmtime API for a name-based linker used to instantiate modules.
|
||||
*/
|
||||
|
||||
#ifndef WASMTIME_LINKER_H
|
||||
#define WASMTIME_LINKER_H
|
||||
|
||||
#include <wasm.h>
|
||||
#include <wasmtime/error.h>
|
||||
#include <wasmtime/store.h>
|
||||
#include <wasmtime/extern.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \typedef wasmtime_linker_t
|
||||
* \brief Alias to #wasmtime_linker
|
||||
*
|
||||
* \struct #wasmtime_linker
|
||||
* \brief Object used to conveniently link together and instantiate wasm
|
||||
* modules.
|
||||
*
|
||||
* This type corresponds to the `wasmtime::Linker` type in Rust. This
|
||||
* type is intended to make it easier to manage a set of modules that link
|
||||
* together, or to make it easier to link WebAssembly modules to WASI.
|
||||
*
|
||||
* A #wasmtime_linker_t is a higher level way to instantiate a module than
|
||||
* #wasm_instance_new since it works at the "string" level of imports rather
|
||||
* than requiring 1:1 mappings.
|
||||
*/
|
||||
typedef struct wasmtime_linker wasmtime_linker_t;
|
||||
|
||||
/**
|
||||
* \brief Creates a new linker for the specified engine.
|
||||
*
|
||||
* This function does not take ownership of the engine argument, and the caller
|
||||
* is expected to delete the returned linker.
|
||||
*/
|
||||
WASM_API_EXTERN wasmtime_linker_t* wasmtime_linker_new(wasm_engine_t* engine);
|
||||
|
||||
/**
|
||||
* \brief Deletes a linker
|
||||
*/
|
||||
WASM_API_EXTERN void wasmtime_linker_delete(wasmtime_linker_t* linker);
|
||||
|
||||
/**
|
||||
* \brief Configures whether this linker allows later definitions to shadow
|
||||
* previous definitions.
|
||||
*
|
||||
* By default this setting is `false`.
|
||||
*/
|
||||
WASM_API_EXTERN void wasmtime_linker_allow_shadowing(wasmtime_linker_t* linker, bool allow_shadowing);
|
||||
|
||||
/**
|
||||
* \brief Defines a new item in this linker.
|
||||
*
|
||||
* \param linker the linker the name is being defined in.
|
||||
* \param module the module name the item is defined under.
|
||||
* \param module_len the byte length of `module`
|
||||
* \param name the field name the item is defined under
|
||||
* \param name_len the byte length of `name`
|
||||
* \param item the item that is being defined in this linker.
|
||||
*
|
||||
* \return On success `NULL` is returned, otherwise an error is returned which
|
||||
* describes why the definition failed.
|
||||
*
|
||||
* For more information about name resolution consult the [Rust
|
||||
* documentation](https://bytecodealliance.github.io/wasmtime/api/wasmtime/struct.Linker.html#name-resolution).
|
||||
*/
|
||||
WASM_API_EXTERN wasmtime_error_t* wasmtime_linker_define(
|
||||
wasmtime_linker_t *linker,
|
||||
const char *module,
|
||||
size_t module_len,
|
||||
const char *name,
|
||||
size_t name_len,
|
||||
const wasmtime_extern_t *item
|
||||
);
|
||||
|
||||
/**
|
||||
* \brief Defines WASI functions in this linker.
|
||||
*
|
||||
* \param linker the linker the name is being defined in.
|
||||
*
|
||||
* \return On success `NULL` is returned, otherwise an error is returned which
|
||||
* describes why the definition failed.
|
||||
*
|
||||
* This function will provide WASI function names in the specified linker. Note
|
||||
* that when an instance is created within a store then the store also needs to
|
||||
* have its WASI settings configured with #wasmtime_context_set_wasi for WASI
|
||||
* functions to work, otherwise an assert will be tripped that will abort the
|
||||
* process.
|
||||
*
|
||||
* For more information about name resolution consult the [Rust
|
||||
* documentation](https://bytecodealliance.github.io/wasmtime/api/wasmtime/struct.Linker.html#name-resolution).
|
||||
*/
|
||||
WASM_API_EXTERN wasmtime_error_t* wasmtime_linker_define_wasi(
|
||||
wasmtime_linker_t *linker
|
||||
);
|
||||
|
||||
/**
|
||||
* \brief Defines an instance under the specified name in this linker.
|
||||
*
|
||||
* \param linker the linker the name is being defined in.
|
||||
* \param store the store that owns `instance`
|
||||
* \param name the module name to define `instance` under.
|
||||
* \param name_len the byte length of `name`
|
||||
* \param instance a previously-created instance.
|
||||
*
|
||||
* \return On success `NULL` is returned, otherwise an error is returned which
|
||||
* describes why the definition failed.
|
||||
*
|
||||
* This function will take all of the exports of the `instance` provided and
|
||||
* defined them under a module called `name` with a field name as the export's
|
||||
* own name.
|
||||
*
|
||||
* For more information about name resolution consult the [Rust
|
||||
* documentation](https://bytecodealliance.github.io/wasmtime/api/wasmtime/struct.Linker.html#name-resolution).
|
||||
*/
|
||||
WASM_API_EXTERN wasmtime_error_t* wasmtime_linker_define_instance(
|
||||
wasmtime_linker_t *linker,
|
||||
wasmtime_context_t *store,
|
||||
const char *name,
|
||||
size_t name_len,
|
||||
const wasmtime_instance_t *instance
|
||||
);
|
||||
|
||||
/**
|
||||
* \brief Instantiates a #wasm_module_t with the items defined in this linker.
|
||||
*
|
||||
* \param linker the linker used to instantiate the provided module.
|
||||
* \param store the store that is used to instantiate within
|
||||
* \param module the module that is being instantiated.
|
||||
* \param instance the returned instance, if successful.
|
||||
* \param trap a trap returned, if the start function traps.
|
||||
*
|
||||
* \return One of three things can happen as a result of this function. First
|
||||
* the module could be successfully instantiated and returned through
|
||||
* `instance`, meaning the return value and `trap` are both set to `NULL`.
|
||||
* Second the start function may trap, meaning the return value and `instance`
|
||||
* are set to `NULL` and `trap` describes the trap that happens. Finally
|
||||
* instantiation may fail for another reason, in which case an error is returned
|
||||
* and `trap` and `instance` are set to `NULL`.
|
||||
*
|
||||
* This function will attempt to satisfy all of the imports of the `module`
|
||||
* provided with items previously defined in this linker. If any name isn't
|
||||
* defined in the linker than an error is returned. (or if the previously
|
||||
* defined item is of the wrong type).
|
||||
*/
|
||||
WASM_API_EXTERN wasmtime_error_t* wasmtime_linker_instantiate(
|
||||
const wasmtime_linker_t *linker,
|
||||
wasmtime_context_t *store,
|
||||
const wasmtime_module_t *module,
|
||||
wasmtime_instance_t *instance,
|
||||
wasm_trap_t **trap
|
||||
);
|
||||
|
||||
/**
|
||||
* \brief Defines automatic instantiations of a #wasm_module_t in this linker.
|
||||
*
|
||||
* \param linker the linker the module is being added to
|
||||
* \param store the store that is used to instantiate `module`
|
||||
* \param name the name of the module within the linker
|
||||
* \param name_len the byte length of `name`
|
||||
* \param module the module that's being instantiated
|
||||
*
|
||||
* \return An error if the module could not be instantiated or added or `NULL`
|
||||
* on success.
|
||||
*
|
||||
* This function automatically handles [Commands and
|
||||
* Reactors](https://github.com/WebAssembly/WASI/blob/master/design/application-abi.md#current-unstable-abi)
|
||||
* instantiation and initialization.
|
||||
*
|
||||
* For more information see the [Rust
|
||||
* documentation](https://bytecodealliance.github.io/wasmtime/api/wasmtime/struct.Linker.html#method.module).
|
||||
*/
|
||||
WASM_API_EXTERN wasmtime_error_t* wasmtime_linker_module(
|
||||
wasmtime_linker_t *linker,
|
||||
wasmtime_context_t *store,
|
||||
const char *name,
|
||||
size_t name_len,
|
||||
const wasmtime_module_t *module
|
||||
);
|
||||
|
||||
/**
|
||||
* \brief Acquires the "default export" of the named module in this linker.
|
||||
*
|
||||
* \param linker the linker to load from
|
||||
* \param store the store to load a function into
|
||||
* \param name the name of the module to get the default export for
|
||||
* \param name_len the byte length of `name`
|
||||
* \param func where to store the extracted default function.
|
||||
*
|
||||
* \return An error is returned if the default export could not be found, or
|
||||
* `NULL` is returned and `func` is filled in otherwise.
|
||||
*
|
||||
* For more information see the [Rust
|
||||
* documentation](https://bytecodealliance.github.io/wasmtime/api/wasmtime/struct.Linker.html#method.get_default).
|
||||
*/
|
||||
WASM_API_EXTERN wasmtime_error_t* wasmtime_linker_get_default(
|
||||
const wasmtime_linker_t *linker,
|
||||
wasmtime_context_t *store,
|
||||
const char *name,
|
||||
size_t name_len,
|
||||
wasmtime_func_t *func
|
||||
);
|
||||
|
||||
/**
|
||||
* \brief Loads an item by name from this linker.
|
||||
*
|
||||
* \param linker the linker to load from
|
||||
* \param store the store to load the item into
|
||||
* \param module the name of the module to get
|
||||
* \param module_len the byte length of `module`
|
||||
* \param name the name of the field to get
|
||||
* \param name_len the byte length of `name`
|
||||
* \param item where to store the extracted item
|
||||
*
|
||||
* \return A nonzero value if the item is defined, in which case `item` is also
|
||||
* filled in. Otherwise zero is returned.
|
||||
*/
|
||||
WASM_API_EXTERN bool wasmtime_linker_get(
|
||||
const wasmtime_linker_t *linker,
|
||||
wasmtime_context_t *store,
|
||||
const char *module,
|
||||
size_t module_len,
|
||||
const char *name,
|
||||
size_t name_len,
|
||||
wasmtime_extern_t *item
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // WASMTIME_LINKER_H
|
||||
90
crates/c-api/include/wasmtime/memory.h
Normal file
90
crates/c-api/include/wasmtime/memory.h
Normal file
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
* \file wasmtime/memory.h
|
||||
*
|
||||
* Wasmtime API for interacting with wasm memories.
|
||||
*/
|
||||
|
||||
#ifndef WASMTIME_MEMORY_H
|
||||
#define WASMTIME_MEMORY_H
|
||||
|
||||
#include <wasm.h>
|
||||
#include <wasmtime/extern.h>
|
||||
#include <wasmtime/store.h>
|
||||
#include <wasmtime/error.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Creates a new WebAssembly linear memory
|
||||
*
|
||||
* \param store the store to create the memory within
|
||||
* \param ty the type of the memory to create
|
||||
* \param ret where to store the returned memory
|
||||
*
|
||||
* If an error happens when creating the memory it's returned and owned by the
|
||||
* caller. If an error happens then `ret` is not filled in.
|
||||
*/
|
||||
WASM_API_EXTERN wasmtime_error_t *wasmtime_memory_new(
|
||||
wasmtime_context_t *store,
|
||||
const wasm_memorytype_t* ty,
|
||||
wasmtime_memory_t *ret
|
||||
);
|
||||
|
||||
/**
|
||||
* \brief Returns the tyep of the memory specified
|
||||
*/
|
||||
WASM_API_EXTERN wasm_memorytype_t* wasmtime_memory_type(
|
||||
const wasmtime_context_t *store,
|
||||
const wasmtime_memory_t *memory
|
||||
);
|
||||
|
||||
/**
|
||||
* \brief Returns the base pointer in memory where the linear memory starts.
|
||||
*/
|
||||
WASM_API_EXTERN uint8_t *wasmtime_memory_data(
|
||||
const wasmtime_context_t *store,
|
||||
const wasmtime_memory_t *memory
|
||||
);
|
||||
|
||||
/**
|
||||
* \brief Returns the byte length of this linear memory.
|
||||
*/
|
||||
WASM_API_EXTERN size_t wasmtime_memory_data_size(
|
||||
const wasmtime_context_t *store,
|
||||
const wasmtime_memory_t *memory
|
||||
);
|
||||
|
||||
/**
|
||||
* \brief Returns the length, in WebAssembly pages, of this linear memory
|
||||
*/
|
||||
WASM_API_EXTERN uint32_t wasmtime_memory_size(
|
||||
const wasmtime_context_t *store,
|
||||
const wasmtime_memory_t *memory
|
||||
);
|
||||
|
||||
/**
|
||||
* \brief Attempts to grow the specified memory by `delta` pages.
|
||||
*
|
||||
* \param store the store that owns `memory`
|
||||
* \param memory the memory to grow
|
||||
* \param delta the number of pages to grow by
|
||||
* \param prev_size where to store the previous size of memory
|
||||
*
|
||||
* If memory cannot be grown then `prev_size` is left unchanged and an error is
|
||||
* returned. Otherwise `prev_size` is set to the previous size of the memory, in
|
||||
* WebAssembly pages, and `NULL` is returned.
|
||||
*/
|
||||
WASM_API_EXTERN wasmtime_error_t *wasmtime_memory_grow(
|
||||
wasmtime_context_t *store,
|
||||
const wasmtime_memory_t *memory,
|
||||
uint32_t delta,
|
||||
uint32_t *prev_size
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // WASMTIME_MEMORY_H
|
||||
172
crates/c-api/include/wasmtime/module.h
Normal file
172
crates/c-api/include/wasmtime/module.h
Normal file
@@ -0,0 +1,172 @@
|
||||
/**
|
||||
* \file wasmtime/module.h
|
||||
*
|
||||
* APIs for interacting with modules in Wasmtime
|
||||
*/
|
||||
|
||||
#ifndef WASMTIME_MODULE_H
|
||||
#define WASMTIME_MODULE_H
|
||||
|
||||
#include <wasm.h>
|
||||
#include <wasmtime/error.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief An opaque object representing the type of a module.
|
||||
*/
|
||||
typedef struct wasmtime_moduletype wasmtime_moduletype_t;
|
||||
|
||||
/**
|
||||
* \brief Deletes a module type.
|
||||
*/
|
||||
WASM_API_EXTERN void wasmtime_moduletype_delete(wasmtime_moduletype_t *ty);
|
||||
|
||||
/**
|
||||
* \brief Returns the list of imports that this module type requires.
|
||||
*
|
||||
* This function does not take ownership of the provided module type but
|
||||
* ownership of `out` is passed to the caller. Note that `out` is treated as
|
||||
* uninitialized when passed to this function.
|
||||
*/
|
||||
WASM_API_EXTERN void wasmtime_moduletype_imports(const wasmtime_moduletype_t*, wasm_importtype_vec_t* out);
|
||||
|
||||
/**
|
||||
* \brief Returns the list of exports that this module type provides.
|
||||
*
|
||||
* This function does not take ownership of the provided module type but
|
||||
* ownership of `out` is passed to the caller. Note that `out` is treated as
|
||||
* uninitialized when passed to this function.
|
||||
*/
|
||||
WASM_API_EXTERN void wasmtime_moduletype_exports(const wasmtime_moduletype_t*, wasm_exporttype_vec_t* out);
|
||||
|
||||
/**
|
||||
* \brief Converts a #wasmtime_moduletype_t to a #wasm_externtype_t
|
||||
*
|
||||
* The returned value is owned by the #wasmtime_moduletype_t argument and should not
|
||||
* be deleted.
|
||||
*/
|
||||
WASM_API_EXTERN wasm_externtype_t* wasmtime_moduletype_as_externtype(wasmtime_moduletype_t*);
|
||||
|
||||
/**
|
||||
* \brief Attempts to convert a #wasm_externtype_t to a #wasmtime_moduletype_t
|
||||
*
|
||||
* The returned value is owned by the #wasmtime_moduletype_t argument and
|
||||
* should not be deleted. Returns `NULL` if the provided argument is not a
|
||||
* #wasmtime_moduletype_t.
|
||||
*/
|
||||
WASM_API_EXTERN wasmtime_moduletype_t* wasmtime_externtype_as_moduletype(wasm_externtype_t*);
|
||||
|
||||
/**
|
||||
* \typedef wasmtime_module_t
|
||||
* \brief Convenience alias for #wasmtime_module
|
||||
*
|
||||
* \struct wasmtime_module
|
||||
* \brief A compiled Wasmtime module.
|
||||
*
|
||||
* This type represents a compiled WebAssembly module. The compiled module is
|
||||
* ready to be instantiated and can be inspected for imports/exports. It is safe
|
||||
* to use a module across multiple threads simultaneously.
|
||||
*/
|
||||
typedef struct wasmtime_module wasmtime_module_t;
|
||||
|
||||
/**
|
||||
* \brief Compiles a WebAssembly binary into a #wasmtime_module_t
|
||||
*
|
||||
* This function will compile a WebAssembly binary into an owned #wasm_module_t.
|
||||
* This performs the same as #wasm_module_new except that it returns a
|
||||
* #wasmtime_error_t type to get richer error information.
|
||||
*
|
||||
* On success the returned #wasmtime_error_t is `NULL` and the `ret` pointer is
|
||||
* filled in with a #wasm_module_t. On failure the #wasmtime_error_t is
|
||||
* non-`NULL` and the `ret` pointer is unmodified.
|
||||
*
|
||||
* This function does not take ownership of any of its arguments, but the
|
||||
* returned error and module are owned by the caller.
|
||||
*/
|
||||
WASM_API_EXTERN wasmtime_error_t *wasmtime_module_new(
|
||||
wasm_engine_t *engine,
|
||||
const uint8_t *wasm,
|
||||
size_t wasm_len,
|
||||
wasmtime_module_t **ret
|
||||
);
|
||||
|
||||
/**
|
||||
* \brief Deletes a module.
|
||||
*/
|
||||
WASM_API_EXTERN void wasmtime_module_delete(wasmtime_module_t *m);
|
||||
|
||||
/**
|
||||
* \brief Creates a shallow clone of the specified module, increasing the
|
||||
* internal reference count.
|
||||
*/
|
||||
WASM_API_EXTERN wasmtime_module_t *wasmtime_module_clone(wasmtime_module_t *m);
|
||||
|
||||
/**
|
||||
* \brief Validate a WebAssembly binary.
|
||||
*
|
||||
* This function will validate the provided byte sequence to determine if it is
|
||||
* a valid WebAssembly binary within the context of the engine provided.
|
||||
*
|
||||
* This function does not take ownership of its arguments but the caller is
|
||||
* expected to deallocate the returned error if it is non-`NULL`.
|
||||
*
|
||||
* If the binary validates then `NULL` is returned, otherwise the error returned
|
||||
* describes why the binary did not validate.
|
||||
*/
|
||||
WASM_API_EXTERN wasmtime_error_t *wasmtime_module_validate(
|
||||
wasm_engine_t *engine,
|
||||
const uint8_t *wasm,
|
||||
size_t wasm_len
|
||||
);
|
||||
|
||||
/**
|
||||
* \brief Returns the type of this module.
|
||||
*
|
||||
* The returned #wasmtime_moduletype_t is expected to be deallocated by the
|
||||
* caller.
|
||||
*/
|
||||
WASM_API_EXTERN wasmtime_moduletype_t* wasmtime_module_type(const wasmtime_module_t*);
|
||||
|
||||
/**
|
||||
* \brief This function serializes compiled module artifacts as blob data.
|
||||
*
|
||||
* \param module the module
|
||||
* \param ret if the conversion is successful, this byte vector is filled in with
|
||||
* the serialized compiled module.
|
||||
*
|
||||
* \return a non-null error if parsing fails, or returns `NULL`. If parsing
|
||||
* fails then `ret` isn't touched.
|
||||
*
|
||||
* This function does not take ownership of `module`, and the caller is
|
||||
* expected to deallocate the returned #wasmtime_error_t and #wasm_byte_vec_t.
|
||||
*/
|
||||
WASM_API_EXTERN wasmtime_error_t* wasmtime_module_serialize(
|
||||
wasmtime_module_t* module,
|
||||
wasm_byte_vec_t *ret
|
||||
);
|
||||
|
||||
/**
|
||||
* \brief Build a module from serialized data.
|
||||
*
|
||||
* This function does not take ownership of any of its arguments, but the
|
||||
* returned error and module are owned by the caller.
|
||||
*
|
||||
* This function is not safe to receive arbitrary user input. See the Rust
|
||||
* documentation for more information on what inputs are safe to pass in here
|
||||
* (e.g. only that of #wasmtime_module_serialize)
|
||||
*/
|
||||
WASM_API_EXTERN wasmtime_error_t *wasmtime_module_deserialize(
|
||||
wasm_engine_t *engine,
|
||||
const uint8_t *bytes,
|
||||
size_t bytes_len,
|
||||
wasmtime_module_t **ret
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // WASMTIME_MODULE_H
|
||||
203
crates/c-api/include/wasmtime/store.h
Normal file
203
crates/c-api/include/wasmtime/store.h
Normal file
@@ -0,0 +1,203 @@
|
||||
/**
|
||||
* \file wasmtime/store.h
|
||||
*
|
||||
* Wasmtime definition of a "store".
|
||||
*/
|
||||
|
||||
#ifndef WASMTIME_STORE_H
|
||||
#define WASMTIME_STORE_H
|
||||
|
||||
#include <wasm.h>
|
||||
#include <wasi.h>
|
||||
#include <wasmtime/error.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \typedef wasmtime_store_t
|
||||
* \brief Convenience alias for #wasmtime_store_t
|
||||
*
|
||||
* \struct wasmtime_store
|
||||
* \brief Storage of WebAssembly objects
|
||||
*
|
||||
* A store is the unit of isolation between WebAssembly instances in an
|
||||
* embedding of Wasmtime. Values in one #wasmtime_store_t cannot flow into
|
||||
* another #wasmtime_store_t. Stores are cheap to create and cheap to dispose.
|
||||
* It's expected that one-off stores are common in embeddings.
|
||||
*
|
||||
* Objects stored within a #wasmtime_store_t are referenced with integer handles
|
||||
* rather than interior pointers. This means that most APIs require that the
|
||||
* store be explicitly passed in, which is done via #wasmtime_context_t. It is
|
||||
* safe to move a #wasmtime_store_t to any thread at any time. A store generally
|
||||
* cannot be concurrently used, however.
|
||||
*/
|
||||
typedef struct wasmtime_store wasmtime_store_t;
|
||||
|
||||
/**
|
||||
* \typedef wasmtime_context_t
|
||||
* \brief Convenience alias for #wasmtime_context
|
||||
*
|
||||
* \struct wasmtime_context
|
||||
* \brief An interior pointer into a #wasmtime_store_t which is used as
|
||||
* "context" for many functions.
|
||||
*
|
||||
* This context pointer is used pervasively throught Wasmtime's API. This can be
|
||||
* acquired from #wasmtime_store_context or #wasmtime_caller_context. The
|
||||
* context pointer for a store is the same for the entire lifetime of a store,
|
||||
* so it can safely be stored adjacent to a #wasmtime_store_t itself.
|
||||
*
|
||||
* Usage of a #wasmtime_context_t must not outlive the original
|
||||
* #wasmtime_store_t. Additionally #wasmtime_context_t can only be used in
|
||||
* situations where it has explicitly been granted access to doing so. For
|
||||
* example finalizers cannot use #wasmtime_context_t because they are not given
|
||||
* access to it.
|
||||
*/
|
||||
typedef struct wasmtime_context wasmtime_context_t;
|
||||
|
||||
/**
|
||||
* \brief Creates a new store within the specified engine.
|
||||
*
|
||||
* \param engine the compilation environment with configuration this store is
|
||||
* connected to
|
||||
* \param data user-provided data to store, can later be acquired with
|
||||
* #wasmtime_context_get_data.
|
||||
* \param finalizer an optional finalizer for `data`
|
||||
*
|
||||
* This function creates a fresh store with the provided configuration settings.
|
||||
* The returned store must be deleted with #wasmtime_store_delete.
|
||||
*/
|
||||
WASM_API_EXTERN wasmtime_store_t *wasmtime_store_new(
|
||||
wasm_engine_t *engine,
|
||||
void *data,
|
||||
void (*finalizer)(void*)
|
||||
);
|
||||
|
||||
/**
|
||||
* \brief Returns the interior #wasmtime_context_t pointer to this store
|
||||
*/
|
||||
WASM_API_EXTERN wasmtime_context_t *wasmtime_store_context(wasmtime_store_t *store);
|
||||
|
||||
/**
|
||||
* \brief Deletes a store.
|
||||
*/
|
||||
WASM_API_EXTERN void wasmtime_store_delete(wasmtime_store_t *store);
|
||||
|
||||
/**
|
||||
* \brief Returns the user-specified data associated with the specified store
|
||||
*/
|
||||
WASM_API_EXTERN void *wasmtime_context_get_data(const wasmtime_context_t* context);
|
||||
|
||||
/**
|
||||
* \brief Overwrites the user-specified data associated with this store.
|
||||
*
|
||||
* Note that this does not execute the original finalizer for the provided data,
|
||||
* and the original finalizer will be executed for the provided data when the
|
||||
* store is deleted.
|
||||
*/
|
||||
WASM_API_EXTERN void wasmtime_context_set_data(wasmtime_context_t* context, void *data);
|
||||
|
||||
/**
|
||||
* \brief Perform garbage collection within the given context.
|
||||
*
|
||||
* Garbage collects `externref`s that are used within this store. Any
|
||||
* `externref`s that are discovered to be unreachable by other code or objects
|
||||
* will have their finalizers run.
|
||||
*
|
||||
* The `context` argument must not be NULL.
|
||||
*/
|
||||
WASM_API_EXTERN void wasmtime_context_gc(wasmtime_context_t* context);
|
||||
|
||||
/**
|
||||
* \brief Adds fuel to this context's store for wasm to consume while executing.
|
||||
*
|
||||
* For this method to work fuel consumption must be enabled via
|
||||
* #wasmtime_config_consume_fuel_set. By default a store starts with 0 fuel
|
||||
* for wasm to execute with (meaning it will immediately trap).
|
||||
* This function must be called for the store to have
|
||||
* some fuel to allow WebAssembly to execute.
|
||||
*
|
||||
* Note that at this time when fuel is entirely consumed it will cause
|
||||
* wasm to trap. More usages of fuel are planned for the future.
|
||||
*
|
||||
* If fuel is not enabled within this store then an error is returned. If fuel
|
||||
* is successfully added then NULL is returned.
|
||||
*/
|
||||
WASM_API_EXTERN wasmtime_error_t *wasmtime_context_add_fuel(wasmtime_context_t *store, uint64_t fuel);
|
||||
|
||||
/**
|
||||
* \brief Returns the amount of fuel consumed by this context's store execution
|
||||
* so far.
|
||||
*
|
||||
* If fuel consumption is not enabled via #wasmtime_config_consume_fuel_set
|
||||
* then this function will return false. Otherwise true is returned and the
|
||||
* fuel parameter is filled in with fuel consuemd so far.
|
||||
*
|
||||
* Also note that fuel, if enabled, must be originally configured via
|
||||
* #wasmtime_context_add_fuel.
|
||||
*/
|
||||
WASM_API_EXTERN bool wasmtime_context_fuel_consumed(const wasmtime_context_t *context, uint64_t *fuel);
|
||||
|
||||
/**
|
||||
* \brief Configres WASI state within the specified store.
|
||||
*
|
||||
* This function is required if #wasmtime_linker_define_wasi is called. This
|
||||
* will configure the WASI state for instances defined within this store to the
|
||||
* configuration specified.
|
||||
*
|
||||
* This function does not take ownership of `context` but it does take ownership
|
||||
* of `wasi`. The caller should no longer use `wasi` after calling this function
|
||||
* (even if an error is returned).
|
||||
*/
|
||||
WASM_API_EXTERN wasmtime_error_t *wasmtime_context_set_wasi(wasmtime_context_t *context, wasi_config_t *wasi);
|
||||
|
||||
/**
|
||||
* \typedef wasmtime_interrupt_handle_t
|
||||
* \brief Convenience alias for #wasmtime_interrupt_handle_t
|
||||
*
|
||||
* \struct wasmtime_interrupt_handle_t
|
||||
* \brief A handle used to interrupt executing WebAssembly code.
|
||||
*
|
||||
* This structure is an opaque handle that represents a handle to a store. This
|
||||
* handle can be used to remotely (from another thread) interrupt currently
|
||||
* executing WebAssembly code.
|
||||
*
|
||||
* This structure is safe to share from multiple threads.
|
||||
*/
|
||||
typedef struct wasmtime_interrupt_handle wasmtime_interrupt_handle_t;
|
||||
|
||||
/**
|
||||
* \brief Creates a new interrupt handle to interrupt executing WebAssembly from
|
||||
* the provided store.
|
||||
*
|
||||
* There are a number of caveats about how interrupt is handled in Wasmtime. For
|
||||
* more information see the [Rust
|
||||
* documentation](https://bytecodealliance.github.io/wasmtime/api/wasmtime/struct.Store.html#method.interrupt_handle).
|
||||
*
|
||||
* This function returns `NULL` if the store's configuration does not have
|
||||
* interrupts enabled. See #wasmtime_config_interruptable_set.
|
||||
*/
|
||||
WASM_API_EXTERN wasmtime_interrupt_handle_t *wasmtime_interrupt_handle_new(wasmtime_context_t *context);
|
||||
|
||||
/**
|
||||
* \brief Requests that WebAssembly code running in the store attached to this
|
||||
* interrupt handle is interrupted.
|
||||
*
|
||||
* For more information about interrupts see #wasmtime_interrupt_handle_new.
|
||||
*
|
||||
* Note that this is safe to call from any thread.
|
||||
*/
|
||||
WASM_API_EXTERN void wasmtime_interrupt_handle_interrupt(wasmtime_interrupt_handle_t *handle);
|
||||
|
||||
/**
|
||||
* \brief Deletes an interrupt handle.
|
||||
*/
|
||||
WASM_API_EXTERN void wasmtime_interrupt_handle_delete(wasmtime_interrupt_handle_t *handle);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // WASMTIME_STORE_H
|
||||
|
||||
126
crates/c-api/include/wasmtime/table.h
Normal file
126
crates/c-api/include/wasmtime/table.h
Normal file
@@ -0,0 +1,126 @@
|
||||
/**
|
||||
* \file wasmtime/table.h
|
||||
*
|
||||
* Wasmtime APIs for interacting with WebAssembly tables.
|
||||
*/
|
||||
|
||||
#ifndef WASMTIME_TABLE_H
|
||||
#define WASMTIME_TABLE_H
|
||||
|
||||
#include <wasm.h>
|
||||
#include <wasmtime/extern.h>
|
||||
#include <wasmtime/store.h>
|
||||
#include <wasmtime/error.h>
|
||||
#include <wasmtime/val.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Creates a new host-defined wasm table.
|
||||
*
|
||||
* \param store the store to create the table within
|
||||
* \param ty the type of the table to create
|
||||
* \param init the initial value for this table's elements
|
||||
* \param table where to store the returned table
|
||||
*
|
||||
* This function does not take ownership of any of its parameters, but yields
|
||||
* ownership of returned error. This function may return an error if the `init`
|
||||
* value does not match `ty`, for example.
|
||||
*/
|
||||
WASM_API_EXTERN wasmtime_error_t *wasmtime_table_new(
|
||||
wasmtime_context_t *store,
|
||||
const wasm_tabletype_t *ty,
|
||||
const wasmtime_val_t *init,
|
||||
wasmtime_table_t *table
|
||||
);
|
||||
|
||||
/**
|
||||
* \brief Returns the type of this table.
|
||||
*
|
||||
* The caller has ownership of the returned #wasm_tabletype_t
|
||||
*/
|
||||
WASM_API_EXTERN wasm_tabletype_t* wasmtime_table_type(
|
||||
const wasmtime_context_t *store,
|
||||
const wasmtime_table_t *table
|
||||
);
|
||||
|
||||
/**
|
||||
* \brief Gets a value in a table.
|
||||
*
|
||||
* \param store the store that owns `table`
|
||||
* \param table the table to access
|
||||
* \param index the table index to access
|
||||
* \param val where to store the table's value
|
||||
*
|
||||
* This function will attempt to access a table element. If a nonzero value is
|
||||
* returned then `val` is filled in and is owned by the caller. Otherwise zero
|
||||
* is returned because the `index` is out-of-bounds.
|
||||
*/
|
||||
WASM_API_EXTERN bool wasmtime_table_get(
|
||||
wasmtime_context_t *store,
|
||||
const wasmtime_table_t *table,
|
||||
uint32_t index,
|
||||
wasmtime_val_t *val
|
||||
);
|
||||
|
||||
/**
|
||||
* \brief Sets a value in a table.
|
||||
*
|
||||
* \param store the store that owns `table`
|
||||
* \param table the table to write to
|
||||
* \param index the table index to write
|
||||
* \param value the value to store.
|
||||
*
|
||||
* This function will store `value` into the specified index in the table. This
|
||||
* does not take ownership of any argument but yields ownership of the error.
|
||||
* This function can fail if `value` has the wrong type for the table, or if
|
||||
* `index` is out of bounds.
|
||||
*/
|
||||
WASM_API_EXTERN wasmtime_error_t *wasmtime_table_set(
|
||||
wasmtime_context_t *store,
|
||||
const wasmtime_table_t *table,
|
||||
uint32_t index,
|
||||
const wasmtime_val_t *value
|
||||
);
|
||||
|
||||
/**
|
||||
* \brief Returns the size, in elements, of the specified table
|
||||
*/
|
||||
WASM_API_EXTERN uint32_t wasmtime_table_size(
|
||||
const wasmtime_context_t *store,
|
||||
const wasmtime_table_t *table
|
||||
);
|
||||
|
||||
/**
|
||||
* \brief Grows a table.
|
||||
*
|
||||
* \param store the store that owns `table`
|
||||
* \param table the table to grow
|
||||
* \param delta the number of elements to grow the table by
|
||||
* \param init the initial value for new table element slots
|
||||
* \param prev_size where to store the previous size of the table before growth
|
||||
*
|
||||
* This function will attempt to grow the table by `delta` table elements. This
|
||||
* can fail if `delta` would exceed the maximum size of the table or if `init`
|
||||
* is the wrong type for this table. If growth is successful then `NULL` is
|
||||
* returned and `prev_size` is filled in with the previous size of the table, in
|
||||
* elements, before the growth happened.
|
||||
*
|
||||
* This function does not take ownership of any of its arguments.
|
||||
*/
|
||||
WASM_API_EXTERN wasmtime_error_t *wasmtime_table_grow(
|
||||
wasmtime_context_t *store,
|
||||
const wasmtime_table_t *table,
|
||||
uint32_t delta,
|
||||
const wasmtime_val_t *init,
|
||||
uint32_t *prev_size
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // WASMTIME_TABLE_H
|
||||
|
||||
60
crates/c-api/include/wasmtime/trap.h
Normal file
60
crates/c-api/include/wasmtime/trap.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* \file wasmtime/trap.h
|
||||
*
|
||||
* Wasmtime APIs for interacting with traps and extensions to #wasm_trap_t.
|
||||
*/
|
||||
|
||||
#ifndef WASMTIME_TRAP_H
|
||||
#define WASMTIME_TRAP_H
|
||||
|
||||
#include <wasm.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Creates a new trap.
|
||||
*
|
||||
* \param msg the message to associate with this trap
|
||||
* \param msg_len the byte length of `msg`
|
||||
*
|
||||
* The #wasm_trap_t returned is owned by the caller.
|
||||
*/
|
||||
WASM_API_EXTERN wasm_trap_t *wasmtime_trap_new(const char *msg, size_t msg_len);
|
||||
|
||||
/**
|
||||
* \brief Attempts to extract a WASI-specific exit status from this trap.
|
||||
*
|
||||
* Returns `true` if the trap is a WASI "exit" trap and has a return status. If
|
||||
* `true` is returned then the exit status is returned through the `status`
|
||||
* pointer. If `false` is returned then this is not a wasi exit trap.
|
||||
*/
|
||||
WASM_API_EXTERN bool wasmtime_trap_exit_status(const wasm_trap_t*, int *status);
|
||||
|
||||
/**
|
||||
* \brief Returns a human-readable name for this frame's function.
|
||||
*
|
||||
* This function will attempt to load a human-readable name for function this
|
||||
* frame points to. This function may return `NULL`.
|
||||
*
|
||||
* The lifetime of the returned name is the same as the #wasm_frame_t itself.
|
||||
*/
|
||||
WASM_API_EXTERN const wasm_name_t *wasmtime_frame_func_name(const wasm_frame_t*);
|
||||
|
||||
/**
|
||||
* \brief Returns a human-readable name for this frame's module.
|
||||
*
|
||||
* This function will attempt to load a human-readable name for module this
|
||||
* frame points to. This function may return `NULL`.
|
||||
*
|
||||
* The lifetime of the returned name is the same as the #wasm_frame_t itself.
|
||||
*/
|
||||
WASM_API_EXTERN const wasm_name_t *wasmtime_frame_module_name(const wasm_frame_t*);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // WASMTIME_TRAP_H
|
||||
158
crates/c-api/include/wasmtime/val.h
Normal file
158
crates/c-api/include/wasmtime/val.h
Normal file
@@ -0,0 +1,158 @@
|
||||
/**
|
||||
* \file wasmtime/val.h
|
||||
*
|
||||
* APIs for interacting with WebAssembly values in Wasmtime.
|
||||
*/
|
||||
|
||||
#ifndef WASMTIME_VAL_H
|
||||
#define WASMTIME_VAL_H
|
||||
|
||||
#include <wasm.h>
|
||||
#include <wasmtime/extern.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \typedef wasmtime_externref_t
|
||||
* \brief Convenience alias for #wasmtime_externref
|
||||
*
|
||||
* \struct wasmtime_externref
|
||||
* \brief A host-defined un-forgeable reference to pass into WebAssembly.
|
||||
*
|
||||
* This structure represents an `externref` that can be passed to WebAssembly.
|
||||
* It cannot be forged by WebAssembly itself and is guaranteed to have been
|
||||
* created by the host.
|
||||
*/
|
||||
typedef struct wasmtime_externref wasmtime_externref_t;
|
||||
|
||||
/**
|
||||
* \brief Create a new `externref` value.
|
||||
*
|
||||
* Creates a new `externref` value wrapping the provided data, returning the
|
||||
* pointer to the externref.
|
||||
*
|
||||
* \param data the host-specific data to wrap
|
||||
* \param finalizer an optional finalizer for `data`
|
||||
*
|
||||
* When the reference is reclaimed, the wrapped data is cleaned up with the
|
||||
* provided `finalizer`.
|
||||
*
|
||||
* The returned value must be deleted with #wasmtime_externref_delete
|
||||
*/
|
||||
WASM_API_EXTERN wasmtime_externref_t *wasmtime_externref_new(void *data, void (*finalizer)(void*));
|
||||
|
||||
/**
|
||||
* \brief Get an `externref`'s wrapped data
|
||||
*
|
||||
* Returns the original `data` passed to #wasmtime_externref_new. It is required
|
||||
* that `data` is not `NULL`.
|
||||
*/
|
||||
WASM_API_EXTERN void *wasmtime_externref_data(wasmtime_externref_t *data);
|
||||
|
||||
/**
|
||||
* \brief Creates a shallow copy of the `externref` argument, returning a
|
||||
* separately owned pointer (increases the reference count).
|
||||
*/
|
||||
WASM_API_EXTERN wasmtime_externref_t *wasmtime_externref_clone(wasmtime_externref_t *ref);
|
||||
|
||||
/**
|
||||
* \brief Decrements the reference count of the `ref`, deleting it if it's the
|
||||
* last reference.
|
||||
*/
|
||||
WASM_API_EXTERN void wasmtime_externref_delete(wasmtime_externref_t *ref);
|
||||
|
||||
/// \brief Discriminant stored in #wasmtime_val::kind
|
||||
typedef uint8_t wasmtime_valkind_t;
|
||||
/// \brief Value of #wasmtime_valkind_t meaning that #wasmtime_val_t is an i32
|
||||
#define WASMTIME_I32 0
|
||||
/// \brief Value of #wasmtime_valkind_t meaning that #wasmtime_val_t is an i64
|
||||
#define WASMTIME_I64 1
|
||||
/// \brief Value of #wasmtime_valkind_t meaning that #wasmtime_val_t is a f32
|
||||
#define WASMTIME_F32 2
|
||||
/// \brief Value of #wasmtime_valkind_t meaning that #wasmtime_val_t is a f64
|
||||
#define WASMTIME_F64 3
|
||||
/// \brief Value of #wasmtime_valkind_t meaning that #wasmtime_val_t is a v128
|
||||
#define WASMTIME_V128 4
|
||||
/// \brief Value of #wasmtime_valkind_t meaning that #wasmtime_val_t is a funcref
|
||||
#define WASMTIME_FUNCREF 5
|
||||
/// \brief Value of #wasmtime_valkind_t meaning that #wasmtime_val_t is an externref
|
||||
#define WASMTIME_EXTERNREF 6
|
||||
|
||||
/// \brief A 128-bit value representing the WebAssembly `v128` type. Bytes are
|
||||
/// stored in little-endian order.
|
||||
typedef uint8_t wasmtime_v128[16];
|
||||
|
||||
/**
|
||||
* \typedef wasmtime_valunion_t
|
||||
* \brief Convenience alias for #wasmtime_valunion
|
||||
*
|
||||
* \union wasmtime_valunion
|
||||
* \brief Container for different kinds of wasm values.
|
||||
*
|
||||
* This type is contained in #wasmtime_val_t and contains the payload for the
|
||||
* various kinds of items a value can be.
|
||||
*/
|
||||
typedef union wasmtime_valunion {
|
||||
/// Field used if #wasmtime_val_t::kind is #WASMTIME_I32
|
||||
int32_t i32;
|
||||
/// Field used if #wasmtime_val_t::kind is #WASMTIME_I64
|
||||
int64_t i64;
|
||||
/// Field used if #wasmtime_val_t::kind is #WASMTIME_F32
|
||||
float32_t f32;
|
||||
/// Field used if #wasmtime_val_t::kind is #WASMTIME_F64
|
||||
float64_t f64;
|
||||
/// Field used if #wasmtime_val_t::kind is #WASMTIME_FUNCREF
|
||||
///
|
||||
/// If this value represents a `ref.null func` value then the `store_id` field
|
||||
/// is set to zero.
|
||||
wasmtime_func_t funcref;
|
||||
/// Field used if #wasmtime_val_t::kind is #WASMTIME_EXTERNREF
|
||||
///
|
||||
/// If this value represents a `ref.null extern` value then this pointer will
|
||||
/// be `NULL`.
|
||||
wasmtime_externref_t *externref;
|
||||
/// Field used if #wasmtime_val_t::kind is #WASMTIME_V128
|
||||
wasmtime_v128 v128;
|
||||
} wasmtime_valunion_t;
|
||||
|
||||
/**
|
||||
* \typedef wasmtime_val_t
|
||||
* \brief Convenience alias for #wasmtime_val_t
|
||||
*
|
||||
* \union wasmtime_val
|
||||
* \brief Container for different kinds of wasm values.
|
||||
*
|
||||
* Note that this structure may contain an owned value, namely
|
||||
* #wasmtime_externref_t, depending on the context in which this is used. APIs
|
||||
* which consume a #wasmtime_val_t do not take ownership, but APIs that return
|
||||
* #wasmtime_val_t require that #wasmtime_val_delete is called to deallocate
|
||||
* the value.
|
||||
*/
|
||||
typedef struct wasmtime_val {
|
||||
/// Discriminant of which field of #of is valid.
|
||||
wasmtime_valkind_t kind;
|
||||
/// Container for the extern item's value.
|
||||
wasmtime_valunion_t of;
|
||||
} wasmtime_val_t;
|
||||
|
||||
/**
|
||||
* \brief Delets an owned #wasmtime_val_t.
|
||||
*
|
||||
* Note that this only deletes the contents, not the memory that `val` points to
|
||||
* itself (which is owned by the caller).
|
||||
*/
|
||||
WASM_API_EXTERN void wasmtime_val_delete(wasmtime_val_t *val);
|
||||
|
||||
/**
|
||||
* \brief Copies `src` into `dst`.
|
||||
*/
|
||||
WASM_API_EXTERN void wasmtime_val_copy(wasmtime_val_t *dst, const wasmtime_val_t *src);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // WASMTIME_VAL_H
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use crate::{wasm_name_t, wasm_trap_t};
|
||||
use crate::wasm_name_t;
|
||||
use anyhow::{anyhow, Error, Result};
|
||||
use wasmtime::Trap;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct wasmtime_error_t {
|
||||
@@ -9,12 +8,6 @@ pub struct wasmtime_error_t {
|
||||
|
||||
wasmtime_c_api_macros::declare_own!(wasmtime_error_t);
|
||||
|
||||
impl wasmtime_error_t {
|
||||
pub(crate) fn to_trap(self) -> Box<wasm_trap_t> {
|
||||
Box::new(wasm_trap_t::new(Trap::from(self.error)))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Error> for wasmtime_error_t {
|
||||
fn from(error: Error) -> wasmtime_error_t {
|
||||
wasmtime_error_t { error }
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
use crate::{
|
||||
wasm_externkind_t, wasm_externtype_t, wasm_func_t, wasm_global_t, wasm_instance_t,
|
||||
wasm_memory_t, wasm_module_t, wasm_table_t,
|
||||
wasm_memory_t, wasm_module_t, wasm_table_t, wasmtime_module_t, CStoreContext, StoreRef,
|
||||
};
|
||||
use wasmtime::Extern;
|
||||
use std::mem::ManuallyDrop;
|
||||
use wasmtime::{Extern, Func, Global, Instance, Memory, Table};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct wasm_extern_t {
|
||||
pub(crate) store: StoreRef,
|
||||
pub(crate) which: Extern,
|
||||
}
|
||||
|
||||
@@ -24,8 +26,8 @@ pub extern "C" fn wasm_extern_kind(e: &wasm_extern_t) -> wasm_externkind_t {
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_extern_type(e: &wasm_extern_t) -> Box<wasm_externtype_t> {
|
||||
Box::new(wasm_externtype_t::new(e.which.ty()))
|
||||
pub unsafe extern "C" fn wasm_extern_type(e: &wasm_extern_t) -> Box<wasm_externtype_t> {
|
||||
Box::new(wasm_externtype_t::new(e.which.ty(&e.store.context())))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -87,3 +89,97 @@ pub extern "C" fn wasm_extern_as_instance(e: &wasm_extern_t) -> Option<&wasm_ins
|
||||
pub extern "C" fn wasm_extern_as_instance_const(e: &wasm_extern_t) -> Option<&wasm_instance_t> {
|
||||
wasm_extern_as_instance(e)
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct wasmtime_extern_t {
|
||||
pub kind: wasmtime_extern_kind_t,
|
||||
pub of: wasmtime_extern_union,
|
||||
}
|
||||
|
||||
pub type wasmtime_extern_kind_t = u8;
|
||||
pub const WASMTIME_EXTERN_FUNC: wasmtime_extern_kind_t = 0;
|
||||
pub const WASMTIME_EXTERN_GLOBAL: wasmtime_extern_kind_t = 1;
|
||||
pub const WASMTIME_EXTERN_TABLE: wasmtime_extern_kind_t = 2;
|
||||
pub const WASMTIME_EXTERN_MEMORY: wasmtime_extern_kind_t = 3;
|
||||
pub const WASMTIME_EXTERN_INSTANCE: wasmtime_extern_kind_t = 4;
|
||||
pub const WASMTIME_EXTERN_MODULE: wasmtime_extern_kind_t = 5;
|
||||
|
||||
#[repr(C)]
|
||||
pub union wasmtime_extern_union {
|
||||
pub func: Func,
|
||||
pub table: Table,
|
||||
pub global: Global,
|
||||
pub instance: Instance,
|
||||
pub memory: Memory,
|
||||
pub module: ManuallyDrop<Box<wasmtime_module_t>>,
|
||||
}
|
||||
|
||||
impl wasmtime_extern_t {
|
||||
pub unsafe fn to_extern(&self) -> Extern {
|
||||
match self.kind {
|
||||
WASMTIME_EXTERN_FUNC => Extern::Func(self.of.func),
|
||||
WASMTIME_EXTERN_GLOBAL => Extern::Global(self.of.global),
|
||||
WASMTIME_EXTERN_TABLE => Extern::Table(self.of.table),
|
||||
WASMTIME_EXTERN_MEMORY => Extern::Memory(self.of.memory),
|
||||
WASMTIME_EXTERN_INSTANCE => Extern::Instance(self.of.instance),
|
||||
WASMTIME_EXTERN_MODULE => Extern::Module(self.of.module.module.clone()),
|
||||
other => panic!("unknown wasm_extern_kind_t: {}", other),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Extern> for wasmtime_extern_t {
|
||||
fn from(item: Extern) -> wasmtime_extern_t {
|
||||
match item {
|
||||
Extern::Func(func) => wasmtime_extern_t {
|
||||
kind: WASMTIME_EXTERN_FUNC,
|
||||
of: wasmtime_extern_union { func },
|
||||
},
|
||||
Extern::Global(global) => wasmtime_extern_t {
|
||||
kind: WASMTIME_EXTERN_GLOBAL,
|
||||
of: wasmtime_extern_union { global },
|
||||
},
|
||||
Extern::Table(table) => wasmtime_extern_t {
|
||||
kind: WASMTIME_EXTERN_TABLE,
|
||||
of: wasmtime_extern_union { table },
|
||||
},
|
||||
Extern::Memory(memory) => wasmtime_extern_t {
|
||||
kind: WASMTIME_EXTERN_MEMORY,
|
||||
of: wasmtime_extern_union { memory },
|
||||
},
|
||||
Extern::Instance(instance) => wasmtime_extern_t {
|
||||
kind: WASMTIME_EXTERN_INSTANCE,
|
||||
of: wasmtime_extern_union { instance },
|
||||
},
|
||||
Extern::Module(module) => wasmtime_extern_t {
|
||||
kind: WASMTIME_EXTERN_MODULE,
|
||||
of: wasmtime_extern_union {
|
||||
module: ManuallyDrop::new(Box::new(wasmtime_module_t { module })),
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for wasmtime_extern_t {
|
||||
fn drop(&mut self) {
|
||||
if self.kind == WASMTIME_EXTERN_MODULE {
|
||||
unsafe {
|
||||
ManuallyDrop::drop(&mut self.of.module);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasmtime_extern_delete(e: &mut ManuallyDrop<wasmtime_extern_t>) {
|
||||
ManuallyDrop::drop(e);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasmtime_extern_type(
|
||||
store: CStoreContext<'_>,
|
||||
e: &wasmtime_extern_t,
|
||||
) -> Box<wasm_externtype_t> {
|
||||
Box::new(wasm_externtype_t::new(e.to_extern().ty(store)))
|
||||
}
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
use crate::{wasm_extern_t, wasm_functype_t, wasm_store_t, wasm_val_t, wasm_val_vec_t};
|
||||
use crate::{wasm_name_t, wasm_trap_t, wasmtime_error_t};
|
||||
use crate::wasm_trap_t;
|
||||
use crate::{
|
||||
wasm_extern_t, wasm_functype_t, wasm_store_t, wasm_val_t, wasm_val_vec_t, wasmtime_error_t,
|
||||
wasmtime_extern_t, wasmtime_val_t, wasmtime_val_union, CStoreContext, CStoreContextMut,
|
||||
};
|
||||
use anyhow::anyhow;
|
||||
use std::ffi::c_void;
|
||||
use std::mem::MaybeUninit;
|
||||
use std::panic::{self, AssertUnwindSafe};
|
||||
use std::ptr;
|
||||
use std::str;
|
||||
use wasmtime::{Caller, Extern, Func, Trap, Val};
|
||||
use wasmtime::{AsContextMut, Caller, Extern, Func, Trap};
|
||||
|
||||
#[derive(Clone)]
|
||||
#[repr(transparent)]
|
||||
@@ -16,11 +19,6 @@ pub struct wasm_func_t {
|
||||
|
||||
wasmtime_c_api_macros::declare_ref!(wasm_func_t);
|
||||
|
||||
#[repr(C)]
|
||||
pub struct wasmtime_caller_t<'a> {
|
||||
caller: Caller<'a>,
|
||||
}
|
||||
|
||||
pub type wasm_func_callback_t = extern "C" fn(
|
||||
args: *const wasm_val_vec_t,
|
||||
results: *mut wasm_val_vec_t,
|
||||
@@ -32,32 +30,6 @@ pub type wasm_func_callback_with_env_t = extern "C" fn(
|
||||
results: *mut wasm_val_vec_t,
|
||||
) -> Option<Box<wasm_trap_t>>;
|
||||
|
||||
pub type wasmtime_func_callback_t = extern "C" fn(
|
||||
caller: *const wasmtime_caller_t,
|
||||
args: *const wasm_val_vec_t,
|
||||
results: *mut wasm_val_vec_t,
|
||||
) -> Option<Box<wasm_trap_t>>;
|
||||
|
||||
pub type wasmtime_func_callback_with_env_t = extern "C" fn(
|
||||
caller: *const wasmtime_caller_t,
|
||||
env: *mut std::ffi::c_void,
|
||||
args: *const wasm_val_vec_t,
|
||||
results: *mut wasm_val_vec_t,
|
||||
) -> Option<Box<wasm_trap_t>>;
|
||||
|
||||
struct Finalizer {
|
||||
env: *mut c_void,
|
||||
finalizer: Option<extern "C" fn(*mut c_void)>,
|
||||
}
|
||||
|
||||
impl Drop for Finalizer {
|
||||
fn drop(&mut self) {
|
||||
if let Some(f) = self.finalizer {
|
||||
f(self.env);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl wasm_func_t {
|
||||
pub(crate) fn try_from(e: &wasm_extern_t) -> Option<&wasm_func_t> {
|
||||
match &e.which {
|
||||
@@ -66,150 +38,90 @@ impl wasm_func_t {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn func(&self) -> &Func {
|
||||
match &self.ext.which {
|
||||
pub(crate) fn func(&self) -> Func {
|
||||
match self.ext.which {
|
||||
Extern::Func(f) => f,
|
||||
_ => unsafe { std::hint::unreachable_unchecked() },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Func> for wasm_func_t {
|
||||
fn from(func: Func) -> wasm_func_t {
|
||||
wasm_func_t {
|
||||
ext: wasm_extern_t { which: func.into() },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn create_function(
|
||||
store: &wasm_store_t,
|
||||
unsafe fn create_function(
|
||||
store: &mut wasm_store_t,
|
||||
ty: &wasm_functype_t,
|
||||
func: impl Fn(Caller<'_>, *const wasm_val_vec_t, *mut wasm_val_vec_t) -> Option<Box<wasm_trap_t>>
|
||||
func: impl Fn(*const wasm_val_vec_t, *mut wasm_val_vec_t) -> Option<Box<wasm_trap_t>>
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
) -> Box<wasm_func_t> {
|
||||
let store = &store.store;
|
||||
let ty = ty.ty().ty.clone();
|
||||
let func = Func::new(store, ty, move |caller, params, results| {
|
||||
let params: wasm_val_vec_t = params
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(|p| wasm_val_t::from_val(p))
|
||||
.collect::<Vec<_>>()
|
||||
.into();
|
||||
let mut out_results: wasm_val_vec_t = vec![wasm_val_t::default(); results.len()].into();
|
||||
let out = func(caller, ¶ms, &mut out_results);
|
||||
if let Some(trap) = out {
|
||||
return Err(trap.trap.clone());
|
||||
}
|
||||
let func = Func::new(
|
||||
store.store.context_mut(),
|
||||
ty,
|
||||
move |_caller, params, results| {
|
||||
let params: wasm_val_vec_t = params
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(|p| wasm_val_t::from_val(p))
|
||||
.collect::<Vec<_>>()
|
||||
.into();
|
||||
let mut out_results: wasm_val_vec_t = vec![wasm_val_t::default(); results.len()].into();
|
||||
let out = func(¶ms, &mut out_results);
|
||||
if let Some(trap) = out {
|
||||
return Err(trap.trap.clone());
|
||||
}
|
||||
|
||||
let out_results = out_results.as_slice();
|
||||
for i in 0..results.len() {
|
||||
results[i] = out_results[i].val();
|
||||
}
|
||||
Ok(())
|
||||
});
|
||||
Box::new(func.into())
|
||||
let out_results = out_results.as_slice();
|
||||
for i in 0..results.len() {
|
||||
results[i] = out_results[i].val();
|
||||
}
|
||||
Ok(())
|
||||
},
|
||||
);
|
||||
Box::new(wasm_func_t {
|
||||
ext: wasm_extern_t {
|
||||
store: store.store.clone(),
|
||||
which: func.into(),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_func_new(
|
||||
store: &wasm_store_t,
|
||||
pub unsafe extern "C" fn wasm_func_new(
|
||||
store: &mut wasm_store_t,
|
||||
ty: &wasm_functype_t,
|
||||
callback: wasm_func_callback_t,
|
||||
) -> Box<wasm_func_t> {
|
||||
create_function(store, ty, move |_caller, params, results| {
|
||||
callback(params, results)
|
||||
})
|
||||
create_function(store, ty, move |params, results| callback(params, results))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasmtime_func_new(
|
||||
store: &wasm_store_t,
|
||||
ty: &wasm_functype_t,
|
||||
callback: wasmtime_func_callback_t,
|
||||
) -> Box<wasm_func_t> {
|
||||
create_function(store, ty, move |caller, params, results| {
|
||||
callback(&wasmtime_caller_t { caller }, params, results)
|
||||
})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_func_new_with_env(
|
||||
store: &wasm_store_t,
|
||||
pub unsafe extern "C" fn wasm_func_new_with_env(
|
||||
store: &mut wasm_store_t,
|
||||
ty: &wasm_functype_t,
|
||||
callback: wasm_func_callback_with_env_t,
|
||||
env: *mut c_void,
|
||||
data: *mut c_void,
|
||||
finalizer: Option<extern "C" fn(arg1: *mut std::ffi::c_void)>,
|
||||
) -> Box<wasm_func_t> {
|
||||
let finalizer = Finalizer { env, finalizer };
|
||||
create_function(store, ty, move |_caller, params, results| {
|
||||
callback(finalizer.env, params, results)
|
||||
})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_func_new_with_env(
|
||||
store: &wasm_store_t,
|
||||
ty: &wasm_functype_t,
|
||||
callback: wasmtime_func_callback_with_env_t,
|
||||
env: *mut c_void,
|
||||
finalizer: Option<extern "C" fn(*mut c_void)>,
|
||||
) -> Box<wasm_func_t> {
|
||||
let finalizer = Finalizer { env, finalizer };
|
||||
create_function(store, ty, move |caller, params, results| {
|
||||
callback(
|
||||
&wasmtime_caller_t { caller },
|
||||
finalizer.env,
|
||||
params,
|
||||
results,
|
||||
)
|
||||
let finalizer = crate::ForeignData { data, finalizer };
|
||||
create_function(store, ty, move |params, results| {
|
||||
callback(finalizer.data, params, results)
|
||||
})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_func_call(
|
||||
wasm_func: &wasm_func_t,
|
||||
func: &mut wasm_func_t,
|
||||
args: *const wasm_val_vec_t,
|
||||
results: *mut wasm_val_vec_t,
|
||||
) -> *mut wasm_trap_t {
|
||||
let mut trap = ptr::null_mut();
|
||||
let error = _wasmtime_func_call(
|
||||
wasm_func,
|
||||
(*args).as_slice(),
|
||||
(*results).as_uninit_slice(),
|
||||
&mut trap,
|
||||
);
|
||||
match error {
|
||||
Some(err) => Box::into_raw(err.to_trap()),
|
||||
None => trap,
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasmtime_func_call(
|
||||
func: &wasm_func_t,
|
||||
args: *const wasm_val_vec_t,
|
||||
results: *mut wasm_val_vec_t,
|
||||
trap_ptr: &mut *mut wasm_trap_t,
|
||||
) -> Option<Box<wasmtime_error_t>> {
|
||||
_wasmtime_func_call(
|
||||
func,
|
||||
(*args).as_slice(),
|
||||
(*results).as_uninit_slice(),
|
||||
trap_ptr,
|
||||
)
|
||||
}
|
||||
|
||||
fn _wasmtime_func_call(
|
||||
func: &wasm_func_t,
|
||||
args: &[wasm_val_t],
|
||||
results: &mut [MaybeUninit<wasm_val_t>],
|
||||
trap_ptr: &mut *mut wasm_trap_t,
|
||||
) -> Option<Box<wasmtime_error_t>> {
|
||||
let func = func.func();
|
||||
if results.len() != func.result_arity() {
|
||||
return Some(Box::new(anyhow!("wrong number of results provided").into()));
|
||||
let f = func.func();
|
||||
let results = (*results).as_uninit_slice();
|
||||
let args = (*args).as_slice();
|
||||
if results.len() != f.ty(func.ext.store.context()).results().len() {
|
||||
return Box::into_raw(Box::new(wasm_trap_t::new(
|
||||
anyhow!("wrong number of results provided").into(),
|
||||
)));
|
||||
}
|
||||
let params = args.iter().map(|i| i.val()).collect::<Vec<_>>();
|
||||
|
||||
@@ -217,20 +129,19 @@ fn _wasmtime_func_call(
|
||||
// want to try to insulate callers against bugs in wasmtime/wasi/etc if we
|
||||
// can. As a result we catch panics here and transform them to traps to
|
||||
// allow the caller to have any insulation possible against Rust panics.
|
||||
let result = panic::catch_unwind(AssertUnwindSafe(|| func.call(¶ms)));
|
||||
let result = panic::catch_unwind(AssertUnwindSafe(|| {
|
||||
f.call(func.ext.store.context_mut(), ¶ms)
|
||||
}));
|
||||
match result {
|
||||
Ok(Ok(out)) => {
|
||||
for (slot, val) in results.iter_mut().zip(out.into_vec().into_iter()) {
|
||||
crate::initialize(slot, wasm_val_t::from_val(val));
|
||||
}
|
||||
None
|
||||
ptr::null_mut()
|
||||
}
|
||||
Ok(Err(trap)) => match trap.downcast::<Trap>() {
|
||||
Ok(trap) => {
|
||||
*trap_ptr = Box::into_raw(Box::new(wasm_trap_t::new(trap)));
|
||||
None
|
||||
}
|
||||
Err(err) => Some(Box::new(err.into())),
|
||||
Ok(trap) => Box::into_raw(Box::new(wasm_trap_t::new(trap))),
|
||||
Err(err) => Box::into_raw(Box::new(wasm_trap_t::new(err.into()))),
|
||||
},
|
||||
Err(panic) => {
|
||||
let trap = if let Some(msg) = panic.downcast_ref::<String>() {
|
||||
@@ -241,25 +152,24 @@ fn _wasmtime_func_call(
|
||||
Trap::new("rust panic happened")
|
||||
};
|
||||
let trap = Box::new(wasm_trap_t::new(trap));
|
||||
*trap_ptr = Box::into_raw(trap);
|
||||
None
|
||||
Box::into_raw(trap)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_func_type(f: &wasm_func_t) -> Box<wasm_functype_t> {
|
||||
Box::new(wasm_functype_t::new(f.func().ty()))
|
||||
pub unsafe extern "C" fn wasm_func_type(f: &wasm_func_t) -> Box<wasm_functype_t> {
|
||||
Box::new(wasm_functype_t::new(f.func().ty(f.ext.store.context())))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_func_param_arity(f: &wasm_func_t) -> usize {
|
||||
f.func().param_arity()
|
||||
pub unsafe extern "C" fn wasm_func_param_arity(f: &wasm_func_t) -> usize {
|
||||
f.func().ty(f.ext.store.context()).params().len()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_func_result_arity(f: &wasm_func_t) -> usize {
|
||||
f.func().result_arity()
|
||||
pub unsafe extern "C" fn wasm_func_result_arity(f: &wasm_func_t) -> usize {
|
||||
f.func().ty(f.ext.store.context()).results().len()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -268,29 +178,150 @@ pub extern "C" fn wasm_func_as_extern(f: &mut wasm_func_t) -> &mut wasm_extern_t
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_caller_export_get(
|
||||
caller: &wasmtime_caller_t,
|
||||
name: &wasm_name_t,
|
||||
) -> Option<Box<wasm_extern_t>> {
|
||||
let name = str::from_utf8(name.as_slice()).ok()?;
|
||||
let which = caller.caller.get_export(name)?;
|
||||
Some(Box::new(wasm_extern_t { which }))
|
||||
pub extern "C" fn wasm_func_as_extern_const(f: &wasm_func_t) -> &wasm_extern_t {
|
||||
&(*f).ext
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct wasmtime_caller_t<'a> {
|
||||
caller: Caller<'a, crate::StoreData>,
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_func_as_funcref(
|
||||
func: &wasm_func_t,
|
||||
funcrefp: &mut MaybeUninit<wasm_val_t>,
|
||||
pub unsafe extern "C" fn wasmtime_func_new(
|
||||
store: CStoreContextMut<'_>,
|
||||
ty: &wasm_functype_t,
|
||||
callback: extern "C" fn(
|
||||
*mut c_void,
|
||||
*mut wasmtime_caller_t,
|
||||
*const wasmtime_val_t,
|
||||
usize,
|
||||
*mut wasmtime_val_t,
|
||||
usize,
|
||||
) -> Option<Box<wasm_trap_t>>,
|
||||
data: *mut c_void,
|
||||
finalizer: Option<extern "C" fn(*mut std::ffi::c_void)>,
|
||||
func: &mut Func,
|
||||
) {
|
||||
let funcref = wasm_val_t::from_val(Val::FuncRef(Some(func.func().clone())));
|
||||
crate::initialize(funcrefp, funcref);
|
||||
let foreign = crate::ForeignData { data, finalizer };
|
||||
let ty = ty.ty().ty.clone();
|
||||
let f = Func::new(store, ty, move |caller, params, results| {
|
||||
let params = params
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(|p| wasmtime_val_t::from_val(p))
|
||||
.collect::<Vec<_>>();
|
||||
let mut out_results = (0..results.len())
|
||||
.map(|_| wasmtime_val_t {
|
||||
kind: crate::WASMTIME_I32,
|
||||
of: wasmtime_val_union { i32: 0 },
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
let mut caller = wasmtime_caller_t { caller };
|
||||
let out = callback(
|
||||
foreign.data,
|
||||
&mut caller,
|
||||
params.as_ptr(),
|
||||
params.len(),
|
||||
out_results.as_mut_ptr(),
|
||||
out_results.len(),
|
||||
);
|
||||
if let Some(trap) = out {
|
||||
return Err(trap.trap);
|
||||
}
|
||||
|
||||
for (i, result) in out_results.iter().enumerate() {
|
||||
results[i] = unsafe { result.to_val() };
|
||||
}
|
||||
Ok(())
|
||||
});
|
||||
*func = f;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_funcref_as_func(val: &wasm_val_t) -> Option<Box<wasm_func_t>> {
|
||||
if let Val::FuncRef(Some(f)) = val.val() {
|
||||
Some(Box::new(f.into()))
|
||||
} else {
|
||||
None
|
||||
pub unsafe extern "C" fn wasmtime_func_call(
|
||||
store: CStoreContextMut<'_>,
|
||||
func: &Func,
|
||||
args: *const wasmtime_val_t,
|
||||
nargs: usize,
|
||||
results: *mut MaybeUninit<wasmtime_val_t>,
|
||||
nresults: usize,
|
||||
trap_ret: &mut *mut wasm_trap_t,
|
||||
) -> Option<Box<wasmtime_error_t>> {
|
||||
if nresults != func.ty(&store).results().len() {
|
||||
return Some(Box::new(wasmtime_error_t::from(anyhow!(
|
||||
"wrong number of results provided"
|
||||
))));
|
||||
}
|
||||
let params = crate::slice_from_raw_parts(args, nargs)
|
||||
.iter()
|
||||
.map(|i| i.to_val())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// We're calling arbitrary code here most of the time, and we in general
|
||||
// want to try to insulate callers against bugs in wasmtime/wasi/etc if we
|
||||
// can. As a result we catch panics here and transform them to traps to
|
||||
// allow the caller to have any insulation possible against Rust panics.
|
||||
let result = panic::catch_unwind(AssertUnwindSafe(|| func.call(store, ¶ms)));
|
||||
match result {
|
||||
Ok(Ok(out)) => {
|
||||
let results = crate::slice_from_raw_parts_mut(results, nresults);
|
||||
for (slot, val) in results.iter_mut().zip(out.into_vec().into_iter()) {
|
||||
crate::initialize(slot, wasmtime_val_t::from_val(val));
|
||||
}
|
||||
None
|
||||
}
|
||||
Ok(Err(trap)) => match trap.downcast::<Trap>() {
|
||||
Ok(trap) => {
|
||||
*trap_ret = Box::into_raw(Box::new(wasm_trap_t::new(trap)));
|
||||
None
|
||||
}
|
||||
Err(err) => Some(Box::new(wasmtime_error_t::from(err))),
|
||||
},
|
||||
Err(panic) => {
|
||||
let trap = if let Some(msg) = panic.downcast_ref::<String>() {
|
||||
Trap::new(msg)
|
||||
} else if let Some(msg) = panic.downcast_ref::<&'static str>() {
|
||||
Trap::new(*msg)
|
||||
} else {
|
||||
Trap::new("rust panic happened")
|
||||
};
|
||||
*trap_ret = Box::into_raw(Box::new(wasm_trap_t::new(trap)));
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_func_type(
|
||||
store: CStoreContext<'_>,
|
||||
func: &Func,
|
||||
) -> Box<wasm_functype_t> {
|
||||
Box::new(wasm_functype_t::new(func.ty(store)))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_caller_context<'a>(
|
||||
caller: &'a mut wasmtime_caller_t,
|
||||
) -> CStoreContextMut<'a> {
|
||||
caller.caller.as_context_mut()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasmtime_caller_export_get(
|
||||
caller: &mut wasmtime_caller_t,
|
||||
name: *const u8,
|
||||
name_len: usize,
|
||||
item: &mut MaybeUninit<wasmtime_extern_t>,
|
||||
) -> bool {
|
||||
let name = match str::from_utf8(crate::slice_from_raw_parts(name, name_len)) {
|
||||
Ok(name) => name,
|
||||
Err(_) => return false,
|
||||
};
|
||||
let which = match caller.caller.get_export(name) {
|
||||
Some(item) => item,
|
||||
None => return false,
|
||||
};
|
||||
crate::initialize(item, which.into());
|
||||
true
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
use crate::{handle_result, wasmtime_error_t};
|
||||
use crate::{wasm_extern_t, wasm_globaltype_t, wasm_store_t, wasm_val_t};
|
||||
use crate::{
|
||||
handle_result, wasm_extern_t, wasm_globaltype_t, wasm_store_t, wasm_val_t, wasmtime_error_t,
|
||||
wasmtime_val_t, CStoreContext, CStoreContextMut,
|
||||
};
|
||||
use std::mem::MaybeUninit;
|
||||
use std::ptr;
|
||||
use wasmtime::{Extern, Global};
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -20,8 +21,8 @@ impl wasm_global_t {
|
||||
}
|
||||
}
|
||||
|
||||
fn global(&self) -> &Global {
|
||||
match &self.ext.which {
|
||||
fn global(&self) -> Global {
|
||||
match self.ext.which {
|
||||
Extern::Global(g) => g,
|
||||
_ => unsafe { std::hint::unreachable_unchecked() },
|
||||
}
|
||||
@@ -29,65 +30,88 @@ impl wasm_global_t {
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_global_new(
|
||||
store: &wasm_store_t,
|
||||
pub unsafe extern "C" fn wasm_global_new(
|
||||
store: &mut wasm_store_t,
|
||||
gt: &wasm_globaltype_t,
|
||||
val: &wasm_val_t,
|
||||
) -> Option<Box<wasm_global_t>> {
|
||||
let mut global = ptr::null_mut();
|
||||
match wasmtime_global_new(store, gt, val, &mut global) {
|
||||
Some(_err) => None,
|
||||
None => {
|
||||
assert!(!global.is_null());
|
||||
Some(unsafe { Box::from_raw(global) })
|
||||
}
|
||||
match Global::new(store.store.context_mut(), gt.ty().ty.clone(), val.val()) {
|
||||
Ok(global) => Some(Box::new(wasm_global_t {
|
||||
ext: wasm_extern_t {
|
||||
store: store.store.clone(),
|
||||
which: global.into(),
|
||||
},
|
||||
})),
|
||||
Err(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_global_new(
|
||||
store: &wasm_store_t,
|
||||
gt: &wasm_globaltype_t,
|
||||
val: &wasm_val_t,
|
||||
ret: &mut *mut wasm_global_t,
|
||||
) -> Option<Box<wasmtime_error_t>> {
|
||||
let global = Global::new(&store.store, gt.ty().ty.clone(), val.val());
|
||||
handle_result(global, |global| {
|
||||
*ret = Box::into_raw(Box::new(wasm_global_t {
|
||||
ext: wasm_extern_t {
|
||||
which: global.into(),
|
||||
},
|
||||
}));
|
||||
})
|
||||
pub extern "C" fn wasm_global_as_extern(g: &mut wasm_global_t) -> &mut wasm_extern_t {
|
||||
&mut g.ext
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_global_as_extern(g: &wasm_global_t) -> &wasm_extern_t {
|
||||
pub extern "C" fn wasm_global_as_extern_const(g: &wasm_global_t) -> &wasm_extern_t {
|
||||
&g.ext
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_global_type(g: &wasm_global_t) -> Box<wasm_globaltype_t> {
|
||||
let globaltype = g.global().ty();
|
||||
pub unsafe extern "C" fn wasm_global_type(g: &wasm_global_t) -> Box<wasm_globaltype_t> {
|
||||
let globaltype = g.global().ty(&g.ext.store.context());
|
||||
Box::new(wasm_globaltype_t::new(globaltype))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_global_get(g: &wasm_global_t, out: &mut MaybeUninit<wasm_val_t>) {
|
||||
crate::initialize(out, wasm_val_t::from_val(g.global().get()));
|
||||
pub unsafe extern "C" fn wasm_global_get(g: &mut wasm_global_t, out: &mut MaybeUninit<wasm_val_t>) {
|
||||
let global = g.global();
|
||||
crate::initialize(
|
||||
out,
|
||||
wasm_val_t::from_val(global.get(g.ext.store.context_mut())),
|
||||
);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_global_set(g: &wasm_global_t, val: &wasm_val_t) {
|
||||
let result = g.global().set(val.val());
|
||||
// FIXME(WebAssembly/wasm-c-api#131) should communicate the error here
|
||||
drop(result);
|
||||
pub unsafe extern "C" fn wasm_global_set(g: &mut wasm_global_t, val: &wasm_val_t) {
|
||||
let global = g.global();
|
||||
drop(global.set(g.ext.store.context_mut(), val.val()));
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_global_set(
|
||||
g: &wasm_global_t,
|
||||
val: &wasm_val_t,
|
||||
pub unsafe extern "C" fn wasmtime_global_new(
|
||||
store: CStoreContextMut<'_>,
|
||||
gt: &wasm_globaltype_t,
|
||||
val: &wasmtime_val_t,
|
||||
ret: &mut Global,
|
||||
) -> Option<Box<wasmtime_error_t>> {
|
||||
handle_result(g.global().set(val.val()), |()| {})
|
||||
let global = Global::new(store, gt.ty().ty.clone(), val.to_val());
|
||||
handle_result(global, |global| {
|
||||
*ret = global;
|
||||
})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_global_type(
|
||||
store: CStoreContext<'_>,
|
||||
global: &Global,
|
||||
) -> Box<wasm_globaltype_t> {
|
||||
Box::new(wasm_globaltype_t::new(global.ty(store)))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_global_get(
|
||||
store: CStoreContextMut<'_>,
|
||||
global: &Global,
|
||||
val: &mut MaybeUninit<wasmtime_val_t>,
|
||||
) {
|
||||
crate::initialize(val, wasmtime_val_t::from_val(global.get(store)))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasmtime_global_set(
|
||||
store: CStoreContextMut<'_>,
|
||||
global: &Global,
|
||||
val: &wasmtime_val_t,
|
||||
) -> Option<Box<wasmtime_error_t>> {
|
||||
handle_result(global.set(store, val.to_val()), |()| {})
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
use crate::{wasm_extern_t, wasm_extern_vec_t, wasm_module_t, wasm_trap_t};
|
||||
use crate::{wasm_instancetype_t, wasm_store_t, wasmtime_error_t};
|
||||
use anyhow::Result;
|
||||
use std::ptr;
|
||||
use crate::{
|
||||
wasm_extern_t, wasm_extern_vec_t, wasm_module_t, wasm_store_t, wasm_trap_t, wasmtime_error_t,
|
||||
wasmtime_extern_t, wasmtime_instancetype_t, wasmtime_module_t, CStoreContext, CStoreContextMut,
|
||||
StoreRef,
|
||||
};
|
||||
use std::mem::MaybeUninit;
|
||||
use wasmtime::{Extern, Instance, Trap};
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -13,9 +15,10 @@ pub struct wasm_instance_t {
|
||||
wasmtime_c_api_macros::declare_ref!(wasm_instance_t);
|
||||
|
||||
impl wasm_instance_t {
|
||||
pub(crate) fn new(instance: Instance) -> wasm_instance_t {
|
||||
pub(crate) fn new(store: StoreRef, instance: Instance) -> wasm_instance_t {
|
||||
wasm_instance_t {
|
||||
ext: wasm_extern_t {
|
||||
store: store,
|
||||
which: instance.into(),
|
||||
},
|
||||
}
|
||||
@@ -28,8 +31,8 @@ impl wasm_instance_t {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn instance(&self) -> &Instance {
|
||||
match &self.ext.which {
|
||||
pub(crate) fn instance(&self) -> Instance {
|
||||
match self.ext.which {
|
||||
Extern::Instance(i) => i,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
@@ -38,100 +41,30 @@ impl wasm_instance_t {
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_instance_new(
|
||||
store: &wasm_store_t,
|
||||
store: &mut wasm_store_t,
|
||||
wasm_module: &wasm_module_t,
|
||||
imports: *const wasm_extern_vec_t,
|
||||
result: Option<&mut *mut wasm_trap_t>,
|
||||
) -> Option<Box<wasm_instance_t>> {
|
||||
let mut instance = ptr::null_mut();
|
||||
let mut trap = ptr::null_mut();
|
||||
let err = _wasmtime_instance_new(
|
||||
store,
|
||||
wasm_module,
|
||||
(*imports).as_slice(),
|
||||
&mut instance,
|
||||
&mut trap,
|
||||
);
|
||||
match err {
|
||||
Some(err) => {
|
||||
assert!(trap.is_null());
|
||||
assert!(instance.is_null());
|
||||
if let Some(result) = result {
|
||||
*result = Box::into_raw(err.to_trap());
|
||||
}
|
||||
None
|
||||
}
|
||||
None => {
|
||||
if instance.is_null() {
|
||||
assert!(!trap.is_null());
|
||||
if let Some(result) = result {
|
||||
*result = trap;
|
||||
} else {
|
||||
drop(Box::from_raw(trap))
|
||||
}
|
||||
None
|
||||
} else {
|
||||
assert!(trap.is_null());
|
||||
Some(Box::from_raw(instance))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasmtime_instance_new(
|
||||
store: &wasm_store_t,
|
||||
module: &wasm_module_t,
|
||||
imports: *const wasm_extern_vec_t,
|
||||
instance_ptr: &mut *mut wasm_instance_t,
|
||||
trap_ptr: &mut *mut wasm_trap_t,
|
||||
) -> Option<Box<wasmtime_error_t>> {
|
||||
_wasmtime_instance_new(store, module, (*imports).as_slice(), instance_ptr, trap_ptr)
|
||||
}
|
||||
|
||||
fn _wasmtime_instance_new(
|
||||
store: &wasm_store_t,
|
||||
module: &wasm_module_t,
|
||||
imports: &[Option<Box<wasm_extern_t>>],
|
||||
instance_ptr: &mut *mut wasm_instance_t,
|
||||
trap_ptr: &mut *mut wasm_trap_t,
|
||||
) -> Option<Box<wasmtime_error_t>> {
|
||||
let store = &store.store;
|
||||
let imports = imports
|
||||
let imports = (*imports)
|
||||
.as_slice()
|
||||
.iter()
|
||||
.filter_map(|import| match import {
|
||||
Some(i) => Some(i.which.clone()),
|
||||
None => None,
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
handle_instantiate(
|
||||
Instance::new(store, module.module(), &imports),
|
||||
instance_ptr,
|
||||
trap_ptr,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn handle_instantiate(
|
||||
instance: Result<Instance>,
|
||||
instance_ptr: &mut *mut wasm_instance_t,
|
||||
trap_ptr: &mut *mut wasm_trap_t,
|
||||
) -> Option<Box<wasmtime_error_t>> {
|
||||
fn write<T>(ptr: &mut *mut T, val: T) {
|
||||
*ptr = Box::into_raw(Box::new(val))
|
||||
}
|
||||
|
||||
match instance {
|
||||
Ok(instance) => {
|
||||
write(instance_ptr, wasm_instance_t::new(instance));
|
||||
match Instance::new(store.store.context_mut(), wasm_module.module(), &imports) {
|
||||
Ok(instance) => Some(Box::new(wasm_instance_t::new(
|
||||
store.store.clone(),
|
||||
instance,
|
||||
))),
|
||||
Err(e) => {
|
||||
if let Some(ptr) = result {
|
||||
*ptr = Box::into_raw(Box::new(wasm_trap_t::new(e.into())));
|
||||
}
|
||||
None
|
||||
}
|
||||
Err(e) => match e.downcast::<Trap>() {
|
||||
Ok(trap) => {
|
||||
write(trap_ptr, wasm_trap_t::new(trap));
|
||||
None
|
||||
}
|
||||
Err(e) => Some(Box::new(e.into())),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,14 +74,19 @@ pub extern "C" fn wasm_instance_as_extern(m: &wasm_instance_t) -> &wasm_extern_t
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_instance_exports(instance: &wasm_instance_t, out: &mut wasm_extern_vec_t) {
|
||||
pub unsafe extern "C" fn wasm_instance_exports(
|
||||
instance: &mut wasm_instance_t,
|
||||
out: &mut wasm_extern_vec_t,
|
||||
) {
|
||||
let store = instance.ext.store.clone();
|
||||
out.set_buffer(
|
||||
instance
|
||||
.instance()
|
||||
.exports()
|
||||
.exports(instance.ext.store.context_mut())
|
||||
.map(|e| {
|
||||
Some(Box::new(wasm_extern_t {
|
||||
which: e.into_extern(),
|
||||
store: store.clone(),
|
||||
}))
|
||||
})
|
||||
.collect(),
|
||||
@@ -156,6 +94,91 @@ pub extern "C" fn wasm_instance_exports(instance: &wasm_instance_t, out: &mut wa
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_instance_type(f: &wasm_instance_t) -> Box<wasm_instancetype_t> {
|
||||
Box::new(wasm_instancetype_t::new(f.instance().ty()))
|
||||
pub unsafe extern "C" fn wasmtime_instance_new(
|
||||
store: CStoreContextMut<'_>,
|
||||
module: &wasmtime_module_t,
|
||||
imports: *const wasmtime_extern_t,
|
||||
nimports: usize,
|
||||
instance: &mut Instance,
|
||||
trap_ptr: &mut *mut wasm_trap_t,
|
||||
) -> Option<Box<wasmtime_error_t>> {
|
||||
let imports = crate::slice_from_raw_parts(imports, nimports)
|
||||
.iter()
|
||||
.map(|i| i.to_extern())
|
||||
.collect::<Vec<_>>();
|
||||
handle_instantiate(
|
||||
Instance::new(store, &module.module, &imports),
|
||||
instance,
|
||||
trap_ptr,
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn handle_instantiate(
|
||||
instance: anyhow::Result<Instance>,
|
||||
instance_ptr: &mut Instance,
|
||||
trap_ptr: &mut *mut wasm_trap_t,
|
||||
) -> Option<Box<wasmtime_error_t>> {
|
||||
match instance {
|
||||
Ok(i) => {
|
||||
*instance_ptr = i;
|
||||
None
|
||||
}
|
||||
Err(e) => match e.downcast::<Trap>() {
|
||||
Ok(trap) => {
|
||||
*trap_ptr = Box::into_raw(Box::new(wasm_trap_t::new(trap)));
|
||||
None
|
||||
}
|
||||
Err(e) => Some(Box::new(e.into())),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_instance_type(
|
||||
store: CStoreContext<'_>,
|
||||
instance: &Instance,
|
||||
) -> Box<wasmtime_instancetype_t> {
|
||||
Box::new(wasmtime_instancetype_t::new(instance.ty(store)))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasmtime_instance_export_get(
|
||||
store: CStoreContextMut<'_>,
|
||||
instance: &Instance,
|
||||
name: *const u8,
|
||||
name_len: usize,
|
||||
item: &mut MaybeUninit<wasmtime_extern_t>,
|
||||
) -> bool {
|
||||
let name = crate::slice_from_raw_parts(name, name_len);
|
||||
let name = match std::str::from_utf8(name) {
|
||||
Ok(name) => name,
|
||||
Err(_) => return false,
|
||||
};
|
||||
match instance.get_export(store, name) {
|
||||
Some(e) => {
|
||||
crate::initialize(item, e.into());
|
||||
true
|
||||
}
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasmtime_instance_export_nth(
|
||||
store: CStoreContextMut<'_>,
|
||||
instance: &Instance,
|
||||
index: usize,
|
||||
name_ptr: &mut *const u8,
|
||||
name_len: &mut usize,
|
||||
item: &mut MaybeUninit<wasmtime_extern_t>,
|
||||
) -> bool {
|
||||
match instance.exports(store).nth(index) {
|
||||
Some(e) => {
|
||||
*name_ptr = e.name().as_ptr();
|
||||
*name_len = e.name().len();
|
||||
crate::initialize(item, e.into_extern().into());
|
||||
true
|
||||
}
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
//! This file defines the extern "C" API, which is compatible with the
|
||||
//! [Wasm C API](https://github.com/WebAssembly/wasm-c-api).
|
||||
//! This crate is the implementation of Wasmtime's C API.
|
||||
//!
|
||||
//! This crate is not intended to be used from Rust itself, for that see the
|
||||
//! `wasmtime` crate. Otherwise this is typically compiled as a
|
||||
//! cdylib/staticlib. Documentation for this crate largely lives in the header
|
||||
//! files of the `include` directory for this crate.
|
||||
//!
|
||||
//! At a high level this crate implements the `wasm.h` API with some gymnastics,
|
||||
//! but otherwise an accompanying `wasmtime.h` API is provided which is more
|
||||
//! specific to Wasmtime and has fewer gymnastics to implement.
|
||||
|
||||
#![allow(non_snake_case, non_camel_case_types, non_upper_case_globals)]
|
||||
#![allow(unknown_lints)]
|
||||
#![allow(improper_ctypes_definitions)]
|
||||
|
||||
// TODO complete the C API
|
||||
|
||||
mod config;
|
||||
mod engine;
|
||||
@@ -53,18 +57,6 @@ mod wat2wasm;
|
||||
#[cfg(feature = "wat")]
|
||||
pub use crate::wat2wasm::*;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone)]
|
||||
pub struct wasm_foreign_t {
|
||||
_unused: [u8; 0],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone)]
|
||||
pub struct wasm_shared_module_t {
|
||||
_unused: [u8; 0],
|
||||
}
|
||||
|
||||
/// Initialize a `MaybeUninit<T>`
|
||||
///
|
||||
/// TODO: Replace calls to this function with
|
||||
@@ -75,3 +67,43 @@ pub(crate) fn initialize<T>(dst: &mut std::mem::MaybeUninit<T>, val: T) {
|
||||
std::ptr::write(dst.as_mut_ptr(), val);
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper for running a C-defined finalizer over some data when the Rust
|
||||
/// structure is dropped.
|
||||
pub struct ForeignData {
|
||||
data: *mut std::ffi::c_void,
|
||||
finalizer: Option<extern "C" fn(*mut std::ffi::c_void)>,
|
||||
}
|
||||
|
||||
unsafe impl Send for ForeignData {}
|
||||
unsafe impl Sync for ForeignData {}
|
||||
|
||||
impl Drop for ForeignData {
|
||||
fn drop(&mut self) {
|
||||
if let Some(f) = self.finalizer {
|
||||
f(self.data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper for creating Rust slices from C inputs.
|
||||
///
|
||||
/// This specifically disregards the `ptr` argument if the length is zero. The
|
||||
/// `ptr` in that case maybe `NULL` or invalid, and it's not valid to have a
|
||||
/// zero-length Rust slice with a `NULL` pointer.
|
||||
unsafe fn slice_from_raw_parts<'a, T>(ptr: *const T, len: usize) -> &'a [T] {
|
||||
if len == 0 {
|
||||
&[]
|
||||
} else {
|
||||
std::slice::from_raw_parts(ptr, len)
|
||||
}
|
||||
}
|
||||
|
||||
/// Same as above, but for `*_mut`
|
||||
unsafe fn slice_from_raw_parts_mut<'a, T>(ptr: *mut T, len: usize) -> &'a mut [T] {
|
||||
if len == 0 {
|
||||
&mut []
|
||||
} else {
|
||||
std::slice::from_raw_parts_mut(ptr, len)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
use crate::{bad_utf8, handle_result, wasmtime_error_t};
|
||||
use crate::{wasm_extern_t, wasm_store_t};
|
||||
use crate::{wasm_func_t, wasm_instance_t, wasm_module_t, wasm_name_t, wasm_trap_t};
|
||||
use crate::{
|
||||
bad_utf8, handle_result, wasm_engine_t, wasm_trap_t, wasmtime_error_t, wasmtime_extern_t,
|
||||
wasmtime_module_t, CStoreContextMut,
|
||||
};
|
||||
use std::mem::MaybeUninit;
|
||||
use std::str;
|
||||
use wasmtime::Linker;
|
||||
use wasmtime::{Func, Instance, Linker};
|
||||
|
||||
#[repr(C)]
|
||||
pub struct wasmtime_linker_t {
|
||||
linker: Linker,
|
||||
linker: Linker<crate::StoreData>,
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_linker_new(store: &wasm_store_t) -> Box<wasmtime_linker_t> {
|
||||
pub extern "C" fn wasmtime_linker_new(engine: &wasm_engine_t) -> Box<wasmtime_linker_t> {
|
||||
Box::new(wasmtime_linker_t {
|
||||
linker: Linker::new(&store.store),
|
||||
linker: Linker::new(&engine.engine),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -27,23 +29,28 @@ pub extern "C" fn wasmtime_linker_allow_shadowing(
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_linker_delete(_linker: Box<wasmtime_linker_t>) {}
|
||||
|
||||
macro_rules! to_str {
|
||||
($ptr:expr, $len:expr) => {
|
||||
match str::from_utf8(crate::slice_from_raw_parts($ptr, $len)) {
|
||||
Ok(s) => s,
|
||||
Err(_) => return bad_utf8(),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_linker_define(
|
||||
pub unsafe extern "C" fn wasmtime_linker_define(
|
||||
linker: &mut wasmtime_linker_t,
|
||||
module: &wasm_name_t,
|
||||
name: &wasm_name_t,
|
||||
item: &wasm_extern_t,
|
||||
module: *const u8,
|
||||
module_len: usize,
|
||||
name: *const u8,
|
||||
name_len: usize,
|
||||
item: &wasmtime_extern_t,
|
||||
) -> Option<Box<wasmtime_error_t>> {
|
||||
let linker = &mut linker.linker;
|
||||
let module = match str::from_utf8(module.as_slice()) {
|
||||
Ok(s) => s,
|
||||
Err(_) => return bad_utf8(),
|
||||
};
|
||||
let name = match str::from_utf8(name.as_slice()) {
|
||||
Ok(s) => s,
|
||||
Err(_) => return bad_utf8(),
|
||||
};
|
||||
let item = item.which.clone();
|
||||
let module = to_str!(module, module_len);
|
||||
let name = to_str!(name, name_len);
|
||||
let item = item.to_extern();
|
||||
handle_result(linker.define(module, name, item), |_linker| ())
|
||||
}
|
||||
|
||||
@@ -51,87 +58,92 @@ pub extern "C" fn wasmtime_linker_define(
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_linker_define_wasi(
|
||||
linker: &mut wasmtime_linker_t,
|
||||
instance: &crate::wasi_instance_t,
|
||||
) -> Option<Box<wasmtime_error_t>> {
|
||||
let linker = &mut linker.linker;
|
||||
handle_result(instance.add_to_linker(linker), |_linker| ())
|
||||
handle_result(
|
||||
wasmtime_wasi::add_to_linker(&mut linker.linker, |cx| cx.wasi.as_mut().unwrap()),
|
||||
|_linker| (),
|
||||
)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_linker_define_instance(
|
||||
pub unsafe extern "C" fn wasmtime_linker_define_instance(
|
||||
linker: &mut wasmtime_linker_t,
|
||||
name: &wasm_name_t,
|
||||
instance: &wasm_instance_t,
|
||||
store: CStoreContextMut<'_>,
|
||||
name: *const u8,
|
||||
name_len: usize,
|
||||
instance: &Instance,
|
||||
) -> Option<Box<wasmtime_error_t>> {
|
||||
let linker = &mut linker.linker;
|
||||
let name = match str::from_utf8(name.as_slice()) {
|
||||
Ok(s) => s,
|
||||
Err(_) => return bad_utf8(),
|
||||
};
|
||||
handle_result(linker.instance(name, instance.instance()), |_linker| ())
|
||||
let name = to_str!(name, name_len);
|
||||
handle_result(linker.instance(store, name, *instance), |_linker| ())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_linker_instantiate(
|
||||
linker: &wasmtime_linker_t,
|
||||
module: &wasm_module_t,
|
||||
instance_ptr: &mut *mut wasm_instance_t,
|
||||
store: CStoreContextMut<'_>,
|
||||
module: &wasmtime_module_t,
|
||||
instance_ptr: &mut Instance,
|
||||
trap_ptr: &mut *mut wasm_trap_t,
|
||||
) -> Option<Box<wasmtime_error_t>> {
|
||||
let result = linker.linker.instantiate(module.module());
|
||||
let result = linker.linker.instantiate(store, &module.module);
|
||||
super::instance::handle_instantiate(result, instance_ptr, trap_ptr)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_linker_module(
|
||||
pub unsafe extern "C" fn wasmtime_linker_module(
|
||||
linker: &mut wasmtime_linker_t,
|
||||
name: &wasm_name_t,
|
||||
module: &wasm_module_t,
|
||||
store: CStoreContextMut<'_>,
|
||||
name: *const u8,
|
||||
name_len: usize,
|
||||
module: &wasmtime_module_t,
|
||||
) -> Option<Box<wasmtime_error_t>> {
|
||||
let linker = &mut linker.linker;
|
||||
let name = match str::from_utf8(name.as_slice()) {
|
||||
Ok(s) => s,
|
||||
Err(_) => return bad_utf8(),
|
||||
};
|
||||
handle_result(linker.module(name, module.module()), |_linker| ())
|
||||
let name = to_str!(name, name_len);
|
||||
handle_result(linker.module(store, name, &module.module), |_linker| ())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_linker_get_default(
|
||||
pub unsafe extern "C" fn wasmtime_linker_get_default(
|
||||
linker: &wasmtime_linker_t,
|
||||
name: &wasm_name_t,
|
||||
func: &mut *mut wasm_func_t,
|
||||
store: CStoreContextMut<'_>,
|
||||
name: *const u8,
|
||||
name_len: usize,
|
||||
func: &mut Func,
|
||||
) -> Option<Box<wasmtime_error_t>> {
|
||||
let linker = &linker.linker;
|
||||
let name = match str::from_utf8(name.as_slice()) {
|
||||
Ok(s) => s,
|
||||
Err(_) => return bad_utf8(),
|
||||
};
|
||||
handle_result(linker.get_default(name), |f| {
|
||||
*func = Box::into_raw(Box::new(f.into()))
|
||||
})
|
||||
let name = to_str!(name, name_len);
|
||||
handle_result(linker.get_default(store, name), |f| *func = f)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_linker_get_one_by_name(
|
||||
pub unsafe extern "C" fn wasmtime_linker_get(
|
||||
linker: &wasmtime_linker_t,
|
||||
module: &wasm_name_t,
|
||||
name: Option<&wasm_name_t>,
|
||||
item_ptr: &mut *mut wasm_extern_t,
|
||||
) -> Option<Box<wasmtime_error_t>> {
|
||||
store: CStoreContextMut<'_>,
|
||||
module: *const u8,
|
||||
module_len: usize,
|
||||
name: *const u8,
|
||||
name_len: usize,
|
||||
item_ptr: &mut MaybeUninit<wasmtime_extern_t>,
|
||||
) -> bool {
|
||||
let linker = &linker.linker;
|
||||
let module = match str::from_utf8(module.as_slice()) {
|
||||
let module = match str::from_utf8(crate::slice_from_raw_parts(module, module_len)) {
|
||||
Ok(s) => s,
|
||||
Err(_) => return bad_utf8(),
|
||||
Err(_) => return false,
|
||||
};
|
||||
let name = match name {
|
||||
Some(name) => match str::from_utf8(name.as_slice()) {
|
||||
let name = if name.is_null() {
|
||||
None
|
||||
} else {
|
||||
match str::from_utf8(crate::slice_from_raw_parts(name, name_len)) {
|
||||
Ok(s) => Some(s),
|
||||
Err(_) => return bad_utf8(),
|
||||
},
|
||||
None => None,
|
||||
Err(_) => return false,
|
||||
}
|
||||
};
|
||||
handle_result(linker.get_one_by_name(module, name), |which| {
|
||||
*item_ptr = Box::into_raw(Box::new(wasm_extern_t { which }))
|
||||
})
|
||||
match linker.get(store, module, name) {
|
||||
Some(which) => {
|
||||
crate::initialize(item_ptr, which.into());
|
||||
true
|
||||
}
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
use crate::{wasm_extern_t, wasm_memorytype_t, wasm_store_t};
|
||||
use crate::{
|
||||
handle_result, wasm_extern_t, wasm_memorytype_t, wasm_store_t, wasmtime_error_t, CStoreContext,
|
||||
CStoreContextMut,
|
||||
};
|
||||
use wasmtime::{Extern, Memory};
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -19,8 +22,8 @@ impl wasm_memory_t {
|
||||
}
|
||||
}
|
||||
|
||||
fn memory(&self) -> &Memory {
|
||||
match &self.ext.which {
|
||||
fn memory(&self) -> Memory {
|
||||
match self.ext.which {
|
||||
Extern::Memory(m) => m,
|
||||
_ => unsafe { std::hint::unreachable_unchecked() },
|
||||
}
|
||||
@@ -28,45 +31,98 @@ impl wasm_memory_t {
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_memory_new(
|
||||
store: &wasm_store_t,
|
||||
pub unsafe extern "C" fn wasm_memory_new(
|
||||
store: &mut wasm_store_t,
|
||||
mt: &wasm_memorytype_t,
|
||||
) -> Option<Box<wasm_memory_t>> {
|
||||
let memory = Memory::new(&store.store, mt.ty().ty.clone()).ok()?;
|
||||
let memory = Memory::new(store.store.context_mut(), mt.ty().ty.clone()).ok()?;
|
||||
Some(Box::new(wasm_memory_t {
|
||||
ext: wasm_extern_t {
|
||||
store: store.store.clone(),
|
||||
which: memory.into(),
|
||||
},
|
||||
}))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_memory_as_extern(m: &wasm_memory_t) -> &wasm_extern_t {
|
||||
pub extern "C" fn wasm_memory_as_extern(m: &mut wasm_memory_t) -> &mut wasm_extern_t {
|
||||
&mut m.ext
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_memory_as_extern_const(m: &wasm_memory_t) -> &wasm_extern_t {
|
||||
&m.ext
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_memory_type(m: &wasm_memory_t) -> Box<wasm_memorytype_t> {
|
||||
let ty = m.memory().ty();
|
||||
pub unsafe extern "C" fn wasm_memory_type(m: &wasm_memory_t) -> Box<wasm_memorytype_t> {
|
||||
let ty = m.memory().ty(m.ext.store.context());
|
||||
Box::new(wasm_memorytype_t::new(ty))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_memory_data(m: &wasm_memory_t) -> *mut u8 {
|
||||
m.memory().data_ptr()
|
||||
pub unsafe extern "C" fn wasm_memory_data(m: &wasm_memory_t) -> *mut u8 {
|
||||
m.memory().data_ptr(m.ext.store.context())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_memory_data_size(m: &wasm_memory_t) -> usize {
|
||||
m.memory().data_size()
|
||||
pub unsafe extern "C" fn wasm_memory_data_size(m: &wasm_memory_t) -> usize {
|
||||
m.memory().data_size(m.ext.store.context())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_memory_size(m: &wasm_memory_t) -> wasm_memory_pages_t {
|
||||
m.memory().size()
|
||||
pub unsafe extern "C" fn wasm_memory_size(m: &wasm_memory_t) -> wasm_memory_pages_t {
|
||||
m.memory().size(m.ext.store.context())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_memory_grow(m: &wasm_memory_t, delta: wasm_memory_pages_t) -> bool {
|
||||
m.memory().grow(delta).is_ok()
|
||||
pub unsafe extern "C" fn wasm_memory_grow(
|
||||
m: &mut wasm_memory_t,
|
||||
delta: wasm_memory_pages_t,
|
||||
) -> bool {
|
||||
let memory = m.memory();
|
||||
let mut store = m.ext.store.context_mut();
|
||||
memory.grow(&mut store, delta).is_ok()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_memory_new(
|
||||
store: CStoreContextMut<'_>,
|
||||
ty: &wasm_memorytype_t,
|
||||
ret: &mut Memory,
|
||||
) -> Option<Box<wasmtime_error_t>> {
|
||||
handle_result(Memory::new(store, ty.ty().ty.clone()), |mem| *ret = mem)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_memory_type(
|
||||
store: CStoreContext<'_>,
|
||||
mem: &Memory,
|
||||
) -> Box<wasm_memorytype_t> {
|
||||
Box::new(wasm_memorytype_t::new(mem.ty(store)))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_memory_data(store: CStoreContext<'_>, mem: &Memory) -> *const u8 {
|
||||
mem.data(store).as_ptr()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_memory_data_size(store: CStoreContext<'_>, mem: &Memory) -> usize {
|
||||
mem.data(store).len()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_memory_size(store: CStoreContext<'_>, mem: &Memory) -> u32 {
|
||||
mem.size(store)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_memory_grow(
|
||||
store: CStoreContextMut<'_>,
|
||||
mem: &Memory,
|
||||
delta: u32,
|
||||
prev_size: &mut u32,
|
||||
) -> Option<Box<wasmtime_error_t>> {
|
||||
handle_result(mem.grow(store, delta), |prev| *prev_size = prev)
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
use crate::{
|
||||
handle_result, wasm_byte_vec_t, wasm_engine_t, wasm_exporttype_t, wasm_exporttype_vec_t,
|
||||
wasm_extern_t, wasm_importtype_t, wasm_importtype_vec_t, wasm_moduletype_t, wasm_store_t,
|
||||
wasmtime_error_t,
|
||||
wasm_extern_t, wasm_importtype_t, wasm_importtype_vec_t, wasm_store_t, wasmtime_error_t,
|
||||
wasmtime_moduletype_t, StoreRef,
|
||||
};
|
||||
use std::ptr;
|
||||
use wasmtime::{Engine, Extern, Module};
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -15,9 +14,10 @@ pub struct wasm_module_t {
|
||||
wasmtime_c_api_macros::declare_ref!(wasm_module_t);
|
||||
|
||||
impl wasm_module_t {
|
||||
pub(crate) fn new(module: Module) -> wasm_module_t {
|
||||
pub(crate) fn new(store: StoreRef, module: Module) -> wasm_module_t {
|
||||
wasm_module_t {
|
||||
ext: wasm_extern_t {
|
||||
store: store,
|
||||
which: module.into(),
|
||||
},
|
||||
}
|
||||
@@ -47,48 +47,22 @@ pub struct wasm_shared_module_t {
|
||||
wasmtime_c_api_macros::declare_own!(wasm_shared_module_t);
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_module_new(
|
||||
store: &wasm_store_t,
|
||||
pub unsafe extern "C" fn wasm_module_new(
|
||||
store: &mut wasm_store_t,
|
||||
binary: &wasm_byte_vec_t,
|
||||
) -> Option<Box<wasm_module_t>> {
|
||||
let mut ret = ptr::null_mut();
|
||||
let engine = wasm_engine_t {
|
||||
engine: store.store.engine().clone(),
|
||||
};
|
||||
match wasmtime_module_new(&engine, binary, &mut ret) {
|
||||
Some(_err) => None,
|
||||
None => {
|
||||
assert!(!ret.is_null());
|
||||
Some(unsafe { Box::from_raw(ret) })
|
||||
}
|
||||
match Module::from_binary(store.store.context().engine(), binary.as_slice()) {
|
||||
Ok(module) => Some(Box::new(wasm_module_t::new(store.store.clone(), module))),
|
||||
Err(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_module_new(
|
||||
engine: &wasm_engine_t,
|
||||
pub unsafe extern "C" fn wasm_module_validate(
|
||||
store: &mut wasm_store_t,
|
||||
binary: &wasm_byte_vec_t,
|
||||
ret: &mut *mut wasm_module_t,
|
||||
) -> Option<Box<wasmtime_error_t>> {
|
||||
let binary = binary.as_slice();
|
||||
handle_result(Module::from_binary(&engine.engine, binary), |module| {
|
||||
let module = Box::new(wasm_module_t::new(module));
|
||||
*ret = Box::into_raw(module);
|
||||
})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_module_validate(store: &wasm_store_t, binary: &wasm_byte_vec_t) -> bool {
|
||||
wasmtime_module_validate(store, binary).is_none()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_module_validate(
|
||||
store: &wasm_store_t,
|
||||
binary: &wasm_byte_vec_t,
|
||||
) -> Option<Box<wasmtime_error_t>> {
|
||||
let binary = binary.as_slice();
|
||||
handle_result(Module::validate(store.store.engine(), binary), |()| {})
|
||||
) -> bool {
|
||||
Module::validate(store.store.context().engine(), binary.as_slice()).is_ok()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -135,66 +109,96 @@ pub extern "C" fn wasm_module_share(module: &wasm_module_t) -> Box<wasm_shared_m
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_module_obtain(
|
||||
store: &wasm_store_t,
|
||||
pub unsafe extern "C" fn wasm_module_obtain(
|
||||
store: &mut wasm_store_t,
|
||||
shared_module: &wasm_shared_module_t,
|
||||
) -> Option<Box<wasm_module_t>> {
|
||||
let module = shared_module.module.clone();
|
||||
if !Engine::same(store.store.engine(), module.engine()) {
|
||||
return None;
|
||||
if Engine::same(store.store.context().engine(), module.engine()) {
|
||||
Some(Box::new(wasm_module_t::new(store.store.clone(), module)))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
Some(Box::new(wasm_module_t::new(module)))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_module_serialize(module: &wasm_module_t, ret: &mut wasm_byte_vec_t) {
|
||||
drop(wasmtime_module_serialize(module, ret));
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_module_deserialize(
|
||||
store: &wasm_store_t,
|
||||
binary: &wasm_byte_vec_t,
|
||||
) -> Option<Box<wasm_module_t>> {
|
||||
let mut ret = ptr::null_mut();
|
||||
let engine = wasm_engine_t {
|
||||
engine: store.store.engine().clone(),
|
||||
};
|
||||
match wasmtime_module_deserialize(&engine, binary, &mut ret) {
|
||||
Some(_err) => None,
|
||||
None => {
|
||||
assert!(!ret.is_null());
|
||||
Some(unsafe { Box::from_raw(ret) })
|
||||
}
|
||||
if let Ok(buf) = module.module().serialize() {
|
||||
ret.set_buffer(buf);
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_module_serialize(
|
||||
module: &wasm_module_t,
|
||||
ret: &mut wasm_byte_vec_t,
|
||||
) -> Option<Box<wasmtime_error_t>> {
|
||||
handle_result(module.module().serialize(), |buf| {
|
||||
ret.set_buffer(buf);
|
||||
})
|
||||
pub unsafe extern "C" fn wasm_module_deserialize(
|
||||
store: &mut wasm_store_t,
|
||||
binary: &wasm_byte_vec_t,
|
||||
) -> Option<Box<wasm_module_t>> {
|
||||
match Module::deserialize(store.store.context().engine(), binary.as_slice()) {
|
||||
Ok(module) => Some(Box::new(wasm_module_t::new(store.store.clone(), module))),
|
||||
Err(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct wasmtime_module_t {
|
||||
pub(crate) module: Module,
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_module_deserialize(
|
||||
pub unsafe extern "C" fn wasmtime_module_new(
|
||||
engine: &wasm_engine_t,
|
||||
binary: &wasm_byte_vec_t,
|
||||
ret: &mut *mut wasm_module_t,
|
||||
wasm: *const u8,
|
||||
len: usize,
|
||||
out: &mut *mut wasmtime_module_t,
|
||||
) -> Option<Box<wasmtime_error_t>> {
|
||||
handle_result(
|
||||
unsafe { Module::deserialize(&engine.engine, binary.as_slice()) },
|
||||
Module::from_binary(&engine.engine, crate::slice_from_raw_parts(wasm, len)),
|
||||
|module| {
|
||||
let module = Box::new(wasm_module_t::new(module));
|
||||
*ret = Box::into_raw(module);
|
||||
*out = Box::into_raw(Box::new(wasmtime_module_t { module }));
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_module_type(f: &wasm_module_t) -> Box<wasm_moduletype_t> {
|
||||
Box::new(wasm_moduletype_t::new(f.module().ty()))
|
||||
pub extern "C" fn wasmtime_module_delete(_module: Box<wasmtime_module_t>) {}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_module_clone(module: &wasmtime_module_t) -> Box<wasmtime_module_t> {
|
||||
Box::new(module.clone())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasmtime_module_validate(
|
||||
engine: &wasm_engine_t,
|
||||
wasm: *const u8,
|
||||
len: usize,
|
||||
) -> Option<Box<wasmtime_error_t>> {
|
||||
let binary = crate::slice_from_raw_parts(wasm, len);
|
||||
handle_result(Module::validate(&engine.engine, binary), |()| {})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_module_type(m: &wasmtime_module_t) -> Box<wasmtime_moduletype_t> {
|
||||
Box::new(wasmtime_moduletype_t::new(m.module.ty()))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_module_serialize(
|
||||
module: &wasmtime_module_t,
|
||||
ret: &mut wasm_byte_vec_t,
|
||||
) -> Option<Box<wasmtime_error_t>> {
|
||||
handle_result(module.module.serialize(), |buf| ret.set_buffer(buf))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasmtime_module_deserialize(
|
||||
engine: &wasm_engine_t,
|
||||
bytes: *const u8,
|
||||
len: usize,
|
||||
out: &mut *mut wasmtime_module_t,
|
||||
) -> Option<Box<wasmtime_error_t>> {
|
||||
let bytes = crate::slice_from_raw_parts(bytes, len);
|
||||
handle_result(Module::deserialize(&engine.engine, bytes), |module| {
|
||||
*out = Box::into_raw(Box::new(wasmtime_module_t { module }));
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
use crate::wasm_val_t;
|
||||
use std::any::Any;
|
||||
use std::mem::MaybeUninit;
|
||||
use std::os::raw::c_void;
|
||||
use std::ptr;
|
||||
use wasmtime::{ExternRef, Func, Val};
|
||||
|
||||
/// `*mut wasm_ref_t` is a reference type (`externref` or `funcref`), as seen by
|
||||
@@ -54,6 +50,11 @@ pub extern "C" fn wasm_ref_copy(r: Option<&wasm_ref_t>) -> Option<Box<wasm_ref_t
|
||||
r.map(|r| Box::new(r.clone()))
|
||||
}
|
||||
|
||||
fn abort(name: &str) -> ! {
|
||||
eprintln!("`{}` is not implemented", name);
|
||||
std::process::abort();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_ref_same(a: Option<&wasm_ref_t>, b: Option<&wasm_ref_t>) -> bool {
|
||||
match (a.map(|a| &a.r), b.map(|b| &b.r)) {
|
||||
@@ -72,8 +73,7 @@ pub extern "C" fn wasm_ref_get_host_info(_ref: Option<&wasm_ref_t>) -> *mut c_vo
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_ref_set_host_info(_ref: Option<&wasm_ref_t>, _info: *mut c_void) {
|
||||
eprintln!("`wasm_ref_set_host_info` is not implemented");
|
||||
std::process::abort();
|
||||
abort("wasm_ref_set_host_info")
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -82,63 +82,162 @@ pub extern "C" fn wasm_ref_set_host_info_with_finalizer(
|
||||
_info: *mut c_void,
|
||||
_finalizer: Option<extern "C" fn(*mut c_void)>,
|
||||
) {
|
||||
eprintln!("`wasm_ref_set_host_info_with_finalizer` is not implemented");
|
||||
std::process::abort();
|
||||
}
|
||||
|
||||
type wasmtime_externref_finalizer_t = extern "C" fn(*mut c_void);
|
||||
|
||||
struct CExternRef {
|
||||
data: *mut c_void,
|
||||
finalizer: Option<wasmtime_externref_finalizer_t>,
|
||||
}
|
||||
|
||||
impl Drop for CExternRef {
|
||||
fn drop(&mut self) {
|
||||
if let Some(f) = self.finalizer {
|
||||
f(self.data);
|
||||
}
|
||||
}
|
||||
abort("wasm_ref_set_host_info_with_finalizer")
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_externref_new(data: *mut c_void, valp: &mut MaybeUninit<wasm_val_t>) {
|
||||
wasmtime_externref_new_with_finalizer(data, None, valp)
|
||||
pub extern "C" fn wasm_ref_as_extern(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_extern_t> {
|
||||
abort("wasm_ref_as_extern")
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_externref_new_with_finalizer(
|
||||
data: *mut c_void,
|
||||
finalizer: Option<wasmtime_externref_finalizer_t>,
|
||||
valp: &mut MaybeUninit<wasm_val_t>,
|
||||
pub extern "C" fn wasm_ref_as_extern_const(
|
||||
_ref: Option<&wasm_ref_t>,
|
||||
) -> Option<&crate::wasm_extern_t> {
|
||||
abort("wasm_ref_as_extern_const")
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_ref_as_foreign(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_foreign_t> {
|
||||
abort("wasm_ref_as_foreign")
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_ref_as_foreign_const(
|
||||
_ref: Option<&wasm_ref_t>,
|
||||
) -> Option<&crate::wasm_foreign_t> {
|
||||
abort("wasm_ref_as_foreign_const")
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_ref_as_func(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_func_t> {
|
||||
abort("wasm_ref_as_func")
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_ref_as_func_const(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_func_t> {
|
||||
abort("wasm_ref_as_func_const")
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_ref_as_global(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_global_t> {
|
||||
abort("wasm_ref_as_global")
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_ref_as_global_const(
|
||||
_ref: Option<&wasm_ref_t>,
|
||||
) -> Option<&crate::wasm_global_t> {
|
||||
abort("wasm_ref_as_global_const")
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_ref_as_instance(
|
||||
_ref: Option<&wasm_ref_t>,
|
||||
) -> Option<&crate::wasm_instance_t> {
|
||||
abort("wasm_ref_as_instance")
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_ref_as_instance_const(
|
||||
_ref: Option<&wasm_ref_t>,
|
||||
) -> Option<&crate::wasm_instance_t> {
|
||||
abort("wasm_ref_as_instance_const")
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_ref_as_memory(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_memory_t> {
|
||||
abort("wasm_ref_as_memory")
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_ref_as_memory_const(
|
||||
_ref: Option<&wasm_ref_t>,
|
||||
) -> Option<&crate::wasm_memory_t> {
|
||||
abort("wasm_ref_as_memory_const")
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_ref_as_module(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_module_t> {
|
||||
abort("wasm_ref_as_module")
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_ref_as_module_const(
|
||||
_ref: Option<&wasm_ref_t>,
|
||||
) -> Option<&crate::wasm_module_t> {
|
||||
abort("wasm_ref_as_module_const")
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_ref_as_table(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_table_t> {
|
||||
abort("wasm_ref_as_table")
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_ref_as_table_const(
|
||||
_ref: Option<&wasm_ref_t>,
|
||||
) -> Option<&crate::wasm_table_t> {
|
||||
abort("wasm_ref_as_table_const")
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_ref_as_trap(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_trap_t> {
|
||||
abort("wasm_ref_as_trap")
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_ref_as_trap_const(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_trap_t> {
|
||||
abort("wasm_ref_as_trap_const")
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
#[repr(C)]
|
||||
pub struct wasm_foreign_t {}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_foreign_new(_store: &crate::wasm_store_t) -> Box<wasm_foreign_t> {
|
||||
abort("wasm_foreign_new")
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_foreign_delete(_foreign: Box<wasm_foreign_t>) {}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_foreign_copy(r: &wasm_foreign_t) -> Box<wasm_foreign_t> {
|
||||
Box::new(r.clone())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_foreign_same(_a: &wasm_foreign_t, _b: &wasm_foreign_t) -> bool {
|
||||
abort("wasm_foreign_same")
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_foreign_get_host_info(_foreign: &wasm_foreign_t) -> *mut c_void {
|
||||
std::ptr::null_mut()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_foreign_set_host_info(_foreign: &wasm_foreign_t, _info: *mut c_void) {
|
||||
abort("wasm_foreign_set_host_info")
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_foreign_set_host_info_with_finalizer(
|
||||
_foreign: &wasm_foreign_t,
|
||||
_info: *mut c_void,
|
||||
_finalizer: Option<extern "C" fn(*mut c_void)>,
|
||||
) {
|
||||
crate::initialize(
|
||||
valp,
|
||||
wasm_val_t::from_val(Val::ExternRef(Some(ExternRef::new(CExternRef {
|
||||
data,
|
||||
finalizer,
|
||||
})))),
|
||||
);
|
||||
abort("wasm_foreign_set_host_info_with_finalizer")
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_externref_data(
|
||||
val: &wasm_val_t,
|
||||
datap: &mut MaybeUninit<*mut c_void>,
|
||||
) -> bool {
|
||||
match val.val() {
|
||||
Val::ExternRef(None) => {
|
||||
crate::initialize(datap, ptr::null_mut());
|
||||
true
|
||||
}
|
||||
Val::ExternRef(Some(x)) => {
|
||||
let data = match x.data().downcast_ref::<CExternRef>() {
|
||||
Some(r) => r.data,
|
||||
None => x.data() as *const dyn Any as *mut c_void,
|
||||
};
|
||||
crate::initialize(datap, data);
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
pub extern "C" fn wasm_foreign_as_ref(_: &wasm_foreign_t) -> &wasm_ref_t {
|
||||
abort("wasm_foreign_as_ref")
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_foreign_as_ref_const(_: &wasm_foreign_t) -> Option<&wasm_ref_t> {
|
||||
abort("wasm_foreign_as_ref_const")
|
||||
}
|
||||
|
||||
@@ -1,10 +1,38 @@
|
||||
use crate::{wasm_engine_t, wasmtime_error_t};
|
||||
use wasmtime::{InterruptHandle, Store};
|
||||
use crate::{wasm_engine_t, wasmtime_error_t, ForeignData};
|
||||
use std::cell::UnsafeCell;
|
||||
use std::ffi::c_void;
|
||||
use std::sync::Arc;
|
||||
use wasmtime::{AsContext, AsContextMut, InterruptHandle, Store, StoreContext, StoreContextMut};
|
||||
|
||||
/// This representation of a `Store` is used to implement the `wasm.h` API.
|
||||
///
|
||||
/// This is stored alongside `Func` and such for `wasm.h` so each object is
|
||||
/// independently owned. The usage of `Arc` here is mostly to just get it to be
|
||||
/// safe to drop across multiple threads, but otherwise acquiring the `context`
|
||||
/// values from this struct is considered unsafe due to it being unknown how the
|
||||
/// aliasing is working on the C side of things.
|
||||
///
|
||||
/// The aliasing requirements are documented in the C API `wasm.h` itself (at
|
||||
/// least Wasmtime's implementation).
|
||||
#[derive(Clone)]
|
||||
pub struct StoreRef {
|
||||
store: Arc<UnsafeCell<Store<()>>>,
|
||||
}
|
||||
|
||||
impl StoreRef {
|
||||
pub unsafe fn context(&self) -> StoreContext<'_, ()> {
|
||||
(*self.store.get()).as_context()
|
||||
}
|
||||
|
||||
pub unsafe fn context_mut(&mut self) -> StoreContextMut<'_, ()> {
|
||||
(*self.store.get()).as_context_mut()
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone)]
|
||||
pub struct wasm_store_t {
|
||||
pub(crate) store: Store,
|
||||
pub(crate) store: StoreRef,
|
||||
}
|
||||
|
||||
wasmtime_c_api_macros::declare_own!(wasm_store_t);
|
||||
@@ -12,14 +40,104 @@ wasmtime_c_api_macros::declare_own!(wasm_store_t);
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_store_new(engine: &wasm_engine_t) -> Box<wasm_store_t> {
|
||||
let engine = &engine.engine;
|
||||
let store = Store::new(engine, ());
|
||||
Box::new(wasm_store_t {
|
||||
store: Store::new(&engine),
|
||||
store: StoreRef {
|
||||
store: Arc::new(UnsafeCell::new(store)),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
/// Representation of a `Store` for `wasmtime.h` This notably tries to move more
|
||||
/// burden of aliasing on the caller rather than internally, allowing for a more
|
||||
/// raw representation of contexts and such that requires less `unsafe` in the
|
||||
/// implementation.
|
||||
///
|
||||
/// Note that this notably carries `StoreData` as a payload which allows storing
|
||||
/// foreign data and configuring WASI as well.
|
||||
#[repr(C)]
|
||||
pub struct wasmtime_store_t {
|
||||
pub(crate) store: Store<StoreData>,
|
||||
}
|
||||
|
||||
pub type CStoreContext<'a> = StoreContext<'a, StoreData>;
|
||||
pub type CStoreContextMut<'a> = StoreContextMut<'a, StoreData>;
|
||||
|
||||
pub struct StoreData {
|
||||
foreign: crate::ForeignData,
|
||||
#[cfg(feature = "wasi")]
|
||||
pub(crate) wasi: Option<wasmtime_wasi::WasiCtx>,
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_store_delete(_: Box<wasmtime_store_t>) {}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_store_new(
|
||||
engine: &wasm_engine_t,
|
||||
data: *mut c_void,
|
||||
finalizer: Option<extern "C" fn(*mut c_void)>,
|
||||
) -> Box<wasmtime_store_t> {
|
||||
Box::new(wasmtime_store_t {
|
||||
store: Store::new(
|
||||
&engine.engine,
|
||||
StoreData {
|
||||
foreign: ForeignData { data, finalizer },
|
||||
#[cfg(feature = "wasi")]
|
||||
wasi: None,
|
||||
},
|
||||
),
|
||||
})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_store_gc(store: &wasm_store_t) {
|
||||
store.store.gc();
|
||||
pub extern "C" fn wasmtime_store_context(store: &mut wasmtime_store_t) -> CStoreContextMut<'_> {
|
||||
store.store.as_context_mut()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_context_get_data(store: CStoreContext<'_>) -> *mut c_void {
|
||||
store.data().foreign.data
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_context_set_data(mut store: CStoreContextMut<'_>, data: *mut c_void) {
|
||||
store.data_mut().foreign.data = data;
|
||||
}
|
||||
|
||||
#[cfg(feature = "wasi")]
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_context_set_wasi(
|
||||
mut context: CStoreContextMut<'_>,
|
||||
wasi: Box<crate::wasi_config_t>,
|
||||
) -> Option<Box<wasmtime_error_t>> {
|
||||
crate::handle_result(wasi.into_wasi_ctx(), |wasi| {
|
||||
context.data_mut().wasi = Some(wasi);
|
||||
})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_context_gc(mut context: CStoreContextMut<'_>) {
|
||||
context.gc();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_context_add_fuel(
|
||||
mut store: CStoreContextMut<'_>,
|
||||
fuel: u64,
|
||||
) -> Option<Box<wasmtime_error_t>> {
|
||||
crate::handle_result(store.add_fuel(fuel), |()| {})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_context_fuel_consumed(store: CStoreContext<'_>, fuel: &mut u64) -> bool {
|
||||
match store.fuel_consumed() {
|
||||
Some(amt) => {
|
||||
*fuel = amt;
|
||||
true
|
||||
}
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
@@ -27,14 +145,12 @@ pub struct wasmtime_interrupt_handle_t {
|
||||
handle: InterruptHandle,
|
||||
}
|
||||
|
||||
wasmtime_c_api_macros::declare_own!(wasmtime_interrupt_handle_t);
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_interrupt_handle_new(
|
||||
store: &wasm_store_t,
|
||||
store: CStoreContext<'_>,
|
||||
) -> Option<Box<wasmtime_interrupt_handle_t>> {
|
||||
Some(Box::new(wasmtime_interrupt_handle_t {
|
||||
handle: store.store.interrupt_handle().ok()?,
|
||||
handle: store.interrupt_handle().ok()?,
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -44,20 +160,4 @@ pub extern "C" fn wasmtime_interrupt_handle_interrupt(handle: &wasmtime_interrup
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_store_add_fuel(
|
||||
store: &wasm_store_t,
|
||||
fuel: u64,
|
||||
) -> Option<Box<wasmtime_error_t>> {
|
||||
crate::handle_result(store.store.add_fuel(fuel), |()| {})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_store_fuel_consumed(store: &wasm_store_t, fuel: &mut u64) -> bool {
|
||||
match store.store.fuel_consumed() {
|
||||
Some(amt) => {
|
||||
*fuel = amt;
|
||||
true
|
||||
}
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
pub extern "C" fn wasmtime_interrupt_handle_delete(_: Box<wasmtime_interrupt_handle_t>) {}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
use crate::r#ref::{ref_to_val, val_into_ref};
|
||||
use crate::{handle_result, wasm_func_t, wasm_ref_t, wasmtime_error_t};
|
||||
use crate::{wasm_extern_t, wasm_store_t, wasm_tabletype_t};
|
||||
use std::ptr;
|
||||
use crate::{
|
||||
handle_result, wasm_extern_t, wasm_ref_t, wasm_store_t, wasm_tabletype_t, wasmtime_error_t,
|
||||
wasmtime_val_t, CStoreContext, CStoreContextMut,
|
||||
};
|
||||
use std::mem::MaybeUninit;
|
||||
use wasmtime::{Extern, Table, TableType, Val, ValType};
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -22,8 +24,8 @@ impl wasm_table_t {
|
||||
}
|
||||
}
|
||||
|
||||
fn table(&self) -> &Table {
|
||||
match &self.ext.which {
|
||||
fn table(&self) -> Table {
|
||||
match self.ext.which {
|
||||
Extern::Table(t) => t,
|
||||
_ => unsafe { std::hint::unreachable_unchecked() },
|
||||
}
|
||||
@@ -42,135 +44,138 @@ fn ref_to_val_for_table(r: Option<&wasm_ref_t>, table_ty: &TableType) -> Val {
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_table_new(
|
||||
store: &wasm_store_t,
|
||||
pub unsafe extern "C" fn wasm_table_new(
|
||||
store: &mut wasm_store_t,
|
||||
tt: &wasm_tabletype_t,
|
||||
init: Option<&wasm_ref_t>,
|
||||
) -> Option<Box<wasm_table_t>> {
|
||||
let init = ref_to_val_for_table(init, &tt.ty().ty);
|
||||
let table = Table::new(&store.store, tt.ty().ty.clone(), init).ok()?;
|
||||
let table = Table::new(store.store.context_mut(), tt.ty().ty.clone(), init).ok()?;
|
||||
Some(Box::new(wasm_table_t {
|
||||
ext: wasm_extern_t {
|
||||
store: store.store.clone(),
|
||||
which: table.into(),
|
||||
},
|
||||
}))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_funcref_table_new(
|
||||
store: &wasm_store_t,
|
||||
tt: &wasm_tabletype_t,
|
||||
init: Option<&wasm_func_t>,
|
||||
out: &mut *mut wasm_table_t,
|
||||
) -> Option<Box<wasmtime_error_t>> {
|
||||
let init: Val = match init {
|
||||
Some(val) => Val::FuncRef(Some(val.func().clone())),
|
||||
None => Val::FuncRef(None),
|
||||
};
|
||||
handle_result(
|
||||
Table::new(&store.store, tt.ty().ty.clone(), init),
|
||||
|table| {
|
||||
*out = Box::into_raw(Box::new(wasm_table_t {
|
||||
ext: wasm_extern_t {
|
||||
which: table.into(),
|
||||
},
|
||||
}));
|
||||
},
|
||||
)
|
||||
pub unsafe extern "C" fn wasm_table_type(t: &wasm_table_t) -> Box<wasm_tabletype_t> {
|
||||
let table = t.table();
|
||||
let store = t.ext.store.context();
|
||||
Box::new(wasm_tabletype_t::new(table.ty(&store)))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_table_type(t: &wasm_table_t) -> Box<wasm_tabletype_t> {
|
||||
let ty = t.table().ty();
|
||||
Box::new(wasm_tabletype_t::new(ty))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_table_get(
|
||||
t: &wasm_table_t,
|
||||
pub unsafe extern "C" fn wasm_table_get(
|
||||
t: &mut wasm_table_t,
|
||||
index: wasm_table_size_t,
|
||||
) -> Option<Box<wasm_ref_t>> {
|
||||
let val = t.table().get(index)?;
|
||||
let table = t.table();
|
||||
let val = table.get(t.ext.store.context_mut(), index)?;
|
||||
val_into_ref(val)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_funcref_table_get(
|
||||
t: &wasm_table_t,
|
||||
index: wasm_table_size_t,
|
||||
ptr: &mut *mut wasm_func_t,
|
||||
) -> bool {
|
||||
match t.table().get(index) {
|
||||
Some(val) => {
|
||||
*ptr = match val {
|
||||
Val::FuncRef(None) => ptr::null_mut(),
|
||||
Val::FuncRef(Some(f)) => Box::into_raw(Box::new(f.into())),
|
||||
_ => return false,
|
||||
};
|
||||
}
|
||||
|
||||
_ => return false,
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_table_set(
|
||||
t: &wasm_table_t,
|
||||
t: &mut wasm_table_t,
|
||||
index: wasm_table_size_t,
|
||||
r: Option<&wasm_ref_t>,
|
||||
) -> bool {
|
||||
let val = ref_to_val_for_table(r, &t.table().ty());
|
||||
t.table().set(index, val).is_ok()
|
||||
let table = t.table();
|
||||
let val = ref_to_val_for_table(r, &table.ty(t.ext.store.context()));
|
||||
table.set(t.ext.store.context_mut(), index, val).is_ok()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_funcref_table_set(
|
||||
t: &wasm_table_t,
|
||||
index: wasm_table_size_t,
|
||||
val: Option<&wasm_func_t>,
|
||||
) -> Option<Box<wasmtime_error_t>> {
|
||||
let val = match val {
|
||||
Some(val) => Val::FuncRef(Some(val.func().clone())),
|
||||
None => Val::FuncRef(None),
|
||||
};
|
||||
handle_result(t.table().set(index, val), |()| {})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_table_size(t: &wasm_table_t) -> wasm_table_size_t {
|
||||
t.table().size()
|
||||
pub unsafe extern "C" fn wasm_table_size(t: &wasm_table_t) -> wasm_table_size_t {
|
||||
let table = t.table();
|
||||
let store = t.ext.store.context();
|
||||
table.size(&store)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_table_grow(
|
||||
t: &wasm_table_t,
|
||||
t: &mut wasm_table_t,
|
||||
delta: wasm_table_size_t,
|
||||
init: Option<&wasm_ref_t>,
|
||||
) -> bool {
|
||||
let init = ref_to_val_for_table(init, &t.table().ty());
|
||||
t.table().grow(delta, init).is_ok()
|
||||
let table = t.table();
|
||||
let init = ref_to_val_for_table(init, &table.ty(t.ext.store.context()));
|
||||
table.grow(t.ext.store.context_mut(), delta, init).is_ok()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_funcref_table_grow(
|
||||
t: &wasm_table_t,
|
||||
delta: wasm_table_size_t,
|
||||
init: Option<&wasm_func_t>,
|
||||
prev_size: Option<&mut wasm_table_size_t>,
|
||||
) -> Option<Box<wasmtime_error_t>> {
|
||||
let val = match init {
|
||||
Some(val) => Val::FuncRef(Some(val.func().clone())),
|
||||
None => Val::FuncRef(None),
|
||||
};
|
||||
handle_result(t.table().grow(delta, val), |prev| {
|
||||
if let Some(ptr) = prev_size {
|
||||
*ptr = prev;
|
||||
}
|
||||
})
|
||||
pub extern "C" fn wasm_table_as_extern(t: &mut wasm_table_t) -> &mut wasm_extern_t {
|
||||
&mut t.ext
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_table_as_extern(t: &wasm_table_t) -> &wasm_extern_t {
|
||||
pub extern "C" fn wasm_table_as_extern_const(t: &wasm_table_t) -> &wasm_extern_t {
|
||||
&t.ext
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasmtime_table_new(
|
||||
store: CStoreContextMut<'_>,
|
||||
tt: &wasm_tabletype_t,
|
||||
init: &wasmtime_val_t,
|
||||
out: &mut Table,
|
||||
) -> Option<Box<wasmtime_error_t>> {
|
||||
handle_result(
|
||||
Table::new(store, tt.ty().ty.clone(), init.to_val()),
|
||||
|table| *out = table,
|
||||
)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasmtime_table_type(
|
||||
store: CStoreContext<'_>,
|
||||
table: &Table,
|
||||
) -> Box<wasm_tabletype_t> {
|
||||
Box::new(wasm_tabletype_t::new(table.ty(store)))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_table_get(
|
||||
store: CStoreContextMut<'_>,
|
||||
table: &Table,
|
||||
index: u32,
|
||||
ret: &mut MaybeUninit<wasmtime_val_t>,
|
||||
) -> bool {
|
||||
match table.get(store, index) {
|
||||
Some(val) => {
|
||||
crate::initialize(ret, wasmtime_val_t::from_val(val));
|
||||
true
|
||||
}
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasmtime_table_set(
|
||||
store: CStoreContextMut<'_>,
|
||||
table: &Table,
|
||||
index: u32,
|
||||
val: &wasmtime_val_t,
|
||||
) -> Option<Box<wasmtime_error_t>> {
|
||||
handle_result(table.set(store, index, val.to_val()), |()| {})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_table_size(store: CStoreContext<'_>, table: &Table) -> u32 {
|
||||
table.size(store)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasmtime_table_grow(
|
||||
store: CStoreContextMut<'_>,
|
||||
table: &Table,
|
||||
delta: u32,
|
||||
val: &wasmtime_val_t,
|
||||
prev_size: &mut u32,
|
||||
) -> Option<Box<wasmtime_error_t>> {
|
||||
handle_result(table.grow(store, delta, val.to_val()), |prev| {
|
||||
*prev_size = prev
|
||||
})
|
||||
}
|
||||
|
||||
@@ -44,6 +44,15 @@ pub extern "C" fn wasm_trap_new(
|
||||
})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasmtime_trap_new(message: *const u8, len: usize) -> Box<wasm_trap_t> {
|
||||
let bytes = crate::slice_from_raw_parts(message, len);
|
||||
let message = String::from_utf8_lossy(&bytes);
|
||||
Box::new(wasm_trap_t {
|
||||
trap: Trap::new(message),
|
||||
})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_trap_message(trap: &wasm_trap_t, out: &mut wasm_message_t) {
|
||||
let mut buffer = Vec::new();
|
||||
@@ -136,3 +145,8 @@ pub extern "C" fn wasm_frame_instance(_arg1: *const wasm_frame_t) -> *mut wasm_i
|
||||
pub extern "C" fn wasm_frame_module_offset(frame: &wasm_frame_t) -> usize {
|
||||
frame.trap.trace()[frame.idx].module_offset()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_frame_copy(frame: &wasm_frame_t) -> Box<wasm_frame_t> {
|
||||
Box::new(frame.clone())
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::{wasm_functype_t, wasm_globaltype_t, wasm_memorytype_t, wasm_tabletype_t};
|
||||
use crate::{wasm_instancetype_t, wasm_moduletype_t};
|
||||
use crate::{wasmtime_instancetype_t, wasmtime_moduletype_t};
|
||||
use crate::{CFuncType, CGlobalType, CInstanceType, CMemoryType, CModuleType, CTableType};
|
||||
use wasmtime::ExternType;
|
||||
|
||||
@@ -123,29 +123,15 @@ pub extern "C" fn wasm_externtype_as_memorytype_const(
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_externtype_as_moduletype(
|
||||
pub extern "C" fn wasmtime_externtype_as_moduletype(
|
||||
et: &wasm_externtype_t,
|
||||
) -> Option<&wasm_moduletype_t> {
|
||||
wasm_externtype_as_moduletype_const(et)
|
||||
) -> Option<&wasmtime_moduletype_t> {
|
||||
wasmtime_moduletype_t::try_from(et)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_externtype_as_moduletype_const(
|
||||
pub extern "C" fn wasmtime_externtype_as_instancetype(
|
||||
et: &wasm_externtype_t,
|
||||
) -> Option<&wasm_moduletype_t> {
|
||||
wasm_moduletype_t::try_from(et)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_externtype_as_instancetype(
|
||||
et: &wasm_externtype_t,
|
||||
) -> Option<&wasm_instancetype_t> {
|
||||
wasm_externtype_as_instancetype_const(et)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_externtype_as_instancetype_const(
|
||||
et: &wasm_externtype_t,
|
||||
) -> Option<&wasm_instancetype_t> {
|
||||
wasm_instancetype_t::try_from(et)
|
||||
) -> Option<&wasmtime_instancetype_t> {
|
||||
wasmtime_instancetype_t::try_from(et)
|
||||
}
|
||||
|
||||
@@ -3,25 +3,25 @@ use wasmtime::InstanceType;
|
||||
|
||||
#[repr(transparent)]
|
||||
#[derive(Clone)]
|
||||
pub struct wasm_instancetype_t {
|
||||
pub struct wasmtime_instancetype_t {
|
||||
ext: wasm_externtype_t,
|
||||
}
|
||||
|
||||
wasmtime_c_api_macros::declare_ty!(wasm_instancetype_t);
|
||||
wasmtime_c_api_macros::declare_ty!(wasmtime_instancetype_t);
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct CInstanceType {
|
||||
pub(crate) ty: InstanceType,
|
||||
}
|
||||
|
||||
impl wasm_instancetype_t {
|
||||
pub(crate) fn new(ty: InstanceType) -> wasm_instancetype_t {
|
||||
wasm_instancetype_t {
|
||||
impl wasmtime_instancetype_t {
|
||||
pub(crate) fn new(ty: InstanceType) -> wasmtime_instancetype_t {
|
||||
wasmtime_instancetype_t {
|
||||
ext: wasm_externtype_t::new(ty.into()),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn try_from(e: &wasm_externtype_t) -> Option<&wasm_instancetype_t> {
|
||||
pub(crate) fn try_from(e: &wasm_externtype_t) -> Option<&wasmtime_instancetype_t> {
|
||||
match &e.which {
|
||||
CExternType::Instance(_) => Some(unsafe { &*(e as *const _ as *const _) }),
|
||||
_ => None,
|
||||
@@ -42,20 +42,15 @@ impl CInstanceType {
|
||||
}
|
||||
}
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_instancetype_as_externtype(ty: &wasm_instancetype_t) -> &wasm_externtype_t {
|
||||
&ty.ext
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_instancetype_as_externtype_const(
|
||||
ty: &wasm_instancetype_t,
|
||||
pub extern "C" fn wasmtime_instancetype_as_externtype(
|
||||
ty: &wasmtime_instancetype_t,
|
||||
) -> &wasm_externtype_t {
|
||||
&ty.ext
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_instancetype_exports(
|
||||
instance: &wasm_instancetype_t,
|
||||
pub extern "C" fn wasmtime_instancetype_exports(
|
||||
instance: &wasmtime_instancetype_t,
|
||||
out: &mut wasm_exporttype_vec_t,
|
||||
) {
|
||||
let exports = instance
|
||||
|
||||
@@ -6,25 +6,25 @@ use wasmtime::ModuleType;
|
||||
|
||||
#[repr(transparent)]
|
||||
#[derive(Clone)]
|
||||
pub struct wasm_moduletype_t {
|
||||
pub struct wasmtime_moduletype_t {
|
||||
ext: wasm_externtype_t,
|
||||
}
|
||||
|
||||
wasmtime_c_api_macros::declare_ty!(wasm_moduletype_t);
|
||||
wasmtime_c_api_macros::declare_ty!(wasmtime_moduletype_t);
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct CModuleType {
|
||||
pub(crate) ty: ModuleType,
|
||||
}
|
||||
|
||||
impl wasm_moduletype_t {
|
||||
pub(crate) fn new(ty: ModuleType) -> wasm_moduletype_t {
|
||||
wasm_moduletype_t {
|
||||
impl wasmtime_moduletype_t {
|
||||
pub(crate) fn new(ty: ModuleType) -> wasmtime_moduletype_t {
|
||||
wasmtime_moduletype_t {
|
||||
ext: wasm_externtype_t::new(ty.into()),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn try_from(e: &wasm_externtype_t) -> Option<&wasm_moduletype_t> {
|
||||
pub(crate) fn try_from(e: &wasm_externtype_t) -> Option<&wasmtime_moduletype_t> {
|
||||
match &e.which {
|
||||
CExternType::Module(_) => Some(unsafe { &*(e as *const _ as *const _) }),
|
||||
_ => None,
|
||||
@@ -46,20 +46,15 @@ impl CModuleType {
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_moduletype_as_externtype(ty: &wasm_moduletype_t) -> &wasm_externtype_t {
|
||||
&ty.ext
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_moduletype_as_externtype_const(
|
||||
ty: &wasm_moduletype_t,
|
||||
pub extern "C" fn wasmtime_moduletype_as_externtype(
|
||||
ty: &wasmtime_moduletype_t,
|
||||
) -> &wasm_externtype_t {
|
||||
&ty.ext
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_moduletype_exports(
|
||||
module: &wasm_moduletype_t,
|
||||
pub extern "C" fn wasmtime_moduletype_exports(
|
||||
module: &wasmtime_moduletype_t,
|
||||
out: &mut wasm_exporttype_vec_t,
|
||||
) {
|
||||
let exports = module
|
||||
@@ -77,8 +72,8 @@ pub extern "C" fn wasm_moduletype_exports(
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_moduletype_imports(
|
||||
module: &wasm_moduletype_t,
|
||||
pub extern "C" fn wasmtime_moduletype_imports(
|
||||
module: &wasmtime_moduletype_t,
|
||||
out: &mut wasm_importtype_vec_t,
|
||||
) {
|
||||
let imports = module
|
||||
|
||||
@@ -36,6 +36,7 @@ pub(crate) fn into_valtype(kind: wasm_valkind_t) -> ValType {
|
||||
WASM_F64 => ValType::F64,
|
||||
WASM_EXTERNREF => ValType::ExternRef,
|
||||
WASM_FUNCREF => ValType::FuncRef,
|
||||
WASMTIME_V128 => ValType::V128,
|
||||
_ => panic!("unexpected kind: {}", kind),
|
||||
}
|
||||
}
|
||||
@@ -48,6 +49,15 @@ pub(crate) fn from_valtype(ty: &ValType) -> wasm_valkind_t {
|
||||
ValType::F64 => WASM_F64,
|
||||
ValType::ExternRef => WASM_EXTERNREF,
|
||||
ValType::FuncRef => WASM_FUNCREF,
|
||||
_ => panic!("wasm_valkind_t has no known conversion for {:?}", ty),
|
||||
ValType::V128 => WASMTIME_V128,
|
||||
}
|
||||
}
|
||||
|
||||
pub type wasmtime_valkind_t = u8;
|
||||
pub const WASMTIME_I32: wasmtime_valkind_t = 0;
|
||||
pub const WASMTIME_I64: wasmtime_valkind_t = 1;
|
||||
pub const WASMTIME_F32: wasmtime_valkind_t = 2;
|
||||
pub const WASMTIME_F64: wasmtime_valkind_t = 3;
|
||||
pub const WASMTIME_V128: wasmtime_valkind_t = 4;
|
||||
pub const WASMTIME_FUNCREF: wasmtime_valkind_t = 5;
|
||||
pub const WASMTIME_EXTERNREF: wasmtime_valkind_t = 6;
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
use crate::r#ref::{ref_to_val, WasmRefInner};
|
||||
use crate::{from_valtype, into_valtype, wasm_ref_t, wasm_valkind_t, WASM_I32};
|
||||
use std::mem::MaybeUninit;
|
||||
use crate::{from_valtype, into_valtype, wasm_ref_t, wasm_valkind_t, wasmtime_valkind_t, WASM_I32};
|
||||
use std::ffi::c_void;
|
||||
use std::mem::{self, ManuallyDrop, MaybeUninit};
|
||||
use std::ptr;
|
||||
use wasmtime::{Val, ValType};
|
||||
use wasmtime::{ExternRef, Func, Val, ValType};
|
||||
|
||||
#[repr(C)]
|
||||
pub struct wasm_val_t {
|
||||
@@ -147,3 +148,143 @@ pub unsafe extern "C" fn wasm_val_copy(out: &mut MaybeUninit<wasm_val_t>, source
|
||||
pub unsafe extern "C" fn wasm_val_delete(val: *mut wasm_val_t) {
|
||||
ptr::drop_in_place(val);
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct wasmtime_val_t {
|
||||
pub kind: wasmtime_valkind_t,
|
||||
pub of: wasmtime_val_union,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub union wasmtime_val_union {
|
||||
pub i32: i32,
|
||||
pub i64: i64,
|
||||
pub f32: u32,
|
||||
pub f64: u64,
|
||||
pub funcref: wasmtime_func_t,
|
||||
pub externref: ManuallyDrop<Option<ExternRef>>,
|
||||
pub v128: [u8; 16],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct wasmtime_func_t {
|
||||
pub store_id: u64,
|
||||
pub index: usize,
|
||||
}
|
||||
|
||||
impl wasmtime_val_t {
|
||||
pub fn from_val(val: Val) -> wasmtime_val_t {
|
||||
match val {
|
||||
Val::I32(i) => wasmtime_val_t {
|
||||
kind: crate::WASMTIME_I32,
|
||||
of: wasmtime_val_union { i32: i },
|
||||
},
|
||||
Val::I64(i) => wasmtime_val_t {
|
||||
kind: crate::WASMTIME_I64,
|
||||
of: wasmtime_val_union { i64: i },
|
||||
},
|
||||
Val::F32(i) => wasmtime_val_t {
|
||||
kind: crate::WASMTIME_F32,
|
||||
of: wasmtime_val_union { f32: i },
|
||||
},
|
||||
Val::F64(i) => wasmtime_val_t {
|
||||
kind: crate::WASMTIME_F64,
|
||||
of: wasmtime_val_union { f64: i },
|
||||
},
|
||||
Val::ExternRef(i) => wasmtime_val_t {
|
||||
kind: crate::WASMTIME_EXTERNREF,
|
||||
of: wasmtime_val_union {
|
||||
externref: ManuallyDrop::new(i),
|
||||
},
|
||||
},
|
||||
Val::FuncRef(i) => wasmtime_val_t {
|
||||
kind: crate::WASMTIME_FUNCREF,
|
||||
of: wasmtime_val_union {
|
||||
funcref: match i {
|
||||
Some(func) => unsafe { mem::transmute::<Func, wasmtime_func_t>(func) },
|
||||
None => wasmtime_func_t {
|
||||
store_id: 0,
|
||||
index: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Val::V128(val) => wasmtime_val_t {
|
||||
kind: crate::WASMTIME_V128,
|
||||
of: wasmtime_val_union {
|
||||
v128: val.to_le_bytes(),
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn to_val(&self) -> Val {
|
||||
match self.kind {
|
||||
crate::WASMTIME_I32 => Val::I32(self.of.i32),
|
||||
crate::WASMTIME_I64 => Val::I64(self.of.i64),
|
||||
crate::WASMTIME_F32 => Val::F32(self.of.f32),
|
||||
crate::WASMTIME_F64 => Val::F64(self.of.f64),
|
||||
crate::WASMTIME_V128 => Val::V128(u128::from_le_bytes(self.of.v128)),
|
||||
crate::WASMTIME_FUNCREF => {
|
||||
let store = self.of.funcref.store_id;
|
||||
let index = self.of.funcref.index;
|
||||
Val::FuncRef(if store == 0 && index == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(mem::transmute::<wasmtime_func_t, Func>(self.of.funcref))
|
||||
})
|
||||
}
|
||||
crate::WASMTIME_EXTERNREF => Val::ExternRef((*self.of.externref).clone()),
|
||||
other => panic!("unknown wasmtime_valkind_t: {}", other),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for wasmtime_val_t {
|
||||
fn drop(&mut self) {
|
||||
if self.kind == crate::WASMTIME_EXTERNREF {
|
||||
unsafe {
|
||||
ManuallyDrop::drop(&mut self.of.externref);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasmtime_val_delete(val: &mut ManuallyDrop<wasmtime_val_t>) {
|
||||
ManuallyDrop::drop(val)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasmtime_val_copy(
|
||||
dst: &mut MaybeUninit<wasmtime_val_t>,
|
||||
src: &wasmtime_val_t,
|
||||
) {
|
||||
crate::initialize(dst, wasmtime_val_t::from_val(src.to_val()))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_externref_new(
|
||||
data: *mut c_void,
|
||||
finalizer: Option<extern "C" fn(*mut c_void)>,
|
||||
) -> ExternRef {
|
||||
ExternRef::new(crate::ForeignData { data, finalizer })
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_externref_data(externref: ManuallyDrop<ExternRef>) -> *mut c_void {
|
||||
externref
|
||||
.data()
|
||||
.downcast_ref::<crate::ForeignData>()
|
||||
.unwrap()
|
||||
.data
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_externref_clone(externref: ManuallyDrop<ExternRef>) -> ExternRef {
|
||||
(*externref).clone()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_externref_delete(_val: Option<ExternRef>) {}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
wasm_exporttype_t, wasm_extern_t, wasm_externtype_t, wasm_frame_t, wasm_functype_t,
|
||||
wasm_globaltype_t, wasm_importtype_t, wasm_instancetype_t, wasm_memorytype_t,
|
||||
wasm_moduletype_t, wasm_tabletype_t, wasm_val_t, wasm_valtype_t,
|
||||
wasm_globaltype_t, wasm_importtype_t, wasm_memorytype_t, wasm_tabletype_t, wasm_val_t,
|
||||
wasm_valtype_t,
|
||||
};
|
||||
use std::mem;
|
||||
use std::mem::MaybeUninit;
|
||||
@@ -186,24 +186,6 @@ declare_vecs! {
|
||||
copy: wasm_memorytype_vec_copy,
|
||||
delete: wasm_memorytype_vec_delete,
|
||||
)
|
||||
(
|
||||
name: wasm_instancetype_vec_t,
|
||||
ty: Option<Box<wasm_instancetype_t>>,
|
||||
new: wasm_instancetype_vec_new,
|
||||
empty: wasm_instancetype_vec_new_empty,
|
||||
uninit: wasm_instancetype_vec_new_uninitialized,
|
||||
copy: wasm_instancetype_vec_copy,
|
||||
delete: wasm_instancetype_vec_delete,
|
||||
)
|
||||
(
|
||||
name: wasm_moduletype_vec_t,
|
||||
ty: Option<Box<wasm_moduletype_t>>,
|
||||
new: wasm_moduletype_vec_new,
|
||||
empty: wasm_moduletype_vec_new_empty,
|
||||
uninit: wasm_moduletype_vec_new_uninitialized,
|
||||
copy: wasm_moduletype_vec_copy,
|
||||
delete: wasm_moduletype_vec_delete,
|
||||
)
|
||||
(
|
||||
name: wasm_externtype_vec_t,
|
||||
ty: Option<Box<wasm_externtype_t>>,
|
||||
|
||||
@@ -1,21 +1,13 @@
|
||||
//! The WASI embedding API definitions for Wasmtime.
|
||||
use crate::{wasm_extern_t, wasm_importtype_t, wasm_store_t, wasm_trap_t};
|
||||
|
||||
use anyhow::Result;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::ffi::CStr;
|
||||
use std::fs::File;
|
||||
use std::os::raw::{c_char, c_int};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::rc::Rc;
|
||||
use std::slice;
|
||||
use std::str;
|
||||
use wasmtime::{Extern, Linker, Trap};
|
||||
use wasmtime_wasi::{
|
||||
sync::{
|
||||
snapshots::preview_0::Wasi as WasiSnapshot0, snapshots::preview_1::Wasi as WasiPreview1,
|
||||
Dir, WasiCtxBuilder,
|
||||
},
|
||||
sync::{Dir, WasiCtxBuilder},
|
||||
WasiCtx,
|
||||
};
|
||||
|
||||
@@ -31,13 +23,6 @@ unsafe fn create_file(path: *const c_char) -> Option<File> {
|
||||
File::create(cstr_to_path(path)?).ok()
|
||||
}
|
||||
|
||||
pub enum WasiModule {
|
||||
Snapshot0(WasiSnapshot0),
|
||||
Preview1(WasiPreview1),
|
||||
}
|
||||
|
||||
impl WasiModule {}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Default)]
|
||||
pub struct wasi_config_t {
|
||||
@@ -54,6 +39,61 @@ pub struct wasi_config_t {
|
||||
inherit_stderr: bool,
|
||||
}
|
||||
|
||||
impl wasi_config_t {
|
||||
pub fn into_wasi_ctx(self) -> Result<WasiCtx> {
|
||||
let mut builder = WasiCtxBuilder::new();
|
||||
if self.inherit_args {
|
||||
builder = builder.inherit_args()?;
|
||||
} else if !self.args.is_empty() {
|
||||
let args = self
|
||||
.args
|
||||
.into_iter()
|
||||
.map(|bytes| Ok(String::from_utf8(bytes)?))
|
||||
.collect::<Result<Vec<String>>>()?;
|
||||
builder = builder.args(&args)?;
|
||||
}
|
||||
if self.inherit_env {
|
||||
builder = builder.inherit_env()?;
|
||||
} else if !self.env.is_empty() {
|
||||
let env = self
|
||||
.env
|
||||
.into_iter()
|
||||
.map(|(kbytes, vbytes)| {
|
||||
let k = String::from_utf8(kbytes)?;
|
||||
let v = String::from_utf8(vbytes)?;
|
||||
Ok((k, v))
|
||||
})
|
||||
.collect::<Result<Vec<(String, String)>>>()?;
|
||||
builder = builder.envs(&env)?;
|
||||
}
|
||||
if self.inherit_stdin {
|
||||
builder = builder.inherit_stdin();
|
||||
} else if let Some(file) = self.stdin {
|
||||
let file = unsafe { cap_std::fs::File::from_std(file) };
|
||||
let file = wasi_cap_std_sync::file::File::from_cap_std(file);
|
||||
builder = builder.stdin(Box::new(file));
|
||||
}
|
||||
if self.inherit_stdout {
|
||||
builder = builder.inherit_stdout();
|
||||
} else if let Some(file) = self.stdout {
|
||||
let file = unsafe { cap_std::fs::File::from_std(file) };
|
||||
let file = wasi_cap_std_sync::file::File::from_cap_std(file);
|
||||
builder = builder.stdout(Box::new(file));
|
||||
}
|
||||
if self.inherit_stderr {
|
||||
builder = builder.inherit_stderr();
|
||||
} else if let Some(file) = self.stderr {
|
||||
let file = unsafe { cap_std::fs::File::from_std(file) };
|
||||
let file = wasi_cap_std_sync::file::File::from_cap_std(file);
|
||||
builder = builder.stderr(Box::new(file));
|
||||
}
|
||||
for (dir, path) in self.preopens {
|
||||
builder = builder.preopened_dir(dir, path)?;
|
||||
}
|
||||
Ok(builder.build())
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasi_config_new() -> Box<wasi_config_t> {
|
||||
Box::new(wasi_config_t::default())
|
||||
@@ -198,151 +238,3 @@ pub unsafe extern "C" fn wasi_config_preopen_dir(
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
enum WasiInstance {
|
||||
Preview1(WasiPreview1),
|
||||
Snapshot0(WasiSnapshot0),
|
||||
}
|
||||
|
||||
fn create_wasi_ctx(config: wasi_config_t) -> Result<Rc<RefCell<WasiCtx>>> {
|
||||
let mut builder = WasiCtxBuilder::new();
|
||||
if config.inherit_args {
|
||||
builder = builder.inherit_args()?;
|
||||
} else if !config.args.is_empty() {
|
||||
let args = config
|
||||
.args
|
||||
.into_iter()
|
||||
.map(|bytes| Ok(String::from_utf8(bytes)?))
|
||||
.collect::<Result<Vec<String>>>()?;
|
||||
builder = builder.args(&args)?;
|
||||
}
|
||||
if config.inherit_env {
|
||||
builder = builder.inherit_env()?;
|
||||
} else if !config.env.is_empty() {
|
||||
let env = config
|
||||
.env
|
||||
.into_iter()
|
||||
.map(|(kbytes, vbytes)| {
|
||||
let k = String::from_utf8(kbytes)?;
|
||||
let v = String::from_utf8(vbytes)?;
|
||||
Ok((k, v))
|
||||
})
|
||||
.collect::<Result<Vec<(String, String)>>>()?;
|
||||
builder = builder.envs(&env)?;
|
||||
}
|
||||
if config.inherit_stdin {
|
||||
builder = builder.inherit_stdin();
|
||||
} else if let Some(file) = config.stdin {
|
||||
let file = unsafe { cap_std::fs::File::from_std(file) };
|
||||
let file = wasi_cap_std_sync::file::File::from_cap_std(file);
|
||||
builder = builder.stdin(Box::new(file));
|
||||
}
|
||||
if config.inherit_stdout {
|
||||
builder = builder.inherit_stdout();
|
||||
} else if let Some(file) = config.stdout {
|
||||
let file = unsafe { cap_std::fs::File::from_std(file) };
|
||||
let file = wasi_cap_std_sync::file::File::from_cap_std(file);
|
||||
builder = builder.stdout(Box::new(file));
|
||||
}
|
||||
if config.inherit_stderr {
|
||||
builder = builder.inherit_stderr();
|
||||
} else if let Some(file) = config.stderr {
|
||||
let file = unsafe { cap_std::fs::File::from_std(file) };
|
||||
let file = wasi_cap_std_sync::file::File::from_cap_std(file);
|
||||
builder = builder.stderr(Box::new(file));
|
||||
}
|
||||
for (dir, path) in config.preopens {
|
||||
builder = builder.preopened_dir(dir, path)?;
|
||||
}
|
||||
Ok(Rc::new(RefCell::new(builder.build())))
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct wasi_instance_t {
|
||||
wasi: WasiInstance,
|
||||
export_cache: HashMap<String, Box<wasm_extern_t>>,
|
||||
}
|
||||
|
||||
impl wasi_instance_t {
|
||||
pub fn add_to_linker(&self, linker: &mut Linker) -> Result<()> {
|
||||
match &self.wasi {
|
||||
WasiInstance::Snapshot0(w) => w.add_to_linker(linker),
|
||||
WasiInstance::Preview1(w) => w.add_to_linker(linker),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasi_instance_new(
|
||||
store: &wasm_store_t,
|
||||
name: *const c_char,
|
||||
config: Box<wasi_config_t>,
|
||||
trap: &mut *mut wasm_trap_t,
|
||||
) -> Option<Box<wasi_instance_t>> {
|
||||
let store = &store.store;
|
||||
|
||||
let result = match CStr::from_ptr(name).to_str().unwrap_or("") {
|
||||
"wasi_snapshot_preview1" => {
|
||||
create_wasi_ctx(*config).map(|cx| WasiInstance::Preview1(WasiPreview1::new(store, cx)))
|
||||
}
|
||||
"wasi_unstable" => create_wasi_ctx(*config)
|
||||
.map(|cx| WasiInstance::Snapshot0(WasiSnapshot0::new(store, cx))),
|
||||
_ => Err(anyhow::anyhow!("unsupported WASI version")),
|
||||
};
|
||||
|
||||
match result {
|
||||
Ok(wasi) => Some(Box::new(wasi_instance_t {
|
||||
wasi,
|
||||
export_cache: HashMap::new(),
|
||||
})),
|
||||
Err(e) => {
|
||||
*trap = Box::into_raw(Box::new(wasm_trap_t {
|
||||
trap: Trap::from(e),
|
||||
}));
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasi_instance_delete(_instance: Box<wasi_instance_t>) {}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasi_instance_bind_import<'a>(
|
||||
instance: &'a mut wasi_instance_t,
|
||||
import: &wasm_importtype_t,
|
||||
) -> Option<&'a wasm_extern_t> {
|
||||
let module = &import.module;
|
||||
let name = str::from_utf8(import.name.as_ref()?.as_bytes()).ok()?;
|
||||
|
||||
let export = match &instance.wasi {
|
||||
WasiInstance::Preview1(wasi) => {
|
||||
if module != "wasi_snapshot_preview1" {
|
||||
return None;
|
||||
}
|
||||
wasi.get_export(&name)?
|
||||
}
|
||||
WasiInstance::Snapshot0(wasi) => {
|
||||
if module != "wasi_unstable" {
|
||||
return None;
|
||||
}
|
||||
|
||||
wasi.get_export(&name)?
|
||||
}
|
||||
};
|
||||
|
||||
if &export.ty() != import.ty.func()? {
|
||||
return None;
|
||||
}
|
||||
|
||||
let entry = instance
|
||||
.export_cache
|
||||
.entry(name.to_string())
|
||||
.or_insert_with(|| {
|
||||
Box::new(wasm_extern_t {
|
||||
which: Extern::Func(export.clone()),
|
||||
})
|
||||
});
|
||||
Some(entry)
|
||||
}
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
use crate::{bad_utf8, handle_result, wasm_byte_vec_t, wasmtime_error_t};
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_wat2wasm(
|
||||
wat: &wasm_byte_vec_t,
|
||||
pub unsafe extern "C" fn wasmtime_wat2wasm(
|
||||
wat: *const u8,
|
||||
wat_len: usize,
|
||||
ret: &mut wasm_byte_vec_t,
|
||||
) -> Option<Box<wasmtime_error_t>> {
|
||||
let wat = match std::str::from_utf8(wat.as_slice()) {
|
||||
let wat = crate::slice_from_raw_parts(wat, wat_len);
|
||||
let wat = match std::str::from_utf8(wat) {
|
||||
Ok(s) => s,
|
||||
Err(_) => return bad_utf8(),
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user