Commit 116cbea5 authored by Jakob Kummerow's avatar Jakob Kummerow Committed by Commit Bot

[wasm-c-api] Roll 7865f7d: Expose possible traps during Instance::make

Change-Id: Iadc6fa94ac2b77a8a8b0f1dbf3c28fc97ff13930
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1765608Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Commit-Queue: Jakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#63361}
parent c317f606
......@@ -904,7 +904,9 @@ own<Frame> Trap::origin() const {
isolate->CreateMessage(impl(this)->v8_object(), nullptr);
i::Handle<i::FixedArray> frames(i::FixedArray::cast(message->stack_frames()),
isolate);
DCHECK_GT(frames->length(), 0);
if (frames->length() == 0) {
return own<Frame>();
}
return CreateFrameFromInternal(frames, 0, isolate, impl(this)->store());
}
......@@ -917,7 +919,7 @@ ownvec<Frame> Trap::trace() const {
i::Handle<i::FixedArray> frames(i::FixedArray::cast(message->stack_frames()),
isolate);
int num_frames = frames->length();
DCHECK_GT(num_frames, 0);
// {num_frames} can be 0; the code below can handle that case.
ownvec<Frame> result = ownvec<Frame>::make_uninitialized(num_frames);
for (int i = 0; i < num_frames; i++) {
result[i] =
......@@ -966,13 +968,6 @@ auto Module::validate(Store* store_abs, const vec<byte_t>& binary) -> bool {
return isolate->wasm_engine()->SyncValidate(isolate, features, bytes);
}
class NopErrorThrower : public i::wasm::ErrorThrower {
public:
explicit NopErrorThrower(i::Isolate* isolate)
: i::wasm::ErrorThrower(isolate, "ignored") {}
~NopErrorThrower() { Reset(); }
};
auto Module::make(Store* store_abs, const vec<byte_t>& binary) -> own<Module> {
StoreImpl* store = impl(store_abs);
i::Isolate* isolate = store->i_isolate();
......@@ -980,11 +975,12 @@ auto Module::make(Store* store_abs, const vec<byte_t>& binary) -> own<Module> {
i::wasm::ModuleWireBytes bytes(
{reinterpret_cast<const uint8_t*>(binary.get()), binary.size()});
i::wasm::WasmFeatures features = i::wasm::WasmFeaturesFromIsolate(isolate);
NopErrorThrower thrower(isolate);
i::wasm::ErrorThrower thrower(isolate, "ignored");
i::Handle<i::WasmModuleObject> module;
if (!isolate->wasm_engine()
->SyncCompile(isolate, features, &thrower, bytes)
.ToHandle(&module)) {
thrower.Reset(); // The API provides no way to expose the error.
return nullptr;
}
return implement<Module>::type::make(store, module);
......@@ -1447,6 +1443,25 @@ own<Trap> CallWasmCapiFunction(i::WasmCapiFunctionData data, const Val args[],
return (func_data->callback_with_env)(func_data->env, args, results);
}
i::Handle<i::JSReceiver> GetProperException(
i::Isolate* isolate, i::Handle<i::Object> maybe_exception) {
if (maybe_exception->IsJSReceiver()) {
return i::Handle<i::JSReceiver>::cast(maybe_exception);
}
i::MaybeHandle<i::String> maybe_string =
i::Object::ToString(isolate, maybe_exception);
i::Handle<i::String> string = isolate->factory()->empty_string();
if (!maybe_string.ToHandle(&string)) {
// If converting the {maybe_exception} to string threw another exception,
// just give up and leave {string} as the empty string.
isolate->clear_pending_exception();
}
// {NewError} cannot fail when its input is a plain String, so we always
// get an Error object here.
return i::Handle<i::JSReceiver>::cast(
isolate->factory()->NewError(isolate->error_function(), string));
}
} // namespace
auto Func::call(const Val args[], Val results[]) const -> own<Trap> {
......@@ -1507,17 +1522,8 @@ auto Func::call(const Val args[], Val results[]) const -> own<Trap> {
if (isolate->has_pending_exception()) {
i::Handle<i::Object> exception(isolate->pending_exception(), isolate);
isolate->clear_pending_exception();
if (!exception->IsJSReceiver()) {
i::MaybeHandle<i::String> maybe_string =
i::Object::ToString(isolate, exception);
i::Handle<i::String> string = maybe_string.is_null()
? isolate->factory()->empty_string()
: maybe_string.ToHandleChecked();
exception =
isolate->factory()->NewError(isolate->error_function(), string);
}
return implement<Trap>::type::make(
store, i::Handle<i::JSReceiver>::cast(exception));
return implement<Trap>::type::make(store,
GetProperException(isolate, exception));
}
PopArgs(sig, results, &packer, store);
......@@ -1903,8 +1909,8 @@ Instance::~Instance() {}
auto Instance::copy() const -> own<Instance> { return impl(this)->copy(); }
auto Instance::make(Store* store_abs, const Module* module_abs,
const Extern* const imports[]) -> own<Instance> {
own<Instance> Instance::make(Store* store_abs, const Module* module_abs,
const Extern* const imports[], own<Trap>* trap) {
StoreImpl* store = impl(store_abs);
const implement<Module>::type* module = impl(module_abs);
i::Isolate* isolate = store->i_isolate();
......@@ -1912,6 +1918,7 @@ auto Instance::make(Store* store_abs, const Module* module_abs,
DCHECK_EQ(module->v8_object()->GetIsolate(), isolate);
if (trap) *trap = nullptr;
ownvec<ImportType> import_types = module_abs->imports();
i::Handle<i::JSObject> imports_obj =
isolate->factory()->NewJSObject(isolate->object_function());
......@@ -1934,14 +1941,33 @@ auto Instance::make(Store* store_abs, const Module* module_abs,
ignore(i::Object::SetProperty(isolate, module_obj, name_str,
impl(imports[i])->v8_object()));
}
NopErrorThrower thrower(isolate);
i::Handle<i::WasmInstanceObject> instance_obj =
isolate->wasm_engine()
->SyncInstantiate(isolate, &thrower, module->v8_object(), imports_obj,
i::MaybeHandle<i::JSArrayBuffer>())
.ToHandleChecked();
return implement<Instance>::type::make(store, instance_obj);
i::wasm::ErrorThrower thrower(isolate, "instantiation");
i::MaybeHandle<i::WasmInstanceObject> instance_obj =
isolate->wasm_engine()->SyncInstantiate(
isolate, &thrower, module->v8_object(), imports_obj,
i::MaybeHandle<i::JSArrayBuffer>());
if (trap) {
if (thrower.error()) {
*trap = implement<Trap>::type::make(
store, GetProperException(isolate, thrower.Reify()));
DCHECK(!thrower.error()); // Reify() called Reset().
DCHECK(!isolate->has_pending_exception()); // Hasn't been thrown yet.
return own<Instance>();
} else if (isolate->has_pending_exception()) {
i::Handle<i::Object> maybe_exception(isolate->pending_exception(),
isolate);
*trap = implement<Trap>::type::make(
store, GetProperException(isolate, maybe_exception));
isolate->clear_pending_exception();
return own<Instance>();
}
} else if (instance_obj.is_null()) {
// If no {trap} output is specified, silently swallow all errors.
thrower.Reset();
isolate->clear_pending_exception();
return own<Instance>();
}
return implement<Instance>::type::make(store, instance_obj.ToHandleChecked());
}
namespace {
......@@ -2995,9 +3021,14 @@ WASM_DEFINE_REF(instance, wasm::Instance)
wasm_instance_t* wasm_instance_new(wasm_store_t* store,
const wasm_module_t* module,
const wasm_extern_t* const imports[]) {
return release_instance(wasm::Instance::make(
store, module, reinterpret_cast<const wasm::Extern* const*>(imports)));
const wasm_extern_t* const imports[],
wasm_trap_t** trap) {
wasm::own<wasm::Trap> error;
wasm_instance_t* instance = release_instance(wasm::Instance::make(
store, module, reinterpret_cast<const wasm::Extern* const*>(imports),
&error));
if (trap) *trap = hide_trap(error.release());
return instance;
}
void wasm_instance_exports(const wasm_instance_t* instance,
......
......@@ -38,6 +38,7 @@ v8_executable("wasm_api_tests") {
"reflect.cc",
"run-all-wasm-api-tests.cc",
"serialize.cc",
"startup-errors.cc",
"table.cc",
"threads.cc",
"traps.cc",
......
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "test/wasm-api-tests/wasm-api-test.h"
namespace v8 {
namespace internal {
namespace wasm {
namespace {
own<Trap> DummyCallback(const Val args[], Val results[]) { return nullptr; }
} // namespace
TEST_F(WasmCapiTest, StartupErrors) {
FunctionSig sig(0, 0, nullptr);
byte code[] = {WASM_UNREACHABLE};
WasmFunctionBuilder* start_func = builder()->AddFunction(&sig);
start_func->EmitCode(code, static_cast<uint32_t>(sizeof(code)));
start_func->Emit(kExprEnd);
builder()->MarkStartFunction(start_func);
builder()->AddImport(CStrVector("dummy"), &sig);
Compile();
own<Trap> trap;
// Try to make an Instance with non-matching imports.
own<Func> bad_func = Func::make(store(), cpp_i_i_sig(), DummyCallback);
Extern* bad_imports[] = {bad_func.get()};
own<Instance> instance =
Instance::make(store(), module(), bad_imports, &trap);
EXPECT_EQ(nullptr, instance);
EXPECT_NE(nullptr, trap);
EXPECT_STREQ(
"Uncaught LinkError: instantiation: Import #0 module=\"\" "
"function=\"dummy\" "
"error: imported function does not match the expected type",
trap->message().get());
EXPECT_EQ(nullptr, trap->origin());
// Don't crash if there is no {trap}.
instance = Instance::make(store(), module(), bad_imports, nullptr);
EXPECT_EQ(nullptr, instance);
// Try to make an instance with a {start} function that traps.
own<FuncType> good_sig =
FuncType::make(ownvec<ValType>::make(), ownvec<ValType>::make());
own<Func> good_func = Func::make(store(), good_sig.get(), DummyCallback);
Extern* good_imports[] = {good_func.get()};
instance = Instance::make(store(), module(), good_imports, &trap);
EXPECT_EQ(nullptr, instance);
EXPECT_NE(nullptr, trap);
EXPECT_STREQ("Uncaught RuntimeError: unreachable", trap->message().get());
EXPECT_NE(nullptr, trap->origin());
// Don't crash if there is no {trap}.
instance = Instance::make(store(), module(), good_imports, nullptr);
EXPECT_EQ(nullptr, instance);
}
} // namespace wasm
} // namespace internal
} // namespace v8
......@@ -111,7 +111,8 @@ int main(int argc, const char* argv[]) {
const wasm_extern_t* imports[] = {
wasm_func_as_extern(print_func), wasm_func_as_extern(closure_func)
};
own wasm_instance_t* instance = wasm_instance_new(store, module, imports);
own wasm_instance_t* instance =
wasm_instance_new(store, module, imports, NULL);
if (!instance) {
printf("> Error instantiating module!\n");
return 1;
......
......@@ -52,7 +52,8 @@ int main(int argc, const char* argv[]) {
printf("Instantiating modules...\n");
for (int i = 0; i <= iterations; ++i) {
if (i % (iterations / 10) == 0) printf("%d\n", i);
own wasm_instance_t* instance = wasm_instance_new(store, module, NULL);
own wasm_instance_t* instance =
wasm_instance_new(store, module, NULL, NULL);
if (!instance) {
printf("> Error instantiating module %d!\n", i);
return 1;
......
......@@ -91,13 +91,17 @@ int main(int argc, const char* argv[]) {
wasm_valtype_new(WASM_I64), WASM_VAR);
wasm_val_t val_f32_1 = {.kind = WASM_F32, .of = {.f32 = 1}};
own wasm_global_t* const_f32_import = wasm_global_new(store, const_f32_type, &val_f32_1);
own wasm_global_t* const_f32_import =
wasm_global_new(store, const_f32_type, &val_f32_1);
wasm_val_t val_i64_2 = {.kind = WASM_I64, .of = {.i64 = 2}};
own wasm_global_t* const_i64_import = wasm_global_new(store, const_i64_type, &val_i64_2);
own wasm_global_t* const_i64_import =
wasm_global_new(store, const_i64_type, &val_i64_2);
wasm_val_t val_f32_3 = {.kind = WASM_F32, .of = {.f32 = 3}};
own wasm_global_t* var_f32_import = wasm_global_new(store, var_f32_type, &val_f32_3);
own wasm_global_t* var_f32_import =
wasm_global_new(store, var_f32_type, &val_f32_3);
wasm_val_t val_i64_4 = {.kind = WASM_I64, .of = {.i64 = 4}};
own wasm_global_t* var_i64_import = wasm_global_new(store, var_i64_type, &val_i64_4);
own wasm_global_t* var_i64_import =
wasm_global_new(store, var_i64_type, &val_i64_4);
wasm_globaltype_delete(const_f32_type);
wasm_globaltype_delete(const_i64_type);
......@@ -112,7 +116,8 @@ int main(int argc, const char* argv[]) {
wasm_global_as_extern(var_f32_import),
wasm_global_as_extern(var_i64_import)
};
own wasm_instance_t* instance = wasm_instance_new(store, module, imports);
own wasm_instance_t* instance =
wasm_instance_new(store, module, imports, NULL);
if (!instance) {
printf("> Error instantiating module!\n");
return 1;
......
......@@ -62,7 +62,8 @@ int main(int argc, const char* argv[]) {
// Instantiate.
printf("Instantiating module...\n");
const wasm_extern_t* imports[] = { wasm_func_as_extern(hello_func) };
own wasm_instance_t* instance = wasm_instance_new(store, module, imports);
own wasm_instance_t* instance =
wasm_instance_new(store, module, imports, NULL);
if (!instance) {
printf("> Error instantiating module!\n");
return 1;
......
......@@ -168,7 +168,8 @@ int main(int argc, const char* argv[]) {
// Instantiate.
printf("Instantiating module...\n");
const wasm_extern_t* imports[] = { wasm_func_as_extern(callback_func) };
own wasm_instance_t* instance = wasm_instance_new(store, module, imports);
own wasm_instance_t* instance =
wasm_instance_new(store, module, imports, NULL);
if (!instance) {
printf("> Error instantiating module!\n");
return 1;
......
......@@ -132,7 +132,8 @@ int main(int argc, const char* argv[]) {
// Instantiate.
printf("Instantiating module...\n");
own wasm_instance_t* instance = wasm_instance_new(store, module, NULL);
own wasm_instance_t* instance =
wasm_instance_new(store, module, NULL, NULL);
if (!instance) {
printf("> Error instantiating module!\n");
return 1;
......
......@@ -79,14 +79,16 @@ int main(int argc, const char* argv[]) {
wasm_valtype_vec_new(&tuple1, 4, types);
wasm_valtype_vec_copy(&tuple2, &tuple1);
own wasm_functype_t* callback_type = wasm_functype_new(&tuple1, &tuple2);
own wasm_func_t* callback_func = wasm_func_new(store, callback_type, callback);
own wasm_func_t* callback_func =
wasm_func_new(store, callback_type, callback);
wasm_functype_delete(callback_type);
// Instantiate.
printf("Instantiating module...\n");
const wasm_extern_t* imports[] = {wasm_func_as_extern(callback_func)};
own wasm_instance_t* instance = wasm_instance_new(store, module, imports);
own wasm_instance_t* instance =
wasm_instance_new(store, module, imports, NULL);
if (!instance) {
printf("> Error instantiating module!\n");
return 1;
......
......@@ -45,28 +45,32 @@ void print_valtypes(const wasm_valtype_vec_t* types) {
void print_externtype(const wasm_externtype_t* type) {
switch (wasm_externtype_kind(type)) {
case WASM_EXTERN_FUNC: {
const wasm_functype_t* functype = wasm_externtype_as_functype_const(type);
const wasm_functype_t* functype =
wasm_externtype_as_functype_const(type);
printf("func ");
print_valtypes(wasm_functype_params(functype));
printf(" -> ");
print_valtypes(wasm_functype_results(functype));
} break;
case WASM_EXTERN_GLOBAL: {
const wasm_globaltype_t* globaltype = wasm_externtype_as_globaltype_const(type);
const wasm_globaltype_t* globaltype =
wasm_externtype_as_globaltype_const(type);
printf("global ");
print_mutability(wasm_globaltype_mutability(globaltype));
printf(" ");
print_valtype(wasm_globaltype_content(globaltype));
} break;
case WASM_EXTERN_TABLE: {
const wasm_tabletype_t* tabletype = wasm_externtype_as_tabletype_const(type);
const wasm_tabletype_t* tabletype =
wasm_externtype_as_tabletype_const(type);
printf("table ");
print_limits(wasm_tabletype_limits(tabletype));
printf(" ");
print_valtype(wasm_tabletype_element(tabletype));
} break;
case WASM_EXTERN_MEMORY: {
const wasm_memorytype_t* memorytype = wasm_externtype_as_memorytype_const(type);
const wasm_memorytype_t* memorytype =
wasm_externtype_as_memorytype_const(type);
printf("memory ");
print_limits(wasm_memorytype_limits(memorytype));
} break;
......@@ -114,7 +118,7 @@ int main(int argc, const char* argv[]) {
// Instantiate.
printf("Instantiating module...\n");
own wasm_instance_t* instance = wasm_instance_new(store, module, NULL);
own wasm_instance_t* instance = wasm_instance_new(store, module, NULL, NULL);
if (!instance) {
printf("> Error instantiating module!\n");
return 1;
......@@ -129,7 +133,8 @@ int main(int argc, const char* argv[]) {
assert(exports.size == export_types.size);
for (size_t i = 0; i < exports.size; ++i) {
assert(wasm_extern_kind(exports.data[i]) == wasm_externtype_kind(wasm_exporttype_type(export_types.data[i])));
assert(wasm_extern_kind(exports.data[i]) ==
wasm_externtype_kind(wasm_exporttype_type(export_types.data[i])));
printf("> export %zu ", i);
print_name(wasm_exporttype_name(export_types.data[i]));
printf("\n");
......
......@@ -77,7 +77,8 @@ int main(int argc, const char* argv[]) {
// Instantiate.
printf("Instantiating deserialized module...\n");
const wasm_extern_t* imports[] = { wasm_func_as_extern(hello_func) };
own wasm_instance_t* instance = wasm_instance_new(store, deserialized, imports);
own wasm_instance_t* instance =
wasm_instance_new(store, deserialized, imports, NULL);
if (!instance) {
printf("> Error instantiating module!\n");
return 1;
......
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include "wasm.h"
#define own
void print_frame(wasm_frame_t* frame) {
printf("> %p @ 0x%zx = %"PRIu32".0x%zx\n",
wasm_frame_instance(frame),
wasm_frame_module_offset(frame),
wasm_frame_func_index(frame),
wasm_frame_func_offset(frame)
);
}
int main(int argc, const char* argv[]) {
// Initialize.
printf("Initializing...\n");
wasm_engine_t* engine = wasm_engine_new();
wasm_store_t* store = wasm_store_new(engine);
// Load binary.
printf("Loading binary...\n");
FILE* file = fopen("start.wasm", "r");
if (!file) {
printf("> Error loading module!\n");
return 1;
}
fseek(file, 0L, SEEK_END);
size_t file_size = ftell(file);
fseek(file, 0L, SEEK_SET);
wasm_byte_vec_t binary;
wasm_byte_vec_new_uninitialized(&binary, file_size);
if (fread(binary.data, file_size, 1, file) != 1) {
printf("> Error loading module!\n");
return 1;
}
fclose(file);
// Compile.
printf("Compiling module...\n");
own wasm_module_t* module = wasm_module_new(store, &binary);
if (!module) {
printf("> Error compiling module!\n");
return 1;
}
wasm_byte_vec_delete(&binary);
// Instantiate.
printf("Instantiating module...\n");
own wasm_trap_t* trap = NULL;
own wasm_instance_t* instance =
wasm_instance_new(store, module, NULL, &trap);
if (instance || !trap) {
printf("> Error instantiating module, expected trap!\n");
return 1;
}
wasm_module_delete(module);
// Print result.
printf("Printing message...\n");
own wasm_name_t message;
wasm_trap_message(trap, &message);
printf("> %s\n", message.data);
printf("Printing origin...\n");
own wasm_frame_t* frame = wasm_trap_origin(trap);
if (frame) {
print_frame(frame);
wasm_frame_delete(frame);
} else {
printf("> Empty origin.\n");
}
printf("Printing trace...\n");
own wasm_frame_vec_t trace;
wasm_trap_trace(trap, &trace);
if (trace.size > 0) {
for (size_t i = 0; i < trace.size; ++i) {
print_frame(trace.data[i]);
}
} else {
printf("> Empty trace.\n");
}
wasm_frame_vec_delete(&trace);
wasm_trap_delete(trap);
wasm_name_delete(&message);
// Shut down.
printf("Shutting down...\n");
wasm_store_delete(store);
wasm_engine_delete(engine);
// All done.
printf("Done.\n");
return 0;
}
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <string>
#include <cinttypes>
#include "wasm.hh"
void print_frame(const wasm::Frame* frame) {
std::cout << "> " << frame->instance();
std::cout << " @ 0x" << std::hex << frame->module_offset();
std::cout << " = " << frame->func_index();
std::cout << ".0x" << std::hex << frame->func_offset() << std::endl;
}
void run() {
// Initialize.
std::cout << "Initializing..." << std::endl;
auto engine = wasm::Engine::make();
auto store_ = wasm::Store::make(engine.get());
auto store = store_.get();
// Load binary.
std::cout << "Loading binary..." << std::endl;
std::ifstream file("start.wasm");
file.seekg(0, std::ios_base::end);
auto file_size = file.tellg();
file.seekg(0);
auto binary = wasm::vec<byte_t>::make_uninitialized(file_size);
file.read(binary.get(), file_size);
file.close();
if (file.fail()) {
std::cout << "> Error loading module!" << std::endl;
exit(1);
}
// Compile.
std::cout << "Compiling module..." << std::endl;
auto module = wasm::Module::make(store, binary);
if (!module) {
std::cout << "> Error compiling module!" << std::endl;
exit(1);
}
// Instantiate.
std::cout << "Instantiating module..." << std::endl;
wasm::own<wasm::Trap> trap;
auto instance = wasm::Instance::make(store, module.get(), nullptr, &trap);
if (instance || !trap) {
std::cout << "> Error instantiating module, expected trap!" << std::endl;
exit(1);
}
// Print result.
std::cout << "Printing message..." << std::endl;
std::cout << "> " << trap->message().get() << std::endl;
std::cout << "Printing origin..." << std::endl;
auto frame = trap->origin();
if (frame) {
print_frame(frame.get());
} else {
std::cout << "> Empty origin." << std::endl;
}
std::cout << "Printing trace..." << std::endl;
auto trace = trap->trace();
if (trace.size() > 0) {
for (size_t i = 0; i < trace.size(); ++i) {
print_frame(trace[i].get());
}
} else {
std::cout << "> Empty trace." << std::endl;
}
// Shut down.
std::cout << "Shutting down..." << std::endl;
}
int main(int argc, const char* argv[]) {
run();
std::cout << "Done." << std::endl;
return 0;
}
(module
(func $start (unreachable))
(start $start)
)
......@@ -110,7 +110,8 @@ int main(int argc, const char* argv[]) {
// Instantiate.
printf("Instantiating module...\n");
own wasm_instance_t* instance = wasm_instance_new(store, module, NULL);
own wasm_instance_t* instance =
wasm_instance_new(store, module, NULL, NULL);
if (!instance) {
printf("> Error instantiating module!\n");
return 1;
......
......@@ -52,7 +52,8 @@ void* run(void* args_abs) {
const wasm_extern_t* imports[] = {
wasm_func_as_extern(func), wasm_global_as_extern(global),
};
own wasm_instance_t* instance = wasm_instance_new(store, module, imports);
own wasm_instance_t* instance =
wasm_instance_new(store, module, imports, NULL);
if (!instance) {
printf("> Error instantiating module!\n");
return NULL;
......
......@@ -66,15 +66,18 @@ int main(int argc, const char* argv[]) {
// Create external print functions.
printf("Creating callback...\n");
own wasm_functype_t* fail_type = wasm_functype_new_0_1(wasm_valtype_new_i32());
own wasm_func_t* fail_func = wasm_func_new_with_env(store, fail_type, fail_callback, store, NULL);
own wasm_functype_t* fail_type =
wasm_functype_new_0_1(wasm_valtype_new_i32());
own wasm_func_t* fail_func =
wasm_func_new_with_env(store, fail_type, fail_callback, store, NULL);
wasm_functype_delete(fail_type);
// Instantiate.
printf("Instantiating module...\n");
const wasm_extern_t* imports[] = { wasm_func_as_extern(fail_func) };
own wasm_instance_t* instance = wasm_instance_new(store, module, imports);
own wasm_instance_t* instance =
wasm_instance_new(store, module, imports, NULL);
if (!instance) {
printf("> Error instantiating module!\n");
return 1;
......@@ -104,8 +107,8 @@ int main(int argc, const char* argv[]) {
printf("Calling export %d...\n", i);
own wasm_trap_t* trap = wasm_func_call(func, NULL, NULL);
if (! trap) {
printf("> Error calling function!\n");
if (!trap) {
printf("> Error calling function, expected trap!\n");
return 1;
}
......
......@@ -87,7 +87,7 @@ void run() {
std::cout << "Calling export " << i << "..." << std::endl;
auto trap = exports[i]->func()->call();
if (!trap) {
std::cout << "> Error calling function!" << std::endl;
std::cout << "> Error calling function, expected trap!" << std::endl;
exit(1);
}
......
......@@ -503,7 +503,9 @@ const wasm_memory_t* wasm_extern_as_memory_const(const wasm_extern_t*);
WASM_DECLARE_REF(instance)
own wasm_instance_t* wasm_instance_new(
wasm_store_t*, const wasm_module_t*, const wasm_extern_t* const imports[]);
wasm_store_t*, const wasm_module_t*, const wasm_extern_t* const imports[],
own wasm_trap_t**
);
void wasm_instance_exports(const wasm_instance_t*, own wasm_extern_vec_t* out);
......
......@@ -719,7 +719,8 @@ public:
~Instance();
static auto make(
Store*, const Module*, const Extern* const[]) -> own<Instance>;
Store*, const Module*, const Extern* const[], own<Trap>* = nullptr
) -> own<Instance>;
auto copy() const -> own<Instance>;
auto exports() const -> ownvec<Extern>;
......
......@@ -38,7 +38,8 @@ CLANG_PATH = os.path.join(CHECKOUT_PATH, "third_party", "llvm-build",
"Release+Asserts", "bin")
EXAMPLES = ["hello", "callback", "trap", "reflect", "global", "table",
"memory", "finalize", "serialize", "threads", "hostref", "multi"]
"memory", "finalize", "serialize", "threads", "hostref", "multi",
"start"]
CLANG = {
"name": "Clang",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment