mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2025-05-09 21:26:21 +00:00
Refine interpreter call native process and memory boundary check (#124)
This commit is contained in:
parent
6e99a37bf2
commit
42dc2d65a1
|
@ -1,72 +1,70 @@
|
||||||
// Licensed to the Apache Software Foundation (ASF) under one or more
|
/*
|
||||||
// contributor license agreements. See the NOTICE file distributed with
|
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||||
// this work for additional information regarding copyright ownership.
|
*
|
||||||
// The ASF licenses this file to You under the Apache License, Version 2.0
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// (the "License"); you may not use this file except in compliance with
|
* you may not use this file except in compliance with the License.
|
||||||
// the License. You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
//
|
*
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
//
|
*
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
// See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
* limitations under the License.
|
||||||
//
|
*/
|
||||||
// Author: Ivan Volosyuk
|
|
||||||
//
|
|
||||||
.text
|
.text
|
||||||
.align 2
|
.align 2
|
||||||
.globl invokeNative
|
.globl invokeNative
|
||||||
.type invokeNative, @function
|
.type invokeNative, @function
|
||||||
invokeNative:
|
invokeNative:
|
||||||
/* rdi - memory */
|
/* rdi - function ptr */
|
||||||
/* rsi - n fp args */
|
/* rsi - argv */
|
||||||
/* rdx - n mem args */
|
/* rdx - n_stacks */
|
||||||
/* rcx - function ptr */
|
|
||||||
|
|
||||||
push %rbp
|
push %rbp
|
||||||
mov %rsp, %rbp
|
mov %rsp, %rbp
|
||||||
|
|
||||||
/* cycle to fill all fp args */
|
mov %rdx, %r10
|
||||||
movq 8(%rdi), %xmm0
|
mov %rsp, %r11 /* Check that stack is aligned on */
|
||||||
movq 16(%rdi), %xmm1
|
and $8, %r11 /* 16 bytes. This code may be removed */
|
||||||
movq 24(%rdi), %xmm2
|
je check_stack_succ /* when we are sure that compiler always */
|
||||||
movq 32(%rdi), %xmm3
|
int3 /* calls us with aligned stack */
|
||||||
movq 40(%rdi), %xmm4
|
check_stack_succ:
|
||||||
movq 48(%rdi), %xmm5
|
mov %r10, %r11 /* Align stack on 16 bytes before pushing */
|
||||||
movq 56(%rdi), %xmm6
|
and $1, %r11 /* stack arguments in case we have an odd */
|
||||||
movq 64(%rdi), %xmm7
|
shl $3, %r11 /* number of stack arguments */
|
||||||
|
sub %r11, %rsp
|
||||||
mov %rsp, %r10 /* Check that stack is aligned on */
|
|
||||||
and $8, %r10 /* 16 bytes. This code may be removed */
|
|
||||||
jz no_abort /* when we are sure that compiler always */
|
|
||||||
int3 /* calls us with aligned stack */
|
|
||||||
no_abort:
|
|
||||||
mov %rdx, %r10 /* Align stack on 16 bytes before pushing */
|
|
||||||
and $1, %r10 /* stack arguments in case we have an odd */
|
|
||||||
shl $3, %r10 /* number of stack arguments */
|
|
||||||
sub %r10, %rsp
|
|
||||||
/* store memory args */
|
/* store memory args */
|
||||||
movq %rcx, %r10 /* func ptr */
|
movq %rdi, %r11 /* func ptr */
|
||||||
movq %rdx, %rcx /* counter */
|
movq %r10, %rcx /* counter */
|
||||||
lea 8+64+48-8(%rdi,%rcx,8), %rdx
|
lea 64+48-8(%rsi,%rcx,8), %r10
|
||||||
sub %rsp, %rdx
|
sub %rsp, %r10
|
||||||
cmpq $0, %rcx
|
cmpq $0, %rcx
|
||||||
jz cycle_end
|
je push_args_end
|
||||||
cycle:
|
push_args:
|
||||||
push 0(%rsp,%rdx)
|
push 0(%rsp,%r10)
|
||||||
loop cycle
|
loop push_args
|
||||||
cycle_end:
|
push_args_end:
|
||||||
movq 80(%rdi), %rsi
|
/* fill all fp args */
|
||||||
movq 88(%rdi), %rdx
|
movq 0x00(%rsi), %xmm0
|
||||||
movq 96(%rdi), %rcx
|
movq 0x08(%rsi), %xmm1
|
||||||
movq 104(%rdi), %r8
|
movq 0x10(%rsi), %xmm2
|
||||||
movq 112(%rdi), %r9
|
movq 0x18(%rsi), %xmm3
|
||||||
|
movq 0x20(%rsi), %xmm4
|
||||||
|
movq 0x28(%rsi), %xmm5
|
||||||
|
movq 0x30(%rsi), %xmm6
|
||||||
|
movq 0x38(%rsi), %xmm7
|
||||||
|
|
||||||
movq 72(%rdi), %rdi
|
/* fill all int args */
|
||||||
|
movq 0x40(%rsi), %rdi
|
||||||
|
movq 0x50(%rsi), %rdx
|
||||||
|
movq 0x58(%rsi), %rcx
|
||||||
|
movq 0x60(%rsi), %r8
|
||||||
|
movq 0x68(%rsi), %r9
|
||||||
|
movq 0x48(%rsi), %rsi
|
||||||
|
|
||||||
call *%r10
|
call *%r11
|
||||||
leave
|
leave
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
|
|
@ -1,56 +1,38 @@
|
||||||
// Copyright (C) 2019 Intel Corporation. All rights reserved.
|
/*
|
||||||
//
|
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
*
|
||||||
// you may not use this file except in compliance with the License.
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// You may obtain a copy of the License at
|
* you may not use this file except in compliance with the License.
|
||||||
//
|
* You may obtain a copy of the License at
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
*
|
||||||
//
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
*
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
// See the License for the specific language governing permissions and
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
// limitations under the License.
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
// Licensed to the Apache Software Foundation (ASF) under one or more
|
|
||||||
// contributor license agreements. See the NOTICE file distributed with
|
|
||||||
// this work for additional information regarding copyright ownership.
|
|
||||||
// The ASF licenses this file to You under the Apache License, Version 2.0
|
|
||||||
// (the "License"); you may not use this file except in compliance with
|
|
||||||
// the License. You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
//
|
|
||||||
// Author: Ivan Volosyuk
|
|
||||||
//
|
|
||||||
.text
|
.text
|
||||||
.align 2
|
.align 2
|
||||||
.globl invokeNative
|
.globl invokeNative
|
||||||
.type invokeNative, @function
|
.type invokeNative, @function
|
||||||
invokeNative:
|
invokeNative:
|
||||||
|
|
||||||
push %ebp
|
push %ebp
|
||||||
movl %esp, %ebp
|
movl %esp, %ebp
|
||||||
push %ecx
|
movl 16(%ebp), %ecx /* ecx = argc */
|
||||||
movl 8(%ebp), %eax /* eax = argv */
|
movl 12(%ebp), %edx /* edx = argv */
|
||||||
movl 12(%ebp), %ecx /* ecx = argc */
|
|
||||||
test %ecx, %ecx
|
test %ecx, %ecx
|
||||||
je restore_ecx /* if ecx == 0, skip pushing arguments */
|
jz skip_push_args /* if ecx == 0, skip pushing arguments */
|
||||||
leal -4(%eax,%ecx,4), %eax /* eax = eax + ecx * 4 - 4 */
|
leal -4(%edx,%ecx,4), %edx /* edx = edx + ecx * 4 - 4 */
|
||||||
subl %esp, %eax /* eax = eax - esp */
|
subl %esp, %edx /* edx = edx - esp */
|
||||||
1:
|
1:
|
||||||
push 0(%esp,%eax)
|
push 0(%esp,%edx)
|
||||||
loop 1b /* loop ecx counts */
|
loop 1b /* loop ecx counts */
|
||||||
restore_ecx:
|
skip_push_args:
|
||||||
movl -4(%ebp), %ecx /* restore ecx */
|
movl 8(%ebp), %edx /* edx = func_ptr */
|
||||||
movl 16(%ebp), %eax /* eax = func_ptr */
|
call *%edx
|
||||||
call *%eax
|
|
||||||
leave
|
leave
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
|
|
@ -75,17 +75,17 @@ GET_F64_FROM_ADDR (uint32 *addr)
|
||||||
#endif /* WASM_CPU_SUPPORTS_UNALIGNED_64BIT_ACCESS != 0 */
|
#endif /* WASM_CPU_SUPPORTS_UNALIGNED_64BIT_ACCESS != 0 */
|
||||||
|
|
||||||
#if WASM_ENABLE_EXT_MEMORY_SPACE != 0
|
#if WASM_ENABLE_EXT_MEMORY_SPACE != 0
|
||||||
#define CHECK_EXT_MEMORY_SPACE() \
|
#define CHECK_EXT_MEMORY_SPACE() \
|
||||||
else if (module->ext_mem_data \
|
else if (module->ext_mem_data \
|
||||||
&& module->ext_mem_base_offset <= offset1 \
|
&& module->ext_mem_base_offset <= offset1 \
|
||||||
&& offset1 < module->ext_mem_base_offset \
|
&& offset1 < module->ext_mem_base_offset \
|
||||||
+ module->ext_mem_size) { \
|
+ module->ext_mem_size) { \
|
||||||
|
/* If offset1 is in valid range, maddr must also be in valid range, \
|
||||||
|
no need to check it again. */ \
|
||||||
maddr = module->ext_mem_data \
|
maddr = module->ext_mem_data \
|
||||||
+ (offset1 - module->ext_mem_base_offset); \
|
+ (offset1 - module->ext_mem_base_offset); \
|
||||||
if (maddr < module->ext_mem_data) \
|
if (maddr + LOAD_SIZE[opcode - WASM_OP_I32_LOAD] > \
|
||||||
goto out_of_bounds; \
|
module->ext_mem_data_end) \
|
||||||
maddr1 = maddr + LOAD_SIZE[opcode - WASM_OP_I32_LOAD]; \
|
|
||||||
if (maddr1 > module->ext_mem_data_end) \
|
|
||||||
goto out_of_bounds; \
|
goto out_of_bounds; \
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
@ -94,26 +94,25 @@ GET_F64_FROM_ADDR (uint32 *addr)
|
||||||
|
|
||||||
#define CHECK_MEMORY_OVERFLOW() do { \
|
#define CHECK_MEMORY_OVERFLOW() do { \
|
||||||
uint32 offset1 = offset + addr; \
|
uint32 offset1 = offset + addr; \
|
||||||
uint8 *maddr1; \
|
/* if (flags != 2) \
|
||||||
if (flags != 2) \
|
LOG_VERBOSE("unaligned load/store in wasm interp, flag: %d.\n", flags); */\
|
||||||
LOG_VERBOSE("unaligned load/store in wasm interp, flag is: %d.\n", flags);\
|
/* The WASM spec doesn't require that the dynamic address operand must be \
|
||||||
if (offset1 < offset) \
|
unsigned, so we don't check whether integer overflow or not here. */ \
|
||||||
goto out_of_bounds; \
|
/* if (offset1 < offset) \
|
||||||
if (offset1 < heap_base_offset) { \
|
goto out_of_bounds; */ \
|
||||||
|
if (offset1 < memory_data_size) { \
|
||||||
|
/* If offset1 is in valid range, maddr must also be in valid range, \
|
||||||
|
no need to check it again. */ \
|
||||||
maddr = memory->memory_data + offset1; \
|
maddr = memory->memory_data + offset1; \
|
||||||
if (maddr < memory->base_addr) \
|
if (maddr + LOAD_SIZE[opcode - WASM_OP_I32_LOAD] > memory->end_addr) \
|
||||||
goto out_of_bounds; \
|
|
||||||
maddr1 = maddr + LOAD_SIZE[opcode - WASM_OP_I32_LOAD]; \
|
|
||||||
if (maddr1 > memory->end_addr) \
|
|
||||||
goto out_of_bounds; \
|
goto out_of_bounds; \
|
||||||
} \
|
} \
|
||||||
else if (offset1 < memory->heap_base_offset \
|
else if (offset1 > heap_base_offset \
|
||||||
+ (memory->heap_data_end - memory->heap_data)) { \
|
&& offset1 < heap_base_offset + heap_data_size) { \
|
||||||
|
/* If offset1 is in valid range, maddr must also be in valid range, \
|
||||||
|
no need to check it again. */ \
|
||||||
maddr = memory->heap_data + offset1 - memory->heap_base_offset; \
|
maddr = memory->heap_data + offset1 - memory->heap_base_offset; \
|
||||||
if (maddr < memory->heap_data) \
|
if (maddr + LOAD_SIZE[opcode - WASM_OP_I32_LOAD] > memory->heap_data_end) \
|
||||||
goto out_of_bounds; \
|
|
||||||
maddr1 = maddr + LOAD_SIZE[opcode - WASM_OP_I32_LOAD]; \
|
|
||||||
if (maddr1 > memory->heap_data_end) \
|
|
||||||
goto out_of_bounds; \
|
goto out_of_bounds; \
|
||||||
} \
|
} \
|
||||||
CHECK_EXT_MEMORY_SPACE() \
|
CHECK_EXT_MEMORY_SPACE() \
|
||||||
|
@ -684,7 +683,11 @@ wasm_interp_call_func_bytecode(WASMThread *self,
|
||||||
{
|
{
|
||||||
WASMModuleInstance *module = self->module_inst;
|
WASMModuleInstance *module = self->module_inst;
|
||||||
WASMMemoryInstance *memory = module->default_memory;
|
WASMMemoryInstance *memory = module->default_memory;
|
||||||
int32 heap_base_offset = memory ? memory->heap_base_offset : 0;
|
uint32 memory_data_size = memory
|
||||||
|
? NumBytesPerPage * memory->cur_page_count : 0;
|
||||||
|
uint32 heap_base_offset = memory ? memory->heap_base_offset : 0;
|
||||||
|
uint32 heap_data_size = memory
|
||||||
|
? memory->heap_data_end - memory->heap_data : 0;
|
||||||
WASMTableInstance *table = module->default_table;
|
WASMTableInstance *table = module->default_table;
|
||||||
uint8 opcode_IMPDEP2 = WASM_OP_IMPDEP2;
|
uint8 opcode_IMPDEP2 = WASM_OP_IMPDEP2;
|
||||||
WASMInterpFrame *frame = NULL;
|
WASMInterpFrame *frame = NULL;
|
||||||
|
@ -1302,6 +1305,7 @@ wasm_interp_call_func_bytecode(WASMThread *self,
|
||||||
PUSH_I32(prev_page_count);
|
PUSH_I32(prev_page_count);
|
||||||
/* update the memory instance ptr */
|
/* update the memory instance ptr */
|
||||||
memory = module->default_memory;
|
memory = module->default_memory;
|
||||||
|
memory_data_size = NumBytesPerPage * memory->cur_page_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
(void)reserved;
|
(void)reserved;
|
||||||
|
|
|
@ -1459,13 +1459,13 @@ word_copy(uint32 *dest, uint32 *src, unsigned num)
|
||||||
#if !defined(__x86_64__) && !defined(__amd_64__)
|
#if !defined(__x86_64__) && !defined(__amd_64__)
|
||||||
|
|
||||||
typedef void (*GenericFunctionPointer)();
|
typedef void (*GenericFunctionPointer)();
|
||||||
int64 invokeNative(uint32 *args, uint32 sz, GenericFunctionPointer f);
|
int64 invokeNative(GenericFunctionPointer f, uint32 *args, uint32 sz);
|
||||||
|
|
||||||
typedef float64 (*Float64FuncPtr)(uint32*, uint32, GenericFunctionPointer);
|
typedef float64 (*Float64FuncPtr)(GenericFunctionPointer f, uint32*, uint32);
|
||||||
typedef float32 (*Float32FuncPtr)(uint32*, uint32, GenericFunctionPointer);
|
typedef float32 (*Float32FuncPtr)(GenericFunctionPointer f, uint32*, uint32);
|
||||||
typedef int64 (*Int64FuncPtr)(uint32*, uint32, GenericFunctionPointer);
|
typedef int64 (*Int64FuncPtr)(GenericFunctionPointer f, uint32*, uint32);
|
||||||
typedef int32 (*Int32FuncPtr)(uint32*, uint32, GenericFunctionPointer);
|
typedef int32 (*Int32FuncPtr)(GenericFunctionPointer f, uint32*, uint32);
|
||||||
typedef void (*VoidFuncPtr)(uint32*, uint32, GenericFunctionPointer);
|
typedef void (*VoidFuncPtr)(GenericFunctionPointer f, uint32*, uint32);
|
||||||
|
|
||||||
static Int64FuncPtr invokeNative_Int64 = (Int64FuncPtr)invokeNative;
|
static Int64FuncPtr invokeNative_Int64 = (Int64FuncPtr)invokeNative;
|
||||||
static Int32FuncPtr invokeNative_Int32 = (Int32FuncPtr)invokeNative;
|
static Int32FuncPtr invokeNative_Int32 = (Int32FuncPtr)invokeNative;
|
||||||
|
@ -1528,21 +1528,21 @@ wasm_runtime_invoke_native(void *func_ptr, WASMType *func_type,
|
||||||
|
|
||||||
argc1 = j;
|
argc1 = j;
|
||||||
if (func_type->result_count == 0) {
|
if (func_type->result_count == 0) {
|
||||||
invokeNative_Void(argv1, argc1, func_ptr);
|
invokeNative_Void(func_ptr, argv1, argc1);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
switch (func_type->types[func_type->param_count]) {
|
switch (func_type->types[func_type->param_count]) {
|
||||||
case VALUE_TYPE_I32:
|
case VALUE_TYPE_I32:
|
||||||
ret[0] = invokeNative_Int32(argv1, argc1, func_ptr);
|
ret[0] = invokeNative_Int32(func_ptr, argv1, argc1);
|
||||||
break;
|
break;
|
||||||
case VALUE_TYPE_I64:
|
case VALUE_TYPE_I64:
|
||||||
PUT_I64_TO_ADDR(ret, invokeNative_Int64(argv1, argc1, func_ptr));
|
PUT_I64_TO_ADDR(ret, invokeNative_Int64(func_ptr, argv1, argc1));
|
||||||
break;
|
break;
|
||||||
case VALUE_TYPE_F32:
|
case VALUE_TYPE_F32:
|
||||||
*(float32*)ret = invokeNative_Float32(argv1, argc1, func_ptr);
|
*(float32*)ret = invokeNative_Float32(func_ptr, argv1, argc1);
|
||||||
break;
|
break;
|
||||||
case VALUE_TYPE_F64:
|
case VALUE_TYPE_F64:
|
||||||
PUT_F64_TO_ADDR(ret, invokeNative_Float64(argv1, argc1, func_ptr));
|
PUT_F64_TO_ADDR(ret, invokeNative_Float64(func_ptr, argv1, argc1));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
wasm_assert(0);
|
wasm_assert(0);
|
||||||
|
@ -1558,13 +1558,13 @@ wasm_runtime_invoke_native(void *func_ptr, WASMType *func_type,
|
||||||
#else /* else of !defined(__x86_64__) && !defined(__amd_64__) */
|
#else /* else of !defined(__x86_64__) && !defined(__amd_64__) */
|
||||||
|
|
||||||
typedef void (*GenericFunctionPointer)();
|
typedef void (*GenericFunctionPointer)();
|
||||||
int64 invokeNative(uint64 *args, uint64 n_fps, uint64 n_stacks, GenericFunctionPointer f);
|
int64 invokeNative(GenericFunctionPointer f, uint64 *args, uint64 n_stacks);
|
||||||
|
|
||||||
typedef float64 (*Float64FuncPtr)(uint64*, uint64, uint64, GenericFunctionPointer);
|
typedef float64 (*Float64FuncPtr)(GenericFunctionPointer, uint64*, uint64);
|
||||||
typedef float32 (*Float32FuncPtr)(uint64*, uint64, uint64, GenericFunctionPointer);
|
typedef float32 (*Float32FuncPtr)(GenericFunctionPointer, uint64*, uint64);
|
||||||
typedef int64 (*Int64FuncPtr)(uint64*,uint64, uint64, GenericFunctionPointer);
|
typedef int64 (*Int64FuncPtr)(GenericFunctionPointer, uint64*,uint64);
|
||||||
typedef int32 (*Int32FuncPtr)(uint64*, uint64, uint64, GenericFunctionPointer);
|
typedef int32 (*Int32FuncPtr)(GenericFunctionPointer, uint64*, uint64);
|
||||||
typedef void (*VoidFuncPtr)(uint64*, uint64, uint64, GenericFunctionPointer);
|
typedef void (*VoidFuncPtr)(GenericFunctionPointer, uint64*, uint64);
|
||||||
|
|
||||||
static Float64FuncPtr invokeNative_Float64 = (Float64FuncPtr)invokeNative;
|
static Float64FuncPtr invokeNative_Float64 = (Float64FuncPtr)invokeNative;
|
||||||
static Float32FuncPtr invokeNative_Float32 = (Float32FuncPtr)invokeNative;
|
static Float32FuncPtr invokeNative_Float32 = (Float32FuncPtr)invokeNative;
|
||||||
|
@ -1604,7 +1604,7 @@ wasm_runtime_invoke_native(void *func_ptr, WASMType *func_type,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fps = argv1 + 1;
|
fps = argv1;
|
||||||
ints = fps + MAX_REG_FLOATS;
|
ints = fps + MAX_REG_FLOATS;
|
||||||
stacks = ints + MAX_REG_INTS;
|
stacks = ints + MAX_REG_INTS;
|
||||||
|
|
||||||
|
@ -1645,21 +1645,21 @@ wasm_runtime_invoke_native(void *func_ptr, WASMType *func_type,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (func_type->result_count == 0) {
|
if (func_type->result_count == 0) {
|
||||||
invokeNative_Void(argv1, n_fps, n_stacks, func_ptr);
|
invokeNative_Void(func_ptr, argv1, n_stacks);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
switch (func_type->types[func_type->param_count]) {
|
switch (func_type->types[func_type->param_count]) {
|
||||||
case VALUE_TYPE_I32:
|
case VALUE_TYPE_I32:
|
||||||
ret[0] = invokeNative_Int32(argv1, n_fps, n_stacks, func_ptr);
|
ret[0] = invokeNative_Int32(func_ptr, argv1, n_stacks);
|
||||||
break;
|
break;
|
||||||
case VALUE_TYPE_I64:
|
case VALUE_TYPE_I64:
|
||||||
PUT_I64_TO_ADDR(ret, invokeNative_Int64(argv1, n_fps, n_stacks, func_ptr));
|
PUT_I64_TO_ADDR(ret, invokeNative_Int64(func_ptr, argv1, n_stacks));
|
||||||
break;
|
break;
|
||||||
case VALUE_TYPE_F32:
|
case VALUE_TYPE_F32:
|
||||||
*(float32*)ret = invokeNative_Float32(argv1, n_fps, n_stacks, func_ptr);
|
*(float32*)ret = invokeNative_Float32(func_ptr, argv1, n_stacks);
|
||||||
break;
|
break;
|
||||||
case VALUE_TYPE_F64:
|
case VALUE_TYPE_F64:
|
||||||
PUT_F64_TO_ADDR(ret, invokeNative_Float64(argv1, n_fps, n_stacks, func_ptr));
|
PUT_F64_TO_ADDR(ret, invokeNative_Float64(func_ptr, argv1, n_stacks));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
wasm_assert(0);
|
wasm_assert(0);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user