Start work on ability to load wasm languages from native lib, via wasmtime
This commit is contained in:
parent
8883d43bee
commit
3f1a7f9cd4
19 changed files with 2989 additions and 284 deletions
1645
Cargo.lock
generated
1645
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
|
@ -43,6 +43,7 @@ which = "4.1.0"
|
|||
[dependencies.tree-sitter]
|
||||
version = "0.20.3"
|
||||
path = "../lib"
|
||||
features = ["wasm"]
|
||||
|
||||
[dependencies.tree-sitter-config]
|
||||
version = "0.19.0"
|
||||
|
|
|
|||
|
|
@ -124,6 +124,7 @@ fn run() -> Result<()> {
|
|||
.arg(&debug_arg)
|
||||
.arg(&debug_build_arg)
|
||||
.arg(&debug_graph_arg)
|
||||
.arg(Arg::with_name("wasm").long("wasm").help("use wasm file"))
|
||||
.arg(Arg::with_name("debug-xml").long("xml").short("x"))
|
||||
.arg(
|
||||
Arg::with_name("stat")
|
||||
|
|
@ -353,6 +354,7 @@ fn run() -> Result<()> {
|
|||
let debug_xml = matches.is_present("debug-xml");
|
||||
let quiet = matches.is_present("quiet");
|
||||
let time = matches.is_present("time");
|
||||
let wasm = matches.is_present("wasm");
|
||||
let edits = matches
|
||||
.values_of("edits")
|
||||
.map_or(Vec::new(), |e| e.collect());
|
||||
|
|
@ -379,8 +381,18 @@ fn run() -> Result<()> {
|
|||
let should_track_stats = matches.is_present("stat");
|
||||
let mut stats = parse::Stats::default();
|
||||
|
||||
let mut wasm_language = None;
|
||||
if wasm {
|
||||
let (language_name, wasm_file) = wasm::load_language_wasm_file(¤t_dir)?;
|
||||
let engine = tree_sitter::wasmtime::Engine::default();
|
||||
let mut context = tree_sitter::WasmStore::new(engine);
|
||||
wasm_language = Some(context.load_language(&language_name, &wasm_file));
|
||||
std::mem::forget(context);
|
||||
}
|
||||
|
||||
for path in paths {
|
||||
let path = Path::new(&path);
|
||||
|
||||
let language =
|
||||
loader.select_language(path, ¤t_dir, matches.value_of("scope"))?;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
use super::wasm;
|
||||
use anyhow::Context;
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
env, fs,
|
||||
|
|
@ -58,19 +57,8 @@ pub fn serve(grammar_path: &Path, open_in_browser: bool) {
|
|||
env::var("TREE_SITTER_PLAYGROUND_ADDR").unwrap_or("127.0.0.1".to_owned()),
|
||||
port
|
||||
);
|
||||
let (grammar_name, language_wasm) = wasm::load_language_wasm_file(&grammar_path).unwrap();
|
||||
let server = Server::http(&addr).expect("Failed to start web server");
|
||||
let grammar_name = wasm::get_grammar_name(&grammar_path.join("src"))
|
||||
.with_context(|| "Failed to get wasm filename")
|
||||
.unwrap();
|
||||
let wasm_filename = format!("tree-sitter-{}.wasm", grammar_name);
|
||||
let language_wasm = fs::read(grammar_path.join(&wasm_filename))
|
||||
.with_context(|| {
|
||||
format!(
|
||||
"Failed to read {}. Run `tree-sitter build-wasm` first.",
|
||||
wasm_filename
|
||||
)
|
||||
})
|
||||
.unwrap();
|
||||
let url = format!("http://{}", addr);
|
||||
println!("Started playground on: {}", url);
|
||||
if open_in_browser {
|
||||
|
|
|
|||
|
|
@ -1,14 +1,31 @@
|
|||
use super::generate::parse_grammar::GrammarJSON;
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use std::ffi::{OsStr, OsString};
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
use std::{
|
||||
ffi::{OsStr, OsString},
|
||||
fs,
|
||||
path::Path,
|
||||
process::Command,
|
||||
};
|
||||
use which::which;
|
||||
|
||||
const EMSCRIPTEN_TAG: &'static str = concat!("emscripten/emsdk:", env!("EMSCRIPTEN_VERSION"));
|
||||
|
||||
pub fn get_grammar_name(src_dir: &Path) -> Result<String> {
|
||||
pub fn load_language_wasm_file(language_dir: &Path) -> Result<(String, Vec<u8>)> {
|
||||
let grammar_name = get_grammar_name(&language_dir)
|
||||
.with_context(|| "Failed to get wasm filename")
|
||||
.unwrap();
|
||||
let wasm_filename = format!("tree-sitter-{}.wasm", grammar_name);
|
||||
let contents = fs::read(language_dir.join(&wasm_filename)).with_context(|| {
|
||||
format!(
|
||||
"Failed to read {}. Run `tree-sitter build-wasm` first.",
|
||||
wasm_filename
|
||||
)
|
||||
})?;
|
||||
Ok((grammar_name, contents))
|
||||
}
|
||||
|
||||
pub fn get_grammar_name(language_dir: &Path) -> Result<String> {
|
||||
let src_dir = language_dir.join("src");
|
||||
let grammar_json_path = src_dir.join("grammar.json");
|
||||
let grammar_json = fs::read_to_string(&grammar_json_path)
|
||||
.with_context(|| format!("Failed to read grammar file {:?}", grammar_json_path))?;
|
||||
|
|
@ -18,8 +35,7 @@ pub fn get_grammar_name(src_dir: &Path) -> Result<String> {
|
|||
}
|
||||
|
||||
pub fn compile_language_to_wasm(language_dir: &Path, force_docker: bool) -> Result<()> {
|
||||
let src_dir = language_dir.join("src");
|
||||
let grammar_name = get_grammar_name(&src_dir)?;
|
||||
let grammar_name = get_grammar_name(&language_dir)?;
|
||||
let output_filename = format!("tree-sitter-{}.wasm", grammar_name);
|
||||
|
||||
let emcc_bin = if cfg!(windows) { "emcc.bat" } else { "emcc" };
|
||||
|
|
|
|||
|
|
@ -21,9 +21,15 @@ include = [
|
|||
"/src/unicode/*",
|
||||
]
|
||||
|
||||
[features]
|
||||
"wasm" = ["wasmtime", "wasmtime-c-api"]
|
||||
|
||||
[dependencies]
|
||||
lazy_static = { version = "1.2.0", optional = true }
|
||||
regex = "1"
|
||||
# wasmtime = { git = "https://github.com/bytecodealliance/wasmtime", optional = true }
|
||||
# wasmtime-c-api = { git = "https://github.com/bytecodealliance/wasmtime", optional = true }
|
||||
wasmtime = { path = "../../wasmtime/crates/wasmtime", optional = true }
|
||||
wasmtime-c-api = { path = "../../wasmtime/crates/c-api", optional = true }
|
||||
|
||||
[build-dependencies]
|
||||
cc = "^1.0.58"
|
||||
|
|
|
|||
|
|
@ -853,6 +853,51 @@ extern "C" {
|
|||
#[doc = " See also `ts_parser_set_language`."]
|
||||
pub fn ts_language_version(arg1: *const TSLanguage) -> u32;
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct wasm_engine_t {
|
||||
_unused: [u8; 0],
|
||||
}
|
||||
pub type TSWasmEngine = wasm_engine_t;
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct TSWasmStore {
|
||||
_unused: [u8; 0],
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct TSWasmLanguage {
|
||||
_unused: [u8; 0],
|
||||
}
|
||||
extern "C" {
|
||||
pub fn ts_wasm_store_new(engine: *mut TSWasmEngine) -> *mut TSWasmStore;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn ts_wasm_store_delete(arg1: *mut TSWasmStore);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn ts_wasm_language_delete(arg1: *const TSWasmLanguage);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn ts_wasm_store_load_language(
|
||||
arg1: *mut TSWasmStore,
|
||||
name: *const ::std::os::raw::c_char,
|
||||
wasm: *const ::std::os::raw::c_char,
|
||||
wasm_len: u32,
|
||||
) -> *mut TSWasmLanguage;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn ts_wasm_store_add_language(arg1: *mut TSWasmStore, arg2: *const TSWasmLanguage);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn ts_parser_set_wasm_language(arg1: *mut TSParser, arg2: *const TSWasmLanguage);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn ts_parser_wasm_language(arg1: *mut TSParser) -> *const TSWasmLanguage;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn ts_parser_set_wasm_store(arg1: *mut TSParser, arg2: *mut TSWasmStore);
|
||||
}
|
||||
extern "C" {
|
||||
#[doc = " Set the allocation functions used by the library."]
|
||||
#[doc = ""]
|
||||
|
|
|
|||
|
|
@ -17,6 +17,13 @@ fn main() {
|
|||
}
|
||||
}
|
||||
|
||||
let mut config = cc::Build::new();
|
||||
|
||||
println!("cargo:rerun-if-env-changed=CARGO_FEATURE_WASM");
|
||||
if env::var("CARGO_FEATURE_WASM").is_ok() {
|
||||
config.define("TREE_SITTER_FEATURE_WASM", "");
|
||||
}
|
||||
|
||||
let src_path = Path::new("src");
|
||||
for entry in fs::read_dir(&src_path).unwrap() {
|
||||
let entry = entry.unwrap();
|
||||
|
|
@ -24,7 +31,7 @@ fn main() {
|
|||
println!("cargo:rerun-if-changed={}", path.to_str().unwrap());
|
||||
}
|
||||
|
||||
cc::Build::new()
|
||||
config
|
||||
.flag_if_supported("-std=c99")
|
||||
.flag_if_supported("-Wno-unused-parameter")
|
||||
.include(src_path)
|
||||
|
|
|
|||
|
|
@ -18,6 +18,11 @@ use std::{
|
|||
u16,
|
||||
};
|
||||
|
||||
#[cfg(feature = "wasm")]
|
||||
mod wasm_language;
|
||||
#[cfg(feature = "wasm")]
|
||||
pub use wasm_language::*;
|
||||
|
||||
/// The latest ABI version that is supported by the current version of the
|
||||
/// library.
|
||||
///
|
||||
|
|
|
|||
76
lib/binding_rust/wasm_language.rs
Normal file
76
lib/binding_rust/wasm_language.rs
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
use crate::{LanguageError, Parser};
|
||||
|
||||
use super::ffi;
|
||||
use std::{ffi::CString, os::raw::c_char};
|
||||
pub use wasmtime;
|
||||
|
||||
#[cfg(feature = "wasm")]
|
||||
pub fn test() {
|
||||
wasmtime_c_api::wasm_engine_new();
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone)]
|
||||
pub struct wasm_engine_t {
|
||||
pub(crate) engine: wasmtime::Engine,
|
||||
}
|
||||
|
||||
pub struct WasmStore(*mut ffi::TSWasmStore);
|
||||
pub struct WasmLanguage(*const ffi::TSWasmLanguage);
|
||||
|
||||
impl WasmStore {
|
||||
pub fn new(engine: wasmtime::Engine) -> Self {
|
||||
let mut c_engine = wasm_engine_t { engine };
|
||||
let c_engine = &mut c_engine as *mut _;
|
||||
WasmStore(unsafe { ffi::ts_wasm_store_new(c_engine as *mut _) })
|
||||
}
|
||||
|
||||
pub fn load_language(&mut self, name: &str, bytes: &[u8]) -> WasmLanguage {
|
||||
let name = CString::new(name).unwrap();
|
||||
WasmLanguage(unsafe {
|
||||
ffi::ts_wasm_store_load_language(
|
||||
self.0,
|
||||
name.as_ptr(),
|
||||
bytes.as_ptr() as *const c_char,
|
||||
bytes.len() as u32,
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Parser {
|
||||
pub fn wasm_language(&self) -> Option<WasmLanguage> {
|
||||
let language = unsafe { ffi::ts_parser_wasm_language(self.0.as_ptr()) };
|
||||
if language.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(WasmLanguage(language))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_wasm_language(&mut self, language: WasmLanguage) -> Result<(), LanguageError> {
|
||||
unsafe {
|
||||
ffi::ts_parser_set_wasm_language(self.0.as_ptr(), language.0);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_wasm_store(&mut self, language: WasmStore) -> Result<(), LanguageError> {
|
||||
unsafe {
|
||||
ffi::ts_parser_set_wasm_store(self.0.as_ptr(), language.0);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for WasmLanguage {
|
||||
fn drop(&mut self) {
|
||||
unsafe { ffi::ts_wasm_language_delete(self.0) };
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for WasmStore {
|
||||
fn drop(&mut self) {
|
||||
unsafe { ffi::ts_wasm_store_delete(self.0) };
|
||||
}
|
||||
}
|
||||
|
|
@ -937,6 +937,29 @@ TSSymbolType ts_language_symbol_type(const TSLanguage *, TSSymbol);
|
|||
*/
|
||||
uint32_t ts_language_version(const TSLanguage *);
|
||||
|
||||
/*************************************/
|
||||
/* Section - WebAssembly Integration */
|
||||
/************************************/
|
||||
|
||||
typedef struct wasm_engine_t TSWasmEngine;
|
||||
typedef struct TSWasmStore TSWasmStore;
|
||||
typedef struct TSWasmLanguage TSWasmLanguage;
|
||||
|
||||
TSWasmStore *ts_wasm_store_new(TSWasmEngine *engine);
|
||||
void ts_wasm_store_delete(TSWasmStore *);
|
||||
void ts_wasm_language_delete(const TSWasmLanguage *);
|
||||
|
||||
TSWasmLanguage *ts_wasm_store_load_language(
|
||||
TSWasmStore *,
|
||||
const char *name,
|
||||
const char *wasm,
|
||||
uint32_t wasm_len
|
||||
);
|
||||
void ts_wasm_store_add_language(TSWasmStore *, const TSWasmLanguage *);
|
||||
void ts_parser_set_wasm_language(TSParser *, const TSWasmLanguage *);
|
||||
const TSWasmLanguage *ts_parser_wasm_language(TSParser *);
|
||||
void ts_parser_set_wasm_store(TSParser *, TSWasmStore *);
|
||||
|
||||
/**********************************/
|
||||
/* Section - Global Configuration */
|
||||
/**********************************/
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#define TREE_SITTER_ATOMIC_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __TINYC__
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,3 @@
|
|||
// The Tree-sitter library can be built by compiling this one source file.
|
||||
//
|
||||
// The following directories must be added to the include path:
|
||||
// - include
|
||||
|
||||
#define _POSIX_C_SOURCE 200112L
|
||||
|
||||
#include "./alloc.c"
|
||||
|
|
@ -16,3 +11,7 @@
|
|||
#include "./subtree.c"
|
||||
#include "./tree_cursor.c"
|
||||
#include "./tree.c"
|
||||
|
||||
#ifdef TREE_SITTER_FEATURE_WASM
|
||||
#include "./wasm.c"
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
#include "./stack.h"
|
||||
#include "./subtree.h"
|
||||
#include "./tree.h"
|
||||
#include "./wasm.h"
|
||||
|
||||
#define LOG(...) \
|
||||
if (self->lexer.logger.log || self->dot_graph_file) { \
|
||||
|
|
@ -88,6 +89,8 @@ struct TSParser {
|
|||
Stack *stack;
|
||||
SubtreePool tree_pool;
|
||||
const TSLanguage *language;
|
||||
const TSWasmLanguage *wasm_language;
|
||||
TSWasmStore *wasm_store;
|
||||
ReduceActionSet reduce_actions;
|
||||
Subtree finished_tree;
|
||||
SubtreeArray trailing_extras;
|
||||
|
|
@ -413,6 +416,7 @@ static Subtree ts_parser__lex(
|
|||
ts_lexer_reset(&self->lexer, start_position);
|
||||
|
||||
for (;;) {
|
||||
bool found_token = false;
|
||||
Length current_position = self->lexer.current_position;
|
||||
|
||||
if (valid_external_tokens) {
|
||||
|
|
@ -424,7 +428,7 @@ static Subtree ts_parser__lex(
|
|||
);
|
||||
ts_lexer_start(&self->lexer);
|
||||
ts_parser__restore_external_scanner(self, external_token);
|
||||
bool found_token = self->language->external_scanner.scan(
|
||||
found_token = self->language->external_scanner.scan(
|
||||
self->external_scanner_payload,
|
||||
&self->lexer.data,
|
||||
valid_external_tokens
|
||||
|
|
@ -482,7 +486,12 @@ static Subtree ts_parser__lex(
|
|||
current_position.extent.column
|
||||
);
|
||||
ts_lexer_start(&self->lexer);
|
||||
bool found_token = self->language->lex_fn(&self->lexer.data, lex_mode.lex_state);
|
||||
found_token = false;
|
||||
if (self->wasm_language) {
|
||||
found_token = ts_wasm_store_run_main_lex_function(self->wasm_store, lex_mode.lex_state);
|
||||
} else {
|
||||
found_token = self->language->lex_fn(&self->lexer.data, lex_mode.lex_state);
|
||||
}
|
||||
ts_lexer_finish(&self->lexer, &lookahead_end_byte);
|
||||
if (found_token) break;
|
||||
|
||||
|
|
@ -543,12 +552,18 @@ static Subtree ts_parser__lex(
|
|||
uint32_t end_byte = self->lexer.token_end_position.bytes;
|
||||
ts_lexer_reset(&self->lexer, self->lexer.token_start_position);
|
||||
ts_lexer_start(&self->lexer);
|
||||
|
||||
if (self->wasm_language) {
|
||||
is_keyword = ts_wasm_store_run_keyword_lex_function(self->wasm_store, 0);
|
||||
} else {
|
||||
is_keyword = self->language->keyword_lex_fn(&self->lexer.data, 0);
|
||||
}
|
||||
|
||||
if (
|
||||
self->language->keyword_lex_fn(&self->lexer.data, 0) &&
|
||||
is_keyword &&
|
||||
self->lexer.token_end_position.bytes == end_byte &&
|
||||
ts_language_has_actions(self->language, parse_state, self->lexer.data.result_symbol)
|
||||
) {
|
||||
is_keyword = true;
|
||||
symbol = self->lexer.data.result_symbol;
|
||||
}
|
||||
}
|
||||
|
|
@ -1797,6 +1812,14 @@ bool ts_parser_set_language(TSParser *self, const TSLanguage *language) {
|
|||
}
|
||||
|
||||
self->language = language;
|
||||
|
||||
#ifdef TREE_SITTER_FEATURE_WASM
|
||||
if (self->wasm_language) {
|
||||
ts_wasm_language_delete(self->wasm_language);
|
||||
self->wasm_language = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
ts_parser_reset(self);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1877,6 +1900,10 @@ TSTree *ts_parser_parse(
|
|||
) {
|
||||
if (!self->language || !input.read) return NULL;
|
||||
|
||||
if (self->wasm_store) {
|
||||
ts_wasm_store_start(self->wasm_store, &self->lexer.data, self->wasm_language);
|
||||
}
|
||||
|
||||
ts_lexer_set_input(&self->lexer, input);
|
||||
|
||||
array_clear(&self->included_range_differences);
|
||||
|
|
@ -1996,4 +2023,28 @@ TSTree *ts_parser_parse_string_encoding(
|
|||
});
|
||||
}
|
||||
|
||||
#ifdef TREE_SITTER_FEATURE_WASM
|
||||
|
||||
void ts_parser_set_wasm_language(TSParser *self, const TSWasmLanguage *language) {
|
||||
if (language) {
|
||||
self->language = language->language;
|
||||
ts_wasm_language_retain(language);
|
||||
}
|
||||
self->wasm_language = language;
|
||||
ts_parser_reset(self);
|
||||
}
|
||||
|
||||
const TSWasmLanguage *ts_parser_wasm_language(TSParser *self) {
|
||||
if (self->wasm_language) {
|
||||
ts_wasm_language_retain(self->wasm_language);
|
||||
}
|
||||
return self->wasm_language;
|
||||
}
|
||||
|
||||
void ts_parser_set_wasm_store(TSParser *self, TSWasmStore *store) {
|
||||
self->wasm_store = store;
|
||||
}
|
||||
|
||||
#endif // TREE_SITTER_FEATURE_WASM
|
||||
|
||||
#undef LOG
|
||||
|
|
|
|||
528
lib/src/wasm.c
Normal file
528
lib/src/wasm.c
Normal file
|
|
@ -0,0 +1,528 @@
|
|||
#include "tree_sitter/api.h"
|
||||
#include "./wasm/wasm.h"
|
||||
#include "./alloc.h"
|
||||
#include "./language.h"
|
||||
#include "./array.h"
|
||||
#include "./atomic.h"
|
||||
#include "./lexer.h"
|
||||
#include "./wasm.h"
|
||||
|
||||
static volatile uint32_t NEXT_LANGUAGE_ID;
|
||||
|
||||
typedef Array(char) StringData;
|
||||
|
||||
typedef struct {
|
||||
uint32_t version;
|
||||
uint32_t symbol_count;
|
||||
uint32_t alias_count;
|
||||
uint32_t token_count;
|
||||
uint32_t external_token_count;
|
||||
uint32_t state_count;
|
||||
uint32_t large_state_count;
|
||||
uint32_t production_id_count;
|
||||
uint32_t field_count;
|
||||
uint16_t max_alias_sequence_length;
|
||||
int32_t parse_table;
|
||||
int32_t small_parse_table;
|
||||
int32_t small_parse_table_map;
|
||||
int32_t parse_actions;
|
||||
int32_t symbol_names;
|
||||
int32_t field_names;
|
||||
int32_t field_map_slices;
|
||||
int32_t field_map_entries;
|
||||
int32_t symbol_metadata;
|
||||
int32_t public_symbol_map;
|
||||
int32_t alias_map;
|
||||
int32_t alias_sequences;
|
||||
int32_t lex_modes;
|
||||
int32_t lex_fn;
|
||||
int32_t keyword_lex_fn;
|
||||
TSSymbol keyword_capture_token;
|
||||
struct {
|
||||
int32_t states;
|
||||
int32_t symbol_map;
|
||||
int32_t create;
|
||||
int32_t destroy;
|
||||
int32_t scan;
|
||||
int32_t serialize;
|
||||
int32_t deserialize;
|
||||
} external_scanner;
|
||||
int32_t primary_state_ids;
|
||||
} LanguageInWasmMemory;
|
||||
|
||||
typedef struct {
|
||||
int32_t lookahead;
|
||||
TSSymbol result_symbol;
|
||||
int32_t advance;
|
||||
int32_t mark_end;
|
||||
int32_t get_column;
|
||||
int32_t is_at_included_range_start;
|
||||
int32_t eof;
|
||||
void *native_lexer_address;
|
||||
} LexerInWasmMemory;
|
||||
|
||||
static wasm_trap_t *advance_callback(
|
||||
void *env,
|
||||
const wasm_val_vec_t *args,
|
||||
wasm_val_vec_t *results
|
||||
) {
|
||||
assert(args->size == 2);
|
||||
assert(args->data[0].kind == WASM_I32);
|
||||
assert(args->data[1].kind == WASM_I32);
|
||||
|
||||
TSWasmStore *store = env;
|
||||
TSLexer *lexer = store->current_lexer;
|
||||
int32_t lexer_address = args->data[0].of.i32;
|
||||
bool skip = args->data[1].of.i32;
|
||||
|
||||
lexer->advance(lexer, skip);
|
||||
char *memory = wasm_memory_data(store->memory);
|
||||
memcpy(&memory[lexer_address], &lexer->lookahead, sizeof(lexer->lookahead));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static wasm_trap_t *mark_end_callback(
|
||||
void *env,
|
||||
const wasm_val_vec_t *args,
|
||||
wasm_val_vec_t *results
|
||||
) {
|
||||
assert(args->size == 1);
|
||||
assert(args->data[0].kind == WASM_I32);
|
||||
TSWasmStore *store = env;
|
||||
TSLexer *lexer = store->current_lexer;
|
||||
lexer->mark_end(lexer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static wasm_trap_t *get_column_callback(
|
||||
void *env,
|
||||
const wasm_val_vec_t *args,
|
||||
wasm_val_vec_t *results
|
||||
) {
|
||||
assert(args->size == 1);
|
||||
assert(args->data[0].kind == WASM_I32);
|
||||
TSWasmStore *store = env;
|
||||
TSLexer *lexer = store->current_lexer;
|
||||
wasm_val_t result = WASM_I32_VAL(lexer->get_column(lexer));
|
||||
results->data[0] = result;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static wasm_trap_t *is_at_included_range_start_callback(
|
||||
void *env,
|
||||
const wasm_val_vec_t *args,
|
||||
wasm_val_vec_t *results
|
||||
) {
|
||||
assert(args->size == 1);
|
||||
assert(args->data[0].kind == WASM_I32);
|
||||
TSWasmStore *store = env;
|
||||
TSLexer *lexer = store->current_lexer;
|
||||
wasm_val_t result = WASM_I32_VAL(lexer->is_at_included_range_start(lexer));
|
||||
results->data[0] = result;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static wasm_trap_t *eof_callback(
|
||||
void *env,
|
||||
const wasm_val_vec_t *args,
|
||||
wasm_val_vec_t *results
|
||||
) {
|
||||
assert(args->size == 1);
|
||||
assert(args->data[0].kind == WASM_I32);
|
||||
TSWasmStore *store = env;
|
||||
TSLexer *lexer = store->current_lexer;
|
||||
wasm_val_t result = WASM_I32_VAL(lexer->eof(lexer));
|
||||
results->data[0] = result;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
wasm_func_callback_with_env_t callback;
|
||||
wasm_functype_t *type;
|
||||
} FunctionDefinition;
|
||||
|
||||
#define array_len(a) (sizeof(a) / sizeof(a[0]))
|
||||
|
||||
static void *copy(const void *data, size_t size) {
|
||||
void *result = ts_malloc(size);
|
||||
memcpy(result, data, size);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void *copy_strings(
|
||||
const char *data,
|
||||
int32_t array_address,
|
||||
size_t count,
|
||||
StringData *string_data
|
||||
) {
|
||||
const char **result = ts_malloc(count * sizeof(char *));
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
int32_t address;
|
||||
memcpy(&address, &data[array_address + i * sizeof(address)], sizeof(address));
|
||||
const char *string = &data[address];
|
||||
uint32_t len = strlen(string);
|
||||
result[i] = (const char *)(uintptr_t)string_data->size;
|
||||
array_extend(string_data, len + 1, string);
|
||||
}
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
result[i] = string_data->contents + (uintptr_t)result[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool name_eq(const wasm_name_t *name, const char *string) {
|
||||
return strncmp(string, name->data, name->size) == 0;
|
||||
}
|
||||
|
||||
TSWasmStore *ts_wasm_store_new(TSWasmEngine *engine) {
|
||||
TSWasmStore *self = ts_malloc(sizeof(TSWasmStore));
|
||||
wasm_store_t *store = wasm_store_new(engine);
|
||||
|
||||
// Memory
|
||||
wasm_limits_t memory_limits = {.min = 64, .max = wasm_limits_max_default};
|
||||
wasm_memorytype_t *memory_type = wasm_memorytype_new(&memory_limits);
|
||||
wasm_memory_t *memory = wasm_memory_new(store, memory_type);
|
||||
wasm_memorytype_delete(memory_type);
|
||||
|
||||
// Lexer functions
|
||||
FunctionDefinition definitions[] = {
|
||||
{advance_callback, wasm_functype_new_2_0(wasm_valtype_new_i32(), wasm_valtype_new_i32())},
|
||||
{mark_end_callback, wasm_functype_new_1_0(wasm_valtype_new_i32())},
|
||||
{get_column_callback, wasm_functype_new_1_1(wasm_valtype_new_i32(), wasm_valtype_new_i32())},
|
||||
{is_at_included_range_start_callback, wasm_functype_new_1_1(wasm_valtype_new_i32(), wasm_valtype_new_i32())},
|
||||
{eof_callback, wasm_functype_new_1_1(wasm_valtype_new_i32(), wasm_valtype_new_i32())},
|
||||
};
|
||||
unsigned definitions_len = array_len(definitions);
|
||||
|
||||
// Function table
|
||||
wasm_limits_t table_limits = {.min = definitions_len, .max = wasm_limits_max_default};
|
||||
wasm_tabletype_t *table_type = wasm_tabletype_new(wasm_valtype_new(WASM_FUNCREF), &table_limits);
|
||||
wasm_table_t *function_table = wasm_table_new(store, table_type, NULL);
|
||||
wasm_tabletype_delete(table_type);
|
||||
|
||||
wasm_table_grow(function_table, definitions_len, NULL);
|
||||
for (unsigned i = 0; i < definitions_len; i++) {
|
||||
FunctionDefinition *definition = &definitions[i];
|
||||
wasm_func_t *func = wasm_func_new_with_env(store, definition->type, definition->callback, self, NULL);
|
||||
wasm_table_set(function_table, i, (wasm_ref_t *)func);
|
||||
wasm_functype_delete(definition->type);
|
||||
}
|
||||
|
||||
*self = (TSWasmStore) {
|
||||
.store = store,
|
||||
.memory = memory,
|
||||
.language_instances = array_new(),
|
||||
.function_table = function_table,
|
||||
};
|
||||
return self;
|
||||
}
|
||||
|
||||
void ts_wasm_store_delete(TSWasmStore *self) {
|
||||
wasm_memory_delete(self->memory);
|
||||
wasm_table_delete(self->function_table);
|
||||
wasm_store_delete(self->store);
|
||||
array_delete(&self->language_instances);
|
||||
ts_free(self);
|
||||
}
|
||||
|
||||
void ts_wasm_language_delete(const TSWasmLanguage *self) {
|
||||
assert(self->ref_count > 0);
|
||||
if (atomic_dec((volatile uint32_t *)&self->ref_count) == 0) {
|
||||
wasm_shared_module_delete(self->module);
|
||||
ts_free((void *)self->language->alias_map);
|
||||
ts_free((void *)self->language->alias_sequences);
|
||||
ts_free((void *)self->language->parse_table);
|
||||
ts_free((void *)self->language->parse_actions);
|
||||
ts_free((void *)self->language->primary_state_ids);
|
||||
ts_free((void *)self->language->public_symbol_map);
|
||||
ts_free(self->language);
|
||||
ts_free(self->symbol_name_buffer);
|
||||
ts_free(self->field_name_buffer);
|
||||
ts_free((void *)self);
|
||||
}
|
||||
}
|
||||
|
||||
void ts_wasm_language_retain(const TSWasmLanguage *self) {
|
||||
atomic_inc((volatile uint32_t *)&self->ref_count);
|
||||
}
|
||||
|
||||
static bool ts_wasm_store__instantiate(
|
||||
TSWasmStore *self,
|
||||
wasm_module_t *module,
|
||||
const char *language_name,
|
||||
wasm_instance_t **result,
|
||||
int32_t *language_address
|
||||
) {
|
||||
// Build language function name string.
|
||||
unsigned prefix_len = strlen("tree_sitter_");
|
||||
unsigned name_len = strlen(language_name);
|
||||
char language_function_name[prefix_len + name_len + 1];
|
||||
memcpy(&language_function_name[0], "tree_sitter_", prefix_len);
|
||||
memcpy(&language_function_name[prefix_len], language_name, name_len);
|
||||
language_function_name[prefix_len + name_len] = '\0';
|
||||
|
||||
wasm_importtype_vec_t import_types = WASM_EMPTY_VEC;
|
||||
wasm_module_imports(module, &import_types);
|
||||
|
||||
wasm_globaltype_t *const_i32_type = wasm_globaltype_new(wasm_valtype_new_i32(), WASM_CONST);
|
||||
wasm_val_t table_base_val = WASM_I32_VAL(5);
|
||||
wasm_val_t memory_base_val = WASM_I32_VAL(1600);
|
||||
wasm_global_t *memory_base_global = wasm_global_new(self->store, const_i32_type, &memory_base_val);
|
||||
wasm_global_t *table_base_global = wasm_global_new(self->store, const_i32_type, &table_base_val);
|
||||
wasm_globaltype_delete(const_i32_type);
|
||||
|
||||
// Build imports list
|
||||
printf("import count: %lu\n", import_types.size);
|
||||
wasm_extern_t *imports_list[import_types.size];
|
||||
wasm_extern_vec_t imports = WASM_ARRAY_VEC(imports_list);
|
||||
for (unsigned i = 0; i < import_types.size; i++) {
|
||||
const wasm_importtype_t *import_type = import_types.data[i];
|
||||
const wasm_name_t *import_name = wasm_importtype_name(import_type);
|
||||
|
||||
if (name_eq(import_name, "__memory_base")) {
|
||||
imports.data[i] = wasm_global_as_extern(memory_base_global);
|
||||
} else if (name_eq(import_name, "__table_base")) {
|
||||
imports.data[i] = wasm_global_as_extern(table_base_global);
|
||||
} else if (name_eq(import_name, "memory")) {
|
||||
imports.data[i] = wasm_memory_as_extern(self->memory);
|
||||
} else if (name_eq(import_name, "__indirect_function_table")) {
|
||||
imports.data[i] = wasm_table_as_extern(self->function_table);
|
||||
} else {
|
||||
printf("unexpected import '%.*s'\n", (int)import_name->size, import_name->data);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
wasm_importtype_vec_delete(&import_types);
|
||||
|
||||
wasm_trap_t *trap = NULL;
|
||||
wasm_instance_t *instance = wasm_instance_new(self->store, module, &imports, &trap);
|
||||
if (trap) {
|
||||
wasm_message_t message;
|
||||
wasm_trap_message(trap, &message);
|
||||
printf("error loading wasm: %s\n", message.data);
|
||||
abort();
|
||||
}
|
||||
|
||||
wasm_extern_vec_t exports = WASM_EMPTY_VEC;
|
||||
wasm_exporttype_vec_t export_types = WASM_EMPTY_VEC;
|
||||
wasm_module_exports(module, &export_types);
|
||||
wasm_instance_exports(instance, &exports);
|
||||
assert(export_types.size == exports.size);
|
||||
printf("export count: %lu\n", export_types.size);
|
||||
|
||||
wasm_extern_t *language_extern = NULL;
|
||||
for (unsigned i = 0; i < exports.size; i++) {
|
||||
wasm_extern_t *export = exports.data[i];
|
||||
wasm_exporttype_t *export_type = export_types.data[i];
|
||||
const wasm_name_t *name = wasm_exporttype_name(export_type);
|
||||
printf(" export name: %.*s\n", (int)name->size, name->data);
|
||||
|
||||
// Update pointers to reflect memory and function table offsets.
|
||||
if (name_eq(name, "__wasm_apply_data_relocs")) {
|
||||
wasm_func_t *apply_relocation_func = wasm_extern_as_func(export);
|
||||
wasm_val_vec_t arguments = WASM_EMPTY_VEC;
|
||||
wasm_val_vec_t results = WASM_EMPTY_VEC;
|
||||
wasm_trap_t *trap = wasm_func_call(apply_relocation_func, &arguments, &results);
|
||||
if (trap) {
|
||||
wasm_message_t message;
|
||||
wasm_trap_message(trap, &message);
|
||||
printf("error calling relocation function: %s\n", message.data);
|
||||
abort();
|
||||
}
|
||||
} else if (name_eq(name, language_function_name)) {
|
||||
language_extern = export;
|
||||
}
|
||||
}
|
||||
wasm_exporttype_vec_delete(&export_types);
|
||||
|
||||
if (!language_extern) {
|
||||
printf("failed to find function %s\n", language_function_name);
|
||||
abort();
|
||||
}
|
||||
|
||||
wasm_func_t *language_func = wasm_extern_as_func(language_extern);
|
||||
wasm_val_vec_t arguments = WASM_EMPTY_VEC;
|
||||
wasm_val_vec_t results = WASM_EMPTY_VEC;
|
||||
wasm_val_vec_new_uninitialized(&results, 1);
|
||||
trap = wasm_func_call(language_func, &arguments, &results);
|
||||
if (trap) {
|
||||
wasm_message_t message;
|
||||
wasm_trap_message(trap, &message);
|
||||
printf("error calling language function: %s\n", message.data);
|
||||
abort();
|
||||
}
|
||||
|
||||
wasm_val_t language_address_val = results.data[0];
|
||||
assert(language_address_val.kind == WASM_I32);
|
||||
|
||||
*result = instance;
|
||||
*language_address = language_address_val.of.i32;
|
||||
return true;
|
||||
}
|
||||
|
||||
TSWasmLanguage *ts_wasm_store_load_language(
|
||||
TSWasmStore *self,
|
||||
const char *language_name,
|
||||
const char *wasm,
|
||||
uint32_t wasm_len
|
||||
) {
|
||||
// Instantiate module.
|
||||
wasm_byte_vec_t file = {.size = wasm_len, .data = (char *)wasm};
|
||||
wasm_module_t *module = wasm_module_new(self->store, &file);
|
||||
|
||||
wasm_instance_t *instance;
|
||||
int32_t language_address;
|
||||
if (!ts_wasm_store__instantiate(self, module, language_name, &instance, &language_address)) return NULL;
|
||||
|
||||
LanguageInWasmMemory wasm_language;
|
||||
const byte_t *memory = wasm_memory_data(self->memory);
|
||||
memcpy(&wasm_language, &memory[language_address], sizeof(LanguageInWasmMemory));
|
||||
|
||||
TSLanguage *language = ts_malloc(sizeof(TSLanguage));
|
||||
StringData symbol_name_buffer = array_new();
|
||||
StringData field_name_buffer = array_new();
|
||||
|
||||
*language = (TSLanguage) {
|
||||
.version = wasm_language.version,
|
||||
.symbol_count = wasm_language.symbol_count,
|
||||
.alias_count = wasm_language.alias_count,
|
||||
.token_count = wasm_language.token_count,
|
||||
.external_token_count = wasm_language.external_token_count,
|
||||
.state_count = wasm_language.state_count,
|
||||
.large_state_count = wasm_language.large_state_count,
|
||||
.production_id_count = wasm_language.production_id_count,
|
||||
.field_count = wasm_language.field_count,
|
||||
.max_alias_sequence_length = wasm_language.max_alias_sequence_length,
|
||||
.keyword_capture_token = wasm_language.keyword_capture_token,
|
||||
.parse_table = copy(
|
||||
&memory[wasm_language.parse_table],
|
||||
wasm_language.large_state_count * wasm_language.symbol_count * sizeof(uint16_t)
|
||||
),
|
||||
.parse_actions = copy(
|
||||
&memory[wasm_language.parse_actions],
|
||||
3000 // TODO - determine number of parse actions
|
||||
),
|
||||
.symbol_names = copy_strings(
|
||||
memory,
|
||||
wasm_language.symbol_names,
|
||||
wasm_language.symbol_count,
|
||||
&symbol_name_buffer
|
||||
),
|
||||
.symbol_metadata = copy(
|
||||
&memory[wasm_language.symbol_metadata],
|
||||
wasm_language.symbol_count * sizeof(TSSymbolMetadata)
|
||||
),
|
||||
.public_symbol_map = copy(
|
||||
&memory[wasm_language.public_symbol_map],
|
||||
wasm_language.symbol_count * sizeof(TSSymbol)
|
||||
),
|
||||
.lex_modes = copy(
|
||||
&memory[wasm_language.lex_modes],
|
||||
wasm_language.state_count * sizeof(TSLexMode)
|
||||
),
|
||||
};
|
||||
|
||||
if (language->field_count > 0 && language->production_id_count > 0) {
|
||||
language->field_map_slices = copy(
|
||||
&memory[wasm_language.field_map_slices],
|
||||
wasm_language.production_id_count * sizeof(TSFieldMapSlice)
|
||||
);
|
||||
const TSFieldMapSlice last_field_map_slice = language->field_map_slices[language->production_id_count - 1];
|
||||
language->field_map_entries = copy(
|
||||
&memory[wasm_language.field_map_entries],
|
||||
(last_field_map_slice.index + last_field_map_slice.length) * sizeof(TSFieldMapEntry)
|
||||
);
|
||||
language->field_names = copy_strings(
|
||||
memory,
|
||||
wasm_language.field_names,
|
||||
wasm_language.field_count,
|
||||
&field_name_buffer
|
||||
);
|
||||
}
|
||||
|
||||
if (language->alias_count > 0 && language->production_id_count > 0) {
|
||||
// The alias map contains symbols, alias counts, and aliases, terminated by a null symbol.
|
||||
int32_t alias_map_size = 0;
|
||||
for (;;) {
|
||||
TSSymbol symbol;
|
||||
memcpy(&symbol, &memory[wasm_language.alias_map + alias_map_size], sizeof(symbol));
|
||||
alias_map_size += sizeof(TSSymbol);
|
||||
if (symbol == 0) break;
|
||||
uint16_t value_count;
|
||||
memcpy(&value_count, &memory[wasm_language.alias_map + alias_map_size], sizeof(value_count));
|
||||
alias_map_size += value_count * sizeof(TSSymbol);
|
||||
}
|
||||
language->alias_map = copy(
|
||||
&memory[wasm_language.alias_map],
|
||||
alias_map_size
|
||||
);
|
||||
language->alias_sequences = copy(
|
||||
&memory[wasm_language.alias_sequences],
|
||||
wasm_language.production_id_count * wasm_language.max_alias_sequence_length * sizeof(TSSymbol)
|
||||
);
|
||||
}
|
||||
|
||||
if (language->state_count > language->large_state_count) {
|
||||
uint32_t small_state_count = wasm_language.state_count - wasm_language.large_state_count;
|
||||
language->small_parse_table_map = copy(
|
||||
&memory[wasm_language.small_parse_table_map],
|
||||
small_state_count * sizeof(uint32_t)
|
||||
);
|
||||
uint32_t index = language->small_parse_table_map[small_state_count - 1];
|
||||
language->small_parse_table = copy(
|
||||
&memory[wasm_language.small_parse_table],
|
||||
(index + 64) * sizeof(uint16_t) // TODO - determine actual size
|
||||
);
|
||||
}
|
||||
|
||||
TSWasmLanguage *result = ts_malloc(sizeof(TSWasmLanguage));
|
||||
*result = (TSWasmLanguage) {
|
||||
.id = atomic_inc(&NEXT_LANGUAGE_ID),
|
||||
.ref_count = 1,
|
||||
.module = wasm_module_share(module),
|
||||
.language = language,
|
||||
.symbol_name_buffer = symbol_name_buffer.contents,
|
||||
.field_name_buffer = field_name_buffer.contents,
|
||||
};
|
||||
array_push(&self->language_instances, ((LanguageInstance) {
|
||||
.instance = instance,
|
||||
.external_scan_index = wasm_language.external_scanner.scan,
|
||||
.keyword_lex_fn_index = wasm_language.keyword_lex_fn,
|
||||
.main_lex_fn_index = wasm_language.lex_fn,
|
||||
}));
|
||||
return result;
|
||||
}
|
||||
|
||||
bool ts_wasm_store_start(TSWasmStore *self, TSLexer *lexer, const TSWasmLanguage *language) {
|
||||
uint32_t instance_index = 0;
|
||||
bool exists = false;
|
||||
array_search_sorted_by(&self->language_instances, .id, language->id, &instance_index, &exists);
|
||||
|
||||
if (!exists) {
|
||||
wasm_module_t *module = wasm_module_obtain(self->store, language->module);
|
||||
wasm_instance_t *instance;
|
||||
int32_t language_address;
|
||||
if (!ts_wasm_store__instantiate(self, module, language->name, &instance, &language_address)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
LanguageInWasmMemory wasm_language;
|
||||
const byte_t *memory = wasm_memory_data(self->memory);
|
||||
memcpy(&wasm_language, &memory[language_address], sizeof(LanguageInWasmMemory));
|
||||
array_insert(&self->language_instances, instance_index, ((LanguageInstance) {
|
||||
.id = language->id,
|
||||
.instance = instance,
|
||||
.main_lex_fn_index = wasm_language.lex_fn,
|
||||
.keyword_lex_fn_index = wasm_language.keyword_lex_fn,
|
||||
}));
|
||||
}
|
||||
|
||||
self->current_lexer = lexer;
|
||||
self->current_instance = &self->language_instances.contents[instance_index];
|
||||
return true;
|
||||
}
|
||||
|
||||
void ts_wasm_store_stop(TSWasmStore *self) {
|
||||
self->current_lexer = NULL;
|
||||
self->current_instance = NULL;
|
||||
}
|
||||
83
lib/src/wasm.h
Normal file
83
lib/src/wasm.h
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
#ifndef TREE_SITTER_WASM_H_
|
||||
#define TREE_SITTER_WASM_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "./array.h"
|
||||
#include "./wasm/wasm.h"
|
||||
#include "./lexer.h"
|
||||
|
||||
typedef struct {
|
||||
uint32_t id;
|
||||
wasm_instance_t *instance;
|
||||
uint32_t main_lex_fn_index;
|
||||
uint32_t keyword_lex_fn_index;
|
||||
uint32_t external_scan_index;
|
||||
} LanguageInstance;
|
||||
|
||||
struct TSWasmStore {
|
||||
wasm_store_t *store;
|
||||
wasm_table_t *function_table;
|
||||
wasm_memory_t *memory;
|
||||
TSLexer *current_lexer;
|
||||
LanguageInstance *current_instance;
|
||||
Array(LanguageInstance) language_instances;
|
||||
};
|
||||
|
||||
struct TSWasmLanguage {
|
||||
uint32_t id;
|
||||
volatile uint32_t ref_count;
|
||||
wasm_shared_module_t *module;
|
||||
TSLanguage *language;
|
||||
const char *name;
|
||||
char *symbol_name_buffer;
|
||||
char *field_name_buffer;
|
||||
};
|
||||
|
||||
void ts_wasm_language_retain(const TSWasmLanguage *);
|
||||
bool ts_wasm_store_start(TSWasmStore *self, TSLexer *lexer, const TSWasmLanguage *language);
|
||||
void ts_wasm_store_stop(TSWasmStore *self);
|
||||
|
||||
static inline bool ts_wasm_store_run_main_lex_function(TSWasmStore *self, TSStateId state) {
|
||||
uint32_t function_index = self->current_instance->main_lex_fn_index;
|
||||
wasm_ref_t *lex_ref = wasm_table_get(self->function_table, function_index);
|
||||
wasm_func_t *lex_func = wasm_ref_as_func(lex_ref);
|
||||
wasm_val_t args_list[2] = {
|
||||
WASM_I32_VAL(state),
|
||||
WASM_I32_VAL(state),
|
||||
};
|
||||
wasm_val_t results_list[1] = {
|
||||
WASM_I32_VAL(0),
|
||||
};
|
||||
wasm_val_vec_t args = WASM_ARRAY_VEC(args_list);
|
||||
wasm_val_vec_t results = WASM_ARRAY_VEC(results_list);
|
||||
wasm_func_call(lex_func, &args, &results);
|
||||
assert(results_list[0].kind == WASM_I32);
|
||||
return results_list[0].of.i32;
|
||||
}
|
||||
|
||||
static inline bool ts_wasm_store_run_keyword_lex_function(TSWasmStore *self, TSStateId state) {
|
||||
uint32_t function_index = self->current_instance->keyword_lex_fn_index;
|
||||
wasm_ref_t *lex_ref = wasm_table_get(self->function_table, function_index);
|
||||
wasm_func_t *lex_func = wasm_ref_as_func(lex_ref);
|
||||
wasm_val_t args_list[2] = {
|
||||
WASM_I32_VAL(state),
|
||||
WASM_I32_VAL(state),
|
||||
};
|
||||
wasm_val_t results_list[1] = {
|
||||
WASM_I32_VAL(0),
|
||||
};
|
||||
wasm_val_vec_t args = WASM_ARRAY_VEC(args_list);
|
||||
wasm_val_vec_t results = WASM_ARRAY_VEC(results_list);
|
||||
wasm_func_call(lex_func, &args, &results);
|
||||
assert(results_list[0].kind == WASM_I32);
|
||||
return results_list[0].of.i32;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // TREE_SITTER_WASM_H_
|
||||
6
lib/src/wasm/README.md
Normal file
6
lib/src/wasm/README.md
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
## WASM
|
||||
|
||||
The `wasm.h` header file contains a standard interface implemented by multiple WASM implementations.
|
||||
It was taken from here:
|
||||
|
||||
https://github.com/WebAssembly/wasm-c-api/blob/c9d31284651b975f05ac27cee0bab1377560b87e/include/wasm.h
|
||||
714
lib/src/wasm/wasm.h
Normal file
714
lib/src/wasm/wasm.h
Normal file
|
|
@ -0,0 +1,714 @@
|
|||
// WebAssembly C API
|
||||
|
||||
#ifndef WASM_H
|
||||
#define WASM_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifndef WASM_API_EXTERN
|
||||
#ifdef _WIN32
|
||||
#define WASM_API_EXTERN __declspec(dllimport)
|
||||
#else
|
||||
#define WASM_API_EXTERN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Auxiliaries
|
||||
|
||||
// Machine types
|
||||
|
||||
typedef char byte_t;
|
||||
typedef float float32_t;
|
||||
typedef double float64_t;
|
||||
|
||||
// Ownership
|
||||
|
||||
#define own
|
||||
|
||||
// The qualifier `own` is used to indicate ownership of data in this API.
|
||||
// It is intended to be interpreted similar to a `const` qualifier:
|
||||
//
|
||||
// - `own wasm_xxx_t*` owns the pointed-to data
|
||||
// - `own wasm_xxx_t` distributes to all fields of a struct or union `xxx`
|
||||
// - `own wasm_xxx_vec_t` owns the vector as well as its elements(!)
|
||||
// - an `own` function parameter passes ownership from caller to callee
|
||||
// - an `own` function result passes ownership from callee to caller
|
||||
// - an exception are `own` pointer parameters named `out`, which are copy-back
|
||||
// output parameters passing back ownership from callee to caller
|
||||
//
|
||||
// Own data is created by `wasm_xxx_new` functions and some others.
|
||||
// It must be released with the corresponding `wasm_xxx_delete` function.
|
||||
//
|
||||
// Deleting a reference does not necessarily delete the underlying object,
|
||||
// it merely indicates that this owner no longer uses it.
|
||||
//
|
||||
// For vectors, `const wasm_xxx_vec_t` is used informally to indicate that
|
||||
// neither the vector nor its elements should be modified.
|
||||
// TODO: introduce proper `wasm_xxx_const_vec_t`?
|
||||
|
||||
|
||||
#define WASM_DECLARE_OWN(name) \
|
||||
typedef struct wasm_##name##_t wasm_##name##_t; \
|
||||
\
|
||||
WASM_API_EXTERN void wasm_##name##_delete(own wasm_##name##_t*);
|
||||
|
||||
|
||||
// Vectors
|
||||
|
||||
#define WASM_DECLARE_VEC(name, ptr_or_none) \
|
||||
typedef struct wasm_##name##_vec_t { \
|
||||
size_t size; \
|
||||
wasm_##name##_t ptr_or_none* data; \
|
||||
} wasm_##name##_vec_t; \
|
||||
\
|
||||
WASM_API_EXTERN void wasm_##name##_vec_new_empty(own wasm_##name##_vec_t* out); \
|
||||
WASM_API_EXTERN void wasm_##name##_vec_new_uninitialized( \
|
||||
own wasm_##name##_vec_t* out, size_t); \
|
||||
WASM_API_EXTERN void wasm_##name##_vec_new( \
|
||||
own wasm_##name##_vec_t* out, \
|
||||
size_t, own wasm_##name##_t ptr_or_none const[]); \
|
||||
WASM_API_EXTERN void wasm_##name##_vec_copy( \
|
||||
own wasm_##name##_vec_t* out, const wasm_##name##_vec_t*); \
|
||||
WASM_API_EXTERN void wasm_##name##_vec_delete(own wasm_##name##_vec_t*);
|
||||
|
||||
|
||||
// Byte vectors
|
||||
|
||||
typedef byte_t wasm_byte_t;
|
||||
WASM_DECLARE_VEC(byte, )
|
||||
|
||||
typedef wasm_byte_vec_t wasm_name_t;
|
||||
|
||||
#define wasm_name wasm_byte_vec
|
||||
#define wasm_name_new wasm_byte_vec_new
|
||||
#define wasm_name_new_empty wasm_byte_vec_new_empty
|
||||
#define wasm_name_new_new_uninitialized wasm_byte_vec_new_uninitialized
|
||||
#define wasm_name_copy wasm_byte_vec_copy
|
||||
#define wasm_name_delete wasm_byte_vec_delete
|
||||
|
||||
static inline void wasm_name_new_from_string(
|
||||
own wasm_name_t* out, const char* s
|
||||
) {
|
||||
wasm_name_new(out, strlen(s), s);
|
||||
}
|
||||
|
||||
static inline void wasm_name_new_from_string_nt(
|
||||
own wasm_name_t* out, const char* s
|
||||
) {
|
||||
wasm_name_new(out, strlen(s) + 1, s);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Runtime Environment
|
||||
|
||||
// Configuration
|
||||
|
||||
WASM_DECLARE_OWN(config)
|
||||
|
||||
WASM_API_EXTERN own wasm_config_t* wasm_config_new(void);
|
||||
|
||||
// Embedders may provide custom functions for manipulating configs.
|
||||
|
||||
|
||||
// Engine
|
||||
|
||||
WASM_DECLARE_OWN(engine)
|
||||
|
||||
WASM_API_EXTERN own wasm_engine_t* wasm_engine_new(void);
|
||||
WASM_API_EXTERN own wasm_engine_t* wasm_engine_new_with_config(own wasm_config_t*);
|
||||
|
||||
|
||||
// Store
|
||||
|
||||
WASM_DECLARE_OWN(store)
|
||||
|
||||
WASM_API_EXTERN own wasm_store_t* wasm_store_new(wasm_engine_t*);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Type Representations
|
||||
|
||||
// Type attributes
|
||||
|
||||
typedef uint8_t wasm_mutability_t;
|
||||
enum wasm_mutability_enum {
|
||||
WASM_CONST,
|
||||
WASM_VAR,
|
||||
};
|
||||
|
||||
typedef struct wasm_limits_t {
|
||||
uint32_t min;
|
||||
uint32_t max;
|
||||
} wasm_limits_t;
|
||||
|
||||
static const uint32_t wasm_limits_max_default = 0xffffffff;
|
||||
|
||||
|
||||
// Generic
|
||||
|
||||
#define WASM_DECLARE_TYPE(name) \
|
||||
WASM_DECLARE_OWN(name) \
|
||||
WASM_DECLARE_VEC(name, *) \
|
||||
\
|
||||
WASM_API_EXTERN own wasm_##name##_t* wasm_##name##_copy(const wasm_##name##_t*);
|
||||
|
||||
|
||||
// Value Types
|
||||
|
||||
WASM_DECLARE_TYPE(valtype)
|
||||
|
||||
typedef uint8_t wasm_valkind_t;
|
||||
enum wasm_valkind_enum {
|
||||
WASM_I32,
|
||||
WASM_I64,
|
||||
WASM_F32,
|
||||
WASM_F64,
|
||||
WASM_ANYREF = 128,
|
||||
WASM_FUNCREF,
|
||||
};
|
||||
|
||||
WASM_API_EXTERN own wasm_valtype_t* wasm_valtype_new(wasm_valkind_t);
|
||||
|
||||
WASM_API_EXTERN wasm_valkind_t wasm_valtype_kind(const wasm_valtype_t*);
|
||||
|
||||
static inline bool wasm_valkind_is_num(wasm_valkind_t k) {
|
||||
return k < WASM_ANYREF;
|
||||
}
|
||||
static inline bool wasm_valkind_is_ref(wasm_valkind_t k) {
|
||||
return k >= WASM_ANYREF;
|
||||
}
|
||||
|
||||
static inline bool wasm_valtype_is_num(const wasm_valtype_t* t) {
|
||||
return wasm_valkind_is_num(wasm_valtype_kind(t));
|
||||
}
|
||||
static inline bool wasm_valtype_is_ref(const wasm_valtype_t* t) {
|
||||
return wasm_valkind_is_ref(wasm_valtype_kind(t));
|
||||
}
|
||||
|
||||
|
||||
// Function Types
|
||||
|
||||
WASM_DECLARE_TYPE(functype)
|
||||
|
||||
WASM_API_EXTERN own wasm_functype_t* wasm_functype_new(
|
||||
own wasm_valtype_vec_t* params, own wasm_valtype_vec_t* results);
|
||||
|
||||
WASM_API_EXTERN const wasm_valtype_vec_t* wasm_functype_params(const wasm_functype_t*);
|
||||
WASM_API_EXTERN const wasm_valtype_vec_t* wasm_functype_results(const wasm_functype_t*);
|
||||
|
||||
|
||||
// Global Types
|
||||
|
||||
WASM_DECLARE_TYPE(globaltype)
|
||||
|
||||
WASM_API_EXTERN own wasm_globaltype_t* wasm_globaltype_new(
|
||||
own wasm_valtype_t*, wasm_mutability_t);
|
||||
|
||||
WASM_API_EXTERN const wasm_valtype_t* wasm_globaltype_content(const wasm_globaltype_t*);
|
||||
WASM_API_EXTERN wasm_mutability_t wasm_globaltype_mutability(const wasm_globaltype_t*);
|
||||
|
||||
|
||||
// Table Types
|
||||
|
||||
WASM_DECLARE_TYPE(tabletype)
|
||||
|
||||
WASM_API_EXTERN own wasm_tabletype_t* wasm_tabletype_new(
|
||||
own wasm_valtype_t*, const wasm_limits_t*);
|
||||
|
||||
WASM_API_EXTERN const wasm_valtype_t* wasm_tabletype_element(const wasm_tabletype_t*);
|
||||
WASM_API_EXTERN const wasm_limits_t* wasm_tabletype_limits(const wasm_tabletype_t*);
|
||||
|
||||
|
||||
// Memory Types
|
||||
|
||||
WASM_DECLARE_TYPE(memorytype)
|
||||
|
||||
WASM_API_EXTERN own wasm_memorytype_t* wasm_memorytype_new(const wasm_limits_t*);
|
||||
|
||||
WASM_API_EXTERN const wasm_limits_t* wasm_memorytype_limits(const wasm_memorytype_t*);
|
||||
|
||||
|
||||
// Extern Types
|
||||
|
||||
WASM_DECLARE_TYPE(externtype)
|
||||
|
||||
typedef uint8_t wasm_externkind_t;
|
||||
enum wasm_externkind_enum {
|
||||
WASM_EXTERN_FUNC,
|
||||
WASM_EXTERN_GLOBAL,
|
||||
WASM_EXTERN_TABLE,
|
||||
WASM_EXTERN_MEMORY,
|
||||
};
|
||||
|
||||
WASM_API_EXTERN wasm_externkind_t wasm_externtype_kind(const wasm_externtype_t*);
|
||||
|
||||
WASM_API_EXTERN wasm_externtype_t* wasm_functype_as_externtype(wasm_functype_t*);
|
||||
WASM_API_EXTERN wasm_externtype_t* wasm_globaltype_as_externtype(wasm_globaltype_t*);
|
||||
WASM_API_EXTERN wasm_externtype_t* wasm_tabletype_as_externtype(wasm_tabletype_t*);
|
||||
WASM_API_EXTERN wasm_externtype_t* wasm_memorytype_as_externtype(wasm_memorytype_t*);
|
||||
|
||||
WASM_API_EXTERN wasm_functype_t* wasm_externtype_as_functype(wasm_externtype_t*);
|
||||
WASM_API_EXTERN wasm_globaltype_t* wasm_externtype_as_globaltype(wasm_externtype_t*);
|
||||
WASM_API_EXTERN wasm_tabletype_t* wasm_externtype_as_tabletype(wasm_externtype_t*);
|
||||
WASM_API_EXTERN wasm_memorytype_t* wasm_externtype_as_memorytype(wasm_externtype_t*);
|
||||
|
||||
WASM_API_EXTERN const wasm_externtype_t* wasm_functype_as_externtype_const(const wasm_functype_t*);
|
||||
WASM_API_EXTERN const wasm_externtype_t* wasm_globaltype_as_externtype_const(const wasm_globaltype_t*);
|
||||
WASM_API_EXTERN const wasm_externtype_t* wasm_tabletype_as_externtype_const(const wasm_tabletype_t*);
|
||||
WASM_API_EXTERN const wasm_externtype_t* wasm_memorytype_as_externtype_const(const wasm_memorytype_t*);
|
||||
|
||||
WASM_API_EXTERN const wasm_functype_t* wasm_externtype_as_functype_const(const wasm_externtype_t*);
|
||||
WASM_API_EXTERN const wasm_globaltype_t* wasm_externtype_as_globaltype_const(const wasm_externtype_t*);
|
||||
WASM_API_EXTERN const wasm_tabletype_t* wasm_externtype_as_tabletype_const(const wasm_externtype_t*);
|
||||
WASM_API_EXTERN const wasm_memorytype_t* wasm_externtype_as_memorytype_const(const wasm_externtype_t*);
|
||||
|
||||
|
||||
// Import Types
|
||||
|
||||
WASM_DECLARE_TYPE(importtype)
|
||||
|
||||
WASM_API_EXTERN own wasm_importtype_t* wasm_importtype_new(
|
||||
own wasm_name_t* module, own wasm_name_t* name, own wasm_externtype_t*);
|
||||
|
||||
WASM_API_EXTERN const wasm_name_t* wasm_importtype_module(const wasm_importtype_t*);
|
||||
WASM_API_EXTERN const wasm_name_t* wasm_importtype_name(const wasm_importtype_t*);
|
||||
WASM_API_EXTERN const wasm_externtype_t* wasm_importtype_type(const wasm_importtype_t*);
|
||||
|
||||
|
||||
// Export Types
|
||||
|
||||
WASM_DECLARE_TYPE(exporttype)
|
||||
|
||||
WASM_API_EXTERN own wasm_exporttype_t* wasm_exporttype_new(
|
||||
own wasm_name_t*, own wasm_externtype_t*);
|
||||
|
||||
WASM_API_EXTERN const wasm_name_t* wasm_exporttype_name(const wasm_exporttype_t*);
|
||||
WASM_API_EXTERN const wasm_externtype_t* wasm_exporttype_type(const wasm_exporttype_t*);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Runtime Objects
|
||||
|
||||
// Values
|
||||
|
||||
struct wasm_ref_t;
|
||||
|
||||
typedef struct wasm_val_t {
|
||||
wasm_valkind_t kind;
|
||||
union {
|
||||
int32_t i32;
|
||||
int64_t i64;
|
||||
float32_t f32;
|
||||
float64_t f64;
|
||||
struct wasm_ref_t* ref;
|
||||
} of;
|
||||
} wasm_val_t;
|
||||
|
||||
WASM_API_EXTERN void wasm_val_delete(own wasm_val_t* v);
|
||||
WASM_API_EXTERN void wasm_val_copy(own wasm_val_t* out, const wasm_val_t*);
|
||||
|
||||
WASM_DECLARE_VEC(val, )
|
||||
|
||||
|
||||
// References
|
||||
|
||||
#define WASM_DECLARE_REF_BASE(name) \
|
||||
WASM_DECLARE_OWN(name) \
|
||||
\
|
||||
WASM_API_EXTERN own wasm_##name##_t* wasm_##name##_copy(const wasm_##name##_t*); \
|
||||
WASM_API_EXTERN bool wasm_##name##_same(const wasm_##name##_t*, const wasm_##name##_t*); \
|
||||
\
|
||||
WASM_API_EXTERN void* wasm_##name##_get_host_info(const wasm_##name##_t*); \
|
||||
WASM_API_EXTERN void wasm_##name##_set_host_info(wasm_##name##_t*, void*); \
|
||||
WASM_API_EXTERN void wasm_##name##_set_host_info_with_finalizer( \
|
||||
wasm_##name##_t*, void*, void (*)(void*));
|
||||
|
||||
#define WASM_DECLARE_REF(name) \
|
||||
WASM_DECLARE_REF_BASE(name) \
|
||||
\
|
||||
WASM_API_EXTERN wasm_ref_t* wasm_##name##_as_ref(wasm_##name##_t*); \
|
||||
WASM_API_EXTERN wasm_##name##_t* wasm_ref_as_##name(wasm_ref_t*); \
|
||||
WASM_API_EXTERN const wasm_ref_t* wasm_##name##_as_ref_const(const wasm_##name##_t*); \
|
||||
WASM_API_EXTERN const wasm_##name##_t* wasm_ref_as_##name##_const(const wasm_ref_t*);
|
||||
|
||||
#define WASM_DECLARE_SHARABLE_REF(name) \
|
||||
WASM_DECLARE_REF(name) \
|
||||
WASM_DECLARE_OWN(shared_##name) \
|
||||
\
|
||||
WASM_API_EXTERN own wasm_shared_##name##_t* wasm_##name##_share(const wasm_##name##_t*); \
|
||||
WASM_API_EXTERN own wasm_##name##_t* wasm_##name##_obtain(wasm_store_t*, const wasm_shared_##name##_t*);
|
||||
|
||||
|
||||
WASM_DECLARE_REF_BASE(ref)
|
||||
|
||||
|
||||
// Frames
|
||||
|
||||
WASM_DECLARE_OWN(frame)
|
||||
WASM_DECLARE_VEC(frame, *)
|
||||
WASM_API_EXTERN own wasm_frame_t* wasm_frame_copy(const wasm_frame_t*);
|
||||
|
||||
WASM_API_EXTERN struct wasm_instance_t* wasm_frame_instance(const wasm_frame_t*);
|
||||
WASM_API_EXTERN uint32_t wasm_frame_func_index(const wasm_frame_t*);
|
||||
WASM_API_EXTERN size_t wasm_frame_func_offset(const wasm_frame_t*);
|
||||
WASM_API_EXTERN size_t wasm_frame_module_offset(const wasm_frame_t*);
|
||||
|
||||
|
||||
// Traps
|
||||
|
||||
typedef wasm_name_t wasm_message_t; // null terminated
|
||||
|
||||
WASM_DECLARE_REF(trap)
|
||||
|
||||
WASM_API_EXTERN own wasm_trap_t* wasm_trap_new(wasm_store_t* store, const wasm_message_t*);
|
||||
|
||||
WASM_API_EXTERN void wasm_trap_message(const wasm_trap_t*, own wasm_message_t* out);
|
||||
WASM_API_EXTERN own wasm_frame_t* wasm_trap_origin(const wasm_trap_t*);
|
||||
WASM_API_EXTERN void wasm_trap_trace(const wasm_trap_t*, own wasm_frame_vec_t* out);
|
||||
|
||||
|
||||
// Foreign Objects
|
||||
|
||||
WASM_DECLARE_REF(foreign)
|
||||
|
||||
WASM_API_EXTERN own wasm_foreign_t* wasm_foreign_new(wasm_store_t*);
|
||||
|
||||
|
||||
// Modules
|
||||
|
||||
WASM_DECLARE_SHARABLE_REF(module)
|
||||
|
||||
WASM_API_EXTERN own wasm_module_t* wasm_module_new(
|
||||
wasm_store_t*, const wasm_byte_vec_t* binary);
|
||||
|
||||
WASM_API_EXTERN bool wasm_module_validate(wasm_store_t*, const wasm_byte_vec_t* binary);
|
||||
|
||||
WASM_API_EXTERN void wasm_module_imports(const wasm_module_t*, own wasm_importtype_vec_t* out);
|
||||
WASM_API_EXTERN void wasm_module_exports(const wasm_module_t*, own wasm_exporttype_vec_t* out);
|
||||
|
||||
WASM_API_EXTERN void wasm_module_serialize(const wasm_module_t*, own wasm_byte_vec_t* out);
|
||||
WASM_API_EXTERN own wasm_module_t* wasm_module_deserialize(wasm_store_t*, const wasm_byte_vec_t*);
|
||||
|
||||
|
||||
// Function Instances
|
||||
|
||||
WASM_DECLARE_REF(func)
|
||||
|
||||
typedef own wasm_trap_t* (*wasm_func_callback_t)(
|
||||
const wasm_val_vec_t* args, own wasm_val_vec_t* results);
|
||||
typedef own wasm_trap_t* (*wasm_func_callback_with_env_t)(
|
||||
void* env, const wasm_val_vec_t* args, wasm_val_vec_t* results);
|
||||
|
||||
WASM_API_EXTERN own wasm_func_t* wasm_func_new(
|
||||
wasm_store_t*, const wasm_functype_t*, wasm_func_callback_t);
|
||||
WASM_API_EXTERN own wasm_func_t* wasm_func_new_with_env(
|
||||
wasm_store_t*, const wasm_functype_t* type, wasm_func_callback_with_env_t,
|
||||
void* env, void (*finalizer)(void*));
|
||||
|
||||
WASM_API_EXTERN own wasm_functype_t* wasm_func_type(const wasm_func_t*);
|
||||
WASM_API_EXTERN size_t wasm_func_param_arity(const wasm_func_t*);
|
||||
WASM_API_EXTERN size_t wasm_func_result_arity(const wasm_func_t*);
|
||||
|
||||
WASM_API_EXTERN own wasm_trap_t* wasm_func_call(
|
||||
const wasm_func_t*, const wasm_val_vec_t* args, wasm_val_vec_t* results);
|
||||
|
||||
|
||||
// Global Instances
|
||||
|
||||
WASM_DECLARE_REF(global)
|
||||
|
||||
WASM_API_EXTERN own wasm_global_t* wasm_global_new(
|
||||
wasm_store_t*, const wasm_globaltype_t*, const wasm_val_t*);
|
||||
|
||||
WASM_API_EXTERN own wasm_globaltype_t* wasm_global_type(const wasm_global_t*);
|
||||
|
||||
WASM_API_EXTERN void wasm_global_get(const wasm_global_t*, own wasm_val_t* out);
|
||||
WASM_API_EXTERN void wasm_global_set(wasm_global_t*, const wasm_val_t*);
|
||||
|
||||
|
||||
// Table Instances
|
||||
|
||||
WASM_DECLARE_REF(table)
|
||||
|
||||
typedef uint32_t wasm_table_size_t;
|
||||
|
||||
WASM_API_EXTERN own wasm_table_t* wasm_table_new(
|
||||
wasm_store_t*, const wasm_tabletype_t*, wasm_ref_t* init);
|
||||
|
||||
WASM_API_EXTERN own wasm_tabletype_t* wasm_table_type(const wasm_table_t*);
|
||||
|
||||
WASM_API_EXTERN own wasm_ref_t* wasm_table_get(const wasm_table_t*, wasm_table_size_t index);
|
||||
WASM_API_EXTERN bool wasm_table_set(wasm_table_t*, wasm_table_size_t index, wasm_ref_t*);
|
||||
|
||||
WASM_API_EXTERN wasm_table_size_t wasm_table_size(const wasm_table_t*);
|
||||
WASM_API_EXTERN bool wasm_table_grow(wasm_table_t*, wasm_table_size_t delta, wasm_ref_t* init);
|
||||
|
||||
|
||||
// Memory Instances
|
||||
|
||||
WASM_DECLARE_REF(memory)
|
||||
|
||||
typedef uint32_t wasm_memory_pages_t;
|
||||
|
||||
static const size_t MEMORY_PAGE_SIZE = 0x10000;
|
||||
|
||||
WASM_API_EXTERN own wasm_memory_t* wasm_memory_new(wasm_store_t*, const wasm_memorytype_t*);
|
||||
|
||||
WASM_API_EXTERN own wasm_memorytype_t* wasm_memory_type(const wasm_memory_t*);
|
||||
|
||||
WASM_API_EXTERN byte_t* wasm_memory_data(wasm_memory_t*);
|
||||
WASM_API_EXTERN size_t wasm_memory_data_size(const wasm_memory_t*);
|
||||
|
||||
WASM_API_EXTERN wasm_memory_pages_t wasm_memory_size(const wasm_memory_t*);
|
||||
WASM_API_EXTERN bool wasm_memory_grow(wasm_memory_t*, wasm_memory_pages_t delta);
|
||||
|
||||
|
||||
// Externals
|
||||
|
||||
WASM_DECLARE_REF(extern)
|
||||
WASM_DECLARE_VEC(extern, *)
|
||||
|
||||
WASM_API_EXTERN wasm_externkind_t wasm_extern_kind(const wasm_extern_t*);
|
||||
WASM_API_EXTERN own wasm_externtype_t* wasm_extern_type(const wasm_extern_t*);
|
||||
|
||||
WASM_API_EXTERN wasm_extern_t* wasm_func_as_extern(wasm_func_t*);
|
||||
WASM_API_EXTERN wasm_extern_t* wasm_global_as_extern(wasm_global_t*);
|
||||
WASM_API_EXTERN wasm_extern_t* wasm_table_as_extern(wasm_table_t*);
|
||||
WASM_API_EXTERN wasm_extern_t* wasm_memory_as_extern(wasm_memory_t*);
|
||||
|
||||
WASM_API_EXTERN wasm_func_t* wasm_extern_as_func(wasm_extern_t*);
|
||||
WASM_API_EXTERN wasm_global_t* wasm_extern_as_global(wasm_extern_t*);
|
||||
WASM_API_EXTERN wasm_table_t* wasm_extern_as_table(wasm_extern_t*);
|
||||
WASM_API_EXTERN wasm_memory_t* wasm_extern_as_memory(wasm_extern_t*);
|
||||
|
||||
WASM_API_EXTERN const wasm_extern_t* wasm_func_as_extern_const(const wasm_func_t*);
|
||||
WASM_API_EXTERN const wasm_extern_t* wasm_global_as_extern_const(const wasm_global_t*);
|
||||
WASM_API_EXTERN const wasm_extern_t* wasm_table_as_extern_const(const wasm_table_t*);
|
||||
WASM_API_EXTERN const wasm_extern_t* wasm_memory_as_extern_const(const wasm_memory_t*);
|
||||
|
||||
WASM_API_EXTERN const wasm_func_t* wasm_extern_as_func_const(const wasm_extern_t*);
|
||||
WASM_API_EXTERN const wasm_global_t* wasm_extern_as_global_const(const wasm_extern_t*);
|
||||
WASM_API_EXTERN const wasm_table_t* wasm_extern_as_table_const(const wasm_extern_t*);
|
||||
WASM_API_EXTERN const wasm_memory_t* wasm_extern_as_memory_const(const wasm_extern_t*);
|
||||
|
||||
|
||||
// Module Instances
|
||||
|
||||
WASM_DECLARE_REF(instance)
|
||||
|
||||
WASM_API_EXTERN own wasm_instance_t* wasm_instance_new(
|
||||
wasm_store_t*, const wasm_module_t*, const wasm_extern_vec_t* imports,
|
||||
own wasm_trap_t**
|
||||
);
|
||||
|
||||
WASM_API_EXTERN void wasm_instance_exports(const wasm_instance_t*, own wasm_extern_vec_t* out);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Convenience
|
||||
|
||||
// Vectors
|
||||
|
||||
#define WASM_EMPTY_VEC {0, NULL}
|
||||
#define WASM_ARRAY_VEC(array) {sizeof(array)/sizeof(*(array)), array}
|
||||
|
||||
|
||||
// Value Type construction short-hands
|
||||
|
||||
static inline own wasm_valtype_t* wasm_valtype_new_i32(void) {
|
||||
return wasm_valtype_new(WASM_I32);
|
||||
}
|
||||
static inline own wasm_valtype_t* wasm_valtype_new_i64(void) {
|
||||
return wasm_valtype_new(WASM_I64);
|
||||
}
|
||||
static inline own wasm_valtype_t* wasm_valtype_new_f32(void) {
|
||||
return wasm_valtype_new(WASM_F32);
|
||||
}
|
||||
static inline own wasm_valtype_t* wasm_valtype_new_f64(void) {
|
||||
return wasm_valtype_new(WASM_F64);
|
||||
}
|
||||
|
||||
static inline own wasm_valtype_t* wasm_valtype_new_anyref(void) {
|
||||
return wasm_valtype_new(WASM_ANYREF);
|
||||
}
|
||||
static inline own wasm_valtype_t* wasm_valtype_new_funcref(void) {
|
||||
return wasm_valtype_new(WASM_FUNCREF);
|
||||
}
|
||||
|
||||
|
||||
// Function Types construction short-hands
|
||||
|
||||
static inline own wasm_functype_t* wasm_functype_new_0_0(void) {
|
||||
wasm_valtype_vec_t params, results;
|
||||
wasm_valtype_vec_new_empty(¶ms);
|
||||
wasm_valtype_vec_new_empty(&results);
|
||||
return wasm_functype_new(¶ms, &results);
|
||||
}
|
||||
|
||||
static inline own wasm_functype_t* wasm_functype_new_1_0(
|
||||
own wasm_valtype_t* p
|
||||
) {
|
||||
wasm_valtype_t* ps[1] = {p};
|
||||
wasm_valtype_vec_t params, results;
|
||||
wasm_valtype_vec_new(¶ms, 1, ps);
|
||||
wasm_valtype_vec_new_empty(&results);
|
||||
return wasm_functype_new(¶ms, &results);
|
||||
}
|
||||
|
||||
static inline own wasm_functype_t* wasm_functype_new_2_0(
|
||||
own wasm_valtype_t* p1, own wasm_valtype_t* p2
|
||||
) {
|
||||
wasm_valtype_t* ps[2] = {p1, p2};
|
||||
wasm_valtype_vec_t params, results;
|
||||
wasm_valtype_vec_new(¶ms, 2, ps);
|
||||
wasm_valtype_vec_new_empty(&results);
|
||||
return wasm_functype_new(¶ms, &results);
|
||||
}
|
||||
|
||||
static inline own wasm_functype_t* wasm_functype_new_3_0(
|
||||
own wasm_valtype_t* p1, own wasm_valtype_t* p2, own wasm_valtype_t* p3
|
||||
) {
|
||||
wasm_valtype_t* ps[3] = {p1, p2, p3};
|
||||
wasm_valtype_vec_t params, results;
|
||||
wasm_valtype_vec_new(¶ms, 3, ps);
|
||||
wasm_valtype_vec_new_empty(&results);
|
||||
return wasm_functype_new(¶ms, &results);
|
||||
}
|
||||
|
||||
static inline own wasm_functype_t* wasm_functype_new_0_1(
|
||||
own wasm_valtype_t* r
|
||||
) {
|
||||
wasm_valtype_t* rs[1] = {r};
|
||||
wasm_valtype_vec_t params, results;
|
||||
wasm_valtype_vec_new_empty(¶ms);
|
||||
wasm_valtype_vec_new(&results, 1, rs);
|
||||
return wasm_functype_new(¶ms, &results);
|
||||
}
|
||||
|
||||
static inline own wasm_functype_t* wasm_functype_new_1_1(
|
||||
own wasm_valtype_t* p, own wasm_valtype_t* r
|
||||
) {
|
||||
wasm_valtype_t* ps[1] = {p};
|
||||
wasm_valtype_t* rs[1] = {r};
|
||||
wasm_valtype_vec_t params, results;
|
||||
wasm_valtype_vec_new(¶ms, 1, ps);
|
||||
wasm_valtype_vec_new(&results, 1, rs);
|
||||
return wasm_functype_new(¶ms, &results);
|
||||
}
|
||||
|
||||
static inline own wasm_functype_t* wasm_functype_new_2_1(
|
||||
own wasm_valtype_t* p1, own wasm_valtype_t* p2, own wasm_valtype_t* r
|
||||
) {
|
||||
wasm_valtype_t* ps[2] = {p1, p2};
|
||||
wasm_valtype_t* rs[1] = {r};
|
||||
wasm_valtype_vec_t params, results;
|
||||
wasm_valtype_vec_new(¶ms, 2, ps);
|
||||
wasm_valtype_vec_new(&results, 1, rs);
|
||||
return wasm_functype_new(¶ms, &results);
|
||||
}
|
||||
|
||||
static inline own wasm_functype_t* wasm_functype_new_3_1(
|
||||
own wasm_valtype_t* p1, own wasm_valtype_t* p2, own wasm_valtype_t* p3,
|
||||
own wasm_valtype_t* r
|
||||
) {
|
||||
wasm_valtype_t* ps[3] = {p1, p2, p3};
|
||||
wasm_valtype_t* rs[1] = {r};
|
||||
wasm_valtype_vec_t params, results;
|
||||
wasm_valtype_vec_new(¶ms, 3, ps);
|
||||
wasm_valtype_vec_new(&results, 1, rs);
|
||||
return wasm_functype_new(¶ms, &results);
|
||||
}
|
||||
|
||||
static inline own wasm_functype_t* wasm_functype_new_0_2(
|
||||
own wasm_valtype_t* r1, own wasm_valtype_t* r2
|
||||
) {
|
||||
wasm_valtype_t* rs[2] = {r1, r2};
|
||||
wasm_valtype_vec_t params, results;
|
||||
wasm_valtype_vec_new_empty(¶ms);
|
||||
wasm_valtype_vec_new(&results, 2, rs);
|
||||
return wasm_functype_new(¶ms, &results);
|
||||
}
|
||||
|
||||
static inline own wasm_functype_t* wasm_functype_new_1_2(
|
||||
own wasm_valtype_t* p, own wasm_valtype_t* r1, own wasm_valtype_t* r2
|
||||
) {
|
||||
wasm_valtype_t* ps[1] = {p};
|
||||
wasm_valtype_t* rs[2] = {r1, r2};
|
||||
wasm_valtype_vec_t params, results;
|
||||
wasm_valtype_vec_new(¶ms, 1, ps);
|
||||
wasm_valtype_vec_new(&results, 2, rs);
|
||||
return wasm_functype_new(¶ms, &results);
|
||||
}
|
||||
|
||||
static inline own wasm_functype_t* wasm_functype_new_2_2(
|
||||
own wasm_valtype_t* p1, own wasm_valtype_t* p2,
|
||||
own wasm_valtype_t* r1, own wasm_valtype_t* r2
|
||||
) {
|
||||
wasm_valtype_t* ps[2] = {p1, p2};
|
||||
wasm_valtype_t* rs[2] = {r1, r2};
|
||||
wasm_valtype_vec_t params, results;
|
||||
wasm_valtype_vec_new(¶ms, 2, ps);
|
||||
wasm_valtype_vec_new(&results, 2, rs);
|
||||
return wasm_functype_new(¶ms, &results);
|
||||
}
|
||||
|
||||
static inline own wasm_functype_t* wasm_functype_new_3_2(
|
||||
own wasm_valtype_t* p1, own wasm_valtype_t* p2, own wasm_valtype_t* p3,
|
||||
own wasm_valtype_t* r1, own wasm_valtype_t* r2
|
||||
) {
|
||||
wasm_valtype_t* ps[3] = {p1, p2, p3};
|
||||
wasm_valtype_t* rs[2] = {r1, r2};
|
||||
wasm_valtype_vec_t params, results;
|
||||
wasm_valtype_vec_new(¶ms, 3, ps);
|
||||
wasm_valtype_vec_new(&results, 2, rs);
|
||||
return wasm_functype_new(¶ms, &results);
|
||||
}
|
||||
|
||||
|
||||
// Value construction short-hands
|
||||
|
||||
static inline void wasm_val_init_ptr(own wasm_val_t* out, void* p) {
|
||||
#if UINTPTR_MAX == UINT32_MAX
|
||||
out->kind = WASM_I32;
|
||||
out->of.i32 = (intptr_t)p;
|
||||
#elif UINTPTR_MAX == UINT64_MAX
|
||||
out->kind = WASM_I64;
|
||||
out->of.i64 = (intptr_t)p;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void* wasm_val_ptr(const wasm_val_t* val) {
|
||||
#if UINTPTR_MAX == UINT32_MAX
|
||||
return (void*)(intptr_t)val->of.i32;
|
||||
#elif UINTPTR_MAX == UINT64_MAX
|
||||
return (void*)(intptr_t)val->of.i64;
|
||||
#endif
|
||||
}
|
||||
|
||||
#define WASM_I32_VAL(i) {.kind = WASM_I32, .of = {.i32 = i}}
|
||||
#define WASM_I64_VAL(i) {.kind = WASM_I64, .of = {.i64 = i}}
|
||||
#define WASM_F32_VAL(z) {.kind = WASM_F32, .of = {.f32 = z}}
|
||||
#define WASM_F64_VAL(z) {.kind = WASM_F64, .of = {.f64 = z}}
|
||||
#define WASM_REF_VAL(r) {.kind = WASM_ANYREF, .of = {.ref = r}}
|
||||
#define WASM_INIT_VAL {.kind = WASM_ANYREF, .of = {.ref = NULL}}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#undef own
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // #ifdef WASM_H
|
||||
|
|
@ -12,7 +12,10 @@ bindgen \
|
|||
--blocklist-type '^__.*' \
|
||||
--blocklist-function ts_tree_print_dot_graph \
|
||||
--size_t-is-usize \
|
||||
$header_path > $output_path
|
||||
$header_path \
|
||||
-- \
|
||||
-D TREE_SITTER_FEATURE_WASM \
|
||||
> $output_path
|
||||
|
||||
echo "" >> $output_path
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue