Implement Exception Handling for classic interpreter (#3096)

This PR adds the initial support for WASM exception handling:
* Inside the classic interpreter only:
  * Initial handling of Tags
  * Initial handling of Exceptions based on W3C Exception Proposal
  * Import and Export of Exceptions and Tags
* Add `cmake -DWAMR_BUILD_EXCE_HANDLING=1/0` option to enable/disable
  the feature, and by default it is disabled
* Update the wamr-test-suites scripts to test the feature
* Additional CI/CD changes to validate the exception spec proposal cases

Refer to:
https://github.com/bytecodealliance/wasm-micro-runtime/issues/1884
587513f3c6
8bebfe9ad7
59bccdfed8

Signed-off-by: Ricardo Aguilar <ricardoaguilar@siemens.com>
Co-authored-by: Chris Woods <chris.woods@siemens.com>
Co-authored-by: Rene Ermler <rene.ermler@siemens.com>
Co-authored-by: Trenner Thomas <trenner.thomas@siemens.com>
This commit is contained in:
Wenyong Huang
2024-01-31 08:27:17 +08:00
committed by GitHub
parent 7e65f9a244
commit af318bac81
16 changed files with 1620 additions and 39 deletions

View File

@ -732,6 +732,101 @@ functions_instantiate(const WASMModule *module, WASMModuleInstance *module_inst,
return functions;
}
#if WASM_ENABLE_TAGS != 0
/**
* Destroy tags instances.
*/
static void
tags_deinstantiate(WASMTagInstance *tags, void **import_tag_ptrs)
{
if (tags) {
wasm_runtime_free(tags);
}
if (import_tag_ptrs) {
wasm_runtime_free(import_tag_ptrs);
}
}
/**
* Instantiate tags in a module.
*/
static WASMTagInstance *
tags_instantiate(const WASMModule *module, WASMModuleInstance *module_inst,
char *error_buf, uint32 error_buf_size)
{
WASMImport *import;
uint32 i, tag_count = module->import_tag_count + module->tag_count;
uint64 total_size = sizeof(WASMTagInstance) * (uint64)tag_count;
WASMTagInstance *tags, *tag;
if (!(tags = runtime_malloc(total_size, error_buf, error_buf_size))) {
return NULL;
}
total_size = sizeof(void *) * (uint64)module->import_tag_count;
if (total_size > 0
&& !(module_inst->e->import_tag_ptrs =
runtime_malloc(total_size, error_buf, error_buf_size))) {
wasm_runtime_free(tags);
return NULL;
}
/* instantiate tags from import section */
tag = tags;
import = module->import_tags;
for (i = 0; i < module->import_tag_count; i++, import++) {
tag->is_import_tag = true;
tag->u.tag_import = &import->u.tag;
tag->type = import->u.tag.type;
tag->attribute = import->u.tag.attribute;
#if WASM_ENABLE_MULTI_MODULE != 0
if (import->u.tag.import_module) {
if (!(tag->import_module_inst = get_sub_module_inst(
module_inst, import->u.tag.import_module))) {
set_error_buf(error_buf, error_buf_size, "unknown tag");
goto fail;
}
if (!(tag->import_tag_inst =
wasm_lookup_tag(tag->import_module_inst,
import->u.tag.field_name, NULL))) {
set_error_buf(error_buf, error_buf_size, "unknown tag");
goto fail;
}
/* Copy the imported tag to current instance */
module_inst->e->import_tag_ptrs[i] =
tag->u.tag_import->import_tag_linked;
}
#endif
tag++;
}
/* instantiate tags from tag section */
for (i = 0; i < module->tag_count; i++) {
tag->is_import_tag = false;
tag->type = module->tags[i]->type;
tag->u.tag = module->tags[i];
#if WASM_ENABLE_FAST_INTERP != 0
/* tag->const_cell_num = function->u.func->const_cell_num; */
#endif
tag++;
}
bh_assert((uint32)(tag - tags) == tag_count);
return tags;
#if WASM_ENABLE_MULTI_MODULE != 0
fail:
tags_deinstantiate(tags, module_inst->e->import_tag_ptrs);
/* clean up */
module_inst->e->import_tag_ptrs = NULL;
return NULL;
#endif
}
#endif
/**
* Destroy global instances.
*/
@ -931,6 +1026,52 @@ export_functions_instantiate(const WASMModule *module,
return export_funcs;
}
#if WASM_ENABLE_TAGS != 0
/**
* Destroy export function instances.
*/
static void
export_tags_deinstantiate(WASMExportTagInstance *tags)
{
if (tags)
wasm_runtime_free(tags);
}
/**
* Instantiate export functions in a module.
*/
static WASMExportTagInstance *
export_tags_instantiate(const WASMModule *module,
WASMModuleInstance *module_inst,
uint32 export_tag_count, char *error_buf,
uint32 error_buf_size)
{
WASMExportTagInstance *export_tags, *export_tag;
WASMExport *export = module->exports;
uint32 i;
uint64 total_size =
sizeof(WASMExportTagInstance) * (uint64)export_tag_count;
if (!(export_tag = export_tags =
runtime_malloc(total_size, error_buf, error_buf_size))) {
return NULL;
}
for (i = 0; i < module->export_count; i++, export ++)
if (export->kind == EXPORT_KIND_TAG) {
export_tag->name = export->name;
bh_assert((uint32)(module_inst->export_tags));
export_tag->tag = &module_inst->e->tags[export->index];
export_tag++;
}
bh_assert((uint32)(export_tag - export_tags) == export_tag_count);
return export_tags;
}
#endif
#if WASM_ENABLE_MULTI_MODULE != 0
static void
export_globals_deinstantiate(WASMExportGlobInstance *globals)
@ -1720,6 +1861,9 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
module_inst->table_count = module->import_table_count + module->table_count;
module_inst->e->function_count =
module->import_function_count + module->function_count;
#if WASM_ENABLE_TAGS != 0
module_inst->e->tag_count = module->import_tag_count + module->tag_count;
#endif
/* export */
module_inst->export_func_count = get_export_count(module, EXPORT_KIND_FUNC);
@ -1728,11 +1872,15 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
get_export_count(module, EXPORT_KIND_TABLE);
module_inst->export_memory_count =
get_export_count(module, EXPORT_KIND_MEMORY);
#if WASM_ENABLE_TAGS != 0
module_inst->e->export_tag_count =
get_export_count(module, EXPORT_KIND_TAG);
#endif
module_inst->export_global_count =
get_export_count(module, EXPORT_KIND_GLOBAL);
#endif
/* Instantiate memories/tables/functions */
/* Instantiate memories/tables/functions/tags */
if ((module_inst->memory_count > 0
&& !(module_inst->memories =
memories_instantiate(module, module_inst, parent, heap_size,
@ -1748,6 +1896,15 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
&& !(module_inst->export_functions = export_functions_instantiate(
module, module_inst, module_inst->export_func_count,
error_buf, error_buf_size)))
#if WASM_ENABLE_TAGS != 0
|| (module_inst->e->tag_count > 0
&& !(module_inst->e->tags = tags_instantiate(
module, module_inst, error_buf, error_buf_size)))
|| (module_inst->e->export_tag_count > 0
&& !(module_inst->e->export_tags = export_tags_instantiate(
module, module_inst, module_inst->e->export_tag_count,
error_buf, error_buf_size)))
#endif
#if WASM_ENABLE_MULTI_MODULE != 0
|| (module_inst->export_global_count > 0
&& !(module_inst->export_globals = export_globals_instantiate(
@ -1765,7 +1922,6 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
) {
goto fail;
}
if (global_count > 0) {
/* Initialize the global data */
global_data = module_inst->global_data;
@ -2188,8 +2344,16 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst)
tables_deinstantiate(module_inst);
functions_deinstantiate(module_inst->e->functions,
module_inst->e->function_count);
#if WASM_ENABLE_TAGS != 0
tags_deinstantiate(module_inst->e->tags, module_inst->e->import_tag_ptrs);
#endif
globals_deinstantiate(module_inst->e->globals);
export_functions_deinstantiate(module_inst->export_functions);
#if WASM_ENABLE_TAGS != 0
export_tags_deinstantiate(module_inst->e->export_tags);
#endif
#if WASM_ENABLE_MULTI_MODULE != 0
export_globals_deinstantiate(module_inst->export_globals);
#endif
@ -2270,6 +2434,21 @@ wasm_lookup_table(const WASMModuleInstance *module_inst, const char *name)
(void)module_inst->export_tables;
return module_inst->tables[0];
}
#if WASM_ENABLE_TAGS != 0
WASMTagInstance *
wasm_lookup_tag(const WASMModuleInstance *module_inst, const char *name,
const char *signature)
{
uint32 i;
for (i = 0; i < module_inst->e->export_tag_count; i++)
if (!strcmp(module_inst->e->export_tags[i].name, name))
return module_inst->e->export_tags[i].tag;
(void)signature;
return NULL;
}
#endif
#endif
#ifdef OS_ENABLE_HW_BOUND_CHECK