Add parameter module inst for native wrapper functions (#117)

And add asm code of em64/arm/mips version to call native wrapper functions;
Fix some issues of calling wrapper functions;
This commit is contained in:
wenyongh
2019-09-10 10:23:46 +08:00
committed by GitHub
parent 2294f52e3a
commit 26149021ff
58 changed files with 1287 additions and 494 deletions

View File

@ -35,9 +35,6 @@
#include <errno.h>
#define get_module_inst() \
wasm_runtime_get_current_module_inst()
#define validate_app_addr(offset, size) \
wasm_runtime_validate_app_addr(module_inst, offset, size)
@ -55,7 +52,7 @@
static int32
__syscall0_wrapper(int32 arg0)
__syscall0_wrapper(WASMModuleInstance *module_inst, int32 arg0)
{
switch (arg0) {
case 199: /* getuid */
@ -67,7 +64,7 @@ __syscall0_wrapper(int32 arg0)
}
static int32
__syscall1_wrapper(int32 arg0, int32 arg1)
__syscall1_wrapper(WASMModuleInstance *module_inst, int32 arg0, int32 arg1)
{
switch (arg0) {
case 6: /* close */
@ -79,7 +76,8 @@ __syscall1_wrapper(int32 arg0, int32 arg1)
}
static int32
__syscall2_wrapper(int32 arg0, int32 arg1, int32 arg2)
__syscall2_wrapper(WASMModuleInstance *module_inst,
int32 arg0, int32 arg1, int32 arg2)
{
switch (arg0) {
case 183: /* getcwd */
@ -91,10 +89,9 @@ __syscall2_wrapper(int32 arg0, int32 arg1, int32 arg2)
}
static int32
__syscall3_wrapper(int32 arg0, int32 arg1, int32 arg2, int32 arg3)
__syscall3_wrapper(WASMModuleInstance *module_inst,
int32 arg0, int32 arg1, int32 arg2, int32 arg3)
{
WASMModuleInstance *module_inst = get_module_inst();
switch (arg0) {
case 146: /* writev */
{
@ -145,7 +142,8 @@ __syscall3_wrapper(int32 arg0, int32 arg1, int32 arg2, int32 arg3)
}
static int32
__syscall4_wrapper(int32 arg0, int32 arg1, int32 arg2,
__syscall4_wrapper(WASMModuleInstance *module_inst,
int32 arg0, int32 arg1, int32 arg2,
int32 arg3, int32 arg4)
{
bh_printf("##_syscall4 called, syscall id: %d\n", arg0);
@ -153,7 +151,8 @@ __syscall4_wrapper(int32 arg0, int32 arg1, int32 arg2,
}
static int32
__syscall5_wrapper(int32 arg0, int32 arg1, int32 arg2,
__syscall5_wrapper(WASMModuleInstance *module_inst,
int32 arg0, int32 arg1, int32 arg2,
int32 arg3, int32 arg4, int32 arg5)
{
switch (arg0) {
@ -166,46 +165,54 @@ __syscall5_wrapper(int32 arg0, int32 arg1, int32 arg2,
}
#define GET_EMCC_SYSCALL_ARGS() \
WASMModuleInstance *module_inst = get_module_inst(); \
int32 *args; \
if (!validate_app_addr(args_off, 1)) \
return 0; \
args = addr_app_to_native(args_off) \
#define EMCC_SYSCALL_WRAPPER0(id) \
static int32 ___syscall##id##_wrapper(int32 _id) { \
return __syscall0_wrapper(id); \
#define EMCC_SYSCALL_WRAPPER0(id) \
static int32 ___syscall##id##_wrapper(WASMModuleInstance *module_inst,\
int32 _id) { \
return __syscall0_wrapper(module_inst, id); \
}
#define EMCC_SYSCALL_WRAPPER1(id) \
static int32 ___syscall##id##_wrapper(int32 _id, int32 args_off) {\
GET_EMCC_SYSCALL_ARGS(); \
return __syscall1_wrapper(id, args[0]); \
#define EMCC_SYSCALL_WRAPPER1(id) \
static int32 ___syscall##id##_wrapper(WASMModuleInstance *module_inst,\
int32 _id, int32 args_off) { \
GET_EMCC_SYSCALL_ARGS(); \
return __syscall1_wrapper(module_inst, id, args[0]); \
}
#define EMCC_SYSCALL_WRAPPER2(id) \
static int32 ___syscall##id##_wrapper(int32 _id, int32 args_off) {\
GET_EMCC_SYSCALL_ARGS(); \
return __syscall2_wrapper(id, args[0], args[1]); \
#define EMCC_SYSCALL_WRAPPER2(id) \
static int32 ___syscall##id##_wrapper(WASMModuleInstance *module_inst,\
int32 _id, int32 args_off){ \
GET_EMCC_SYSCALL_ARGS(); \
return __syscall2_wrapper(module_inst, id, args[0], args[1]); \
}
#define EMCC_SYSCALL_WRAPPER3(id) \
static int32 ___syscall##id##_wrapper(int32 _id, int32 args_off) {\
GET_EMCC_SYSCALL_ARGS(); \
return __syscall3_wrapper(id, args[0], args[1], args[2]); \
#define EMCC_SYSCALL_WRAPPER3(id) \
static int32 ___syscall##id##_wrapper(WASMModuleInstance *module_inst,\
int32 _id, int32 args_off) { \
GET_EMCC_SYSCALL_ARGS(); \
return __syscall3_wrapper(module_inst, id, \
args[0], args[1], args[2]); \
}
#define EMCC_SYSCALL_WRAPPER4(id) \
static int32 ___syscall##id##_wrapper(int32 _id, int32 args_off) {\
GET_EMCC_SYSCALL_ARGS(); \
return __syscall4_wrapper(id, args[0], args[1], args[2], args[3]);\
#define EMCC_SYSCALL_WRAPPER4(id) \
static int32 ___syscall##id##_wrapper(WASMModuleInstance *module_inst,\
int32 _id, int32 args_off) { \
GET_EMCC_SYSCALL_ARGS(); \
return __syscall4_wrapper(module_inst, id, \
args[0], args[1], args[2], args[3]); \
}
#define EMCC_SYSCALL_WRAPPER5(id) \
static int32 ___syscall##id##_wrapper(int32 _id, int32 args_off) {\
GET_EMCC_SYSCALL_ARGS(); \
return __syscall5_wrapper(id, args[0], args[1], args[2], \
args[3], args[4]); \
#define EMCC_SYSCALL_WRAPPER5(id) \
static int32 ___syscall##id##_wrapper(WASMModuleInstance *module_inst,\
int32 _id, int32 args_off) { \
GET_EMCC_SYSCALL_ARGS(); \
return __syscall5_wrapper(module_inst, id, \
args[0], args[1], args[2], \
args[3], args[4]); \
}
EMCC_SYSCALL_WRAPPER0(199)
@ -224,18 +231,16 @@ EMCC_SYSCALL_WRAPPER3(221)
EMCC_SYSCALL_WRAPPER5(140)
static int32
getTotalMemory_wrapper()
getTotalMemory_wrapper(WASMModuleInstance *module_inst)
{
WASMModuleInstance *module_inst = wasm_runtime_get_current_module_inst();
WASMMemoryInstance *memory = module_inst->default_memory;
return NumBytesPerPage * memory->cur_page_count;
}
static int32
enlargeMemory_wrapper()
enlargeMemory_wrapper(WASMModuleInstance *module_inst)
{
bool ret;
WASMModuleInstance *module_inst = wasm_runtime_get_current_module_inst();
WASMMemoryInstance *memory = module_inst->default_memory;
uint32 DYNAMICTOP_PTR_offset = module_inst->DYNAMICTOP_PTR_offset;
uint32 addr_data_offset = *(uint32*)(memory->global_data + DYNAMICTOP_PTR_offset);
@ -254,9 +259,8 @@ enlargeMemory_wrapper()
}
static void
_abort_wrapper(int32 code)
_abort_wrapper(WASMModuleInstance *module_inst, int32 code)
{
WASMModuleInstance *module_inst = wasm_runtime_get_current_module_inst();
char buf[32];
snprintf(buf, sizeof(buf), "env.abort(%i)", code);
@ -264,14 +268,13 @@ _abort_wrapper(int32 code)
}
static void
abortOnCannotGrowMemory_wrapper()
abortOnCannotGrowMemory_wrapper(WASMModuleInstance *module_inst)
{
WASMModuleInstance *module_inst = wasm_runtime_get_current_module_inst();
wasm_runtime_set_exception(module_inst, "abort on cannot grow memory");
}
static void
___setErrNo_wrapper(int32 error_no)
___setErrNo_wrapper(WASMModuleInstance *module_inst, int32 error_no)
{
errno = error_no;
}
@ -330,3 +333,4 @@ wasm_platform_native_func_lookup(const char *module_name,
return NULL;
}

View File

@ -35,9 +35,6 @@
#include <errno.h>
#define get_module_inst() \
wasm_runtime_get_current_module_inst()
#define validate_app_addr(offset, size) \
wasm_runtime_validate_app_addr(module_inst, offset, size)
@ -55,46 +52,46 @@
static int32
__syscall0_wrapper(int32 arg0)
__syscall0_wrapper(WASMModuleInstance *module_inst, int32 arg0)
{
switch (arg0) {
case 199: /* getuid */
/* TODO */
default:
printf("##_syscall0 called, syscall id: %d\n", arg0);
bh_printf("##_syscall0 called, syscall id: %d\n", arg0);
}
return 0;
}
static int32
__syscall1_wrapper(int32 arg0, int32 arg1)
__syscall1_wrapper(WASMModuleInstance *module_inst, int32 arg0, int32 arg1)
{
switch (arg0) {
case 6: /* close */
/* TODO */
default:
printf("##_syscall1 called, syscall id: %d\n", arg0);
bh_printf("##_syscall1 called, syscall id: %d\n", arg0);
}
return 0;
}
static int32
__syscall2_wrapper(int32 arg0, int32 arg1, int32 arg2)
__syscall2_wrapper(WASMModuleInstance *module_inst,
int32 arg0, int32 arg1, int32 arg2)
{
switch (arg0) {
case 183: /* getcwd */
/* TODO */
default:
printf("##_syscall2 called, syscall id: %d\n", arg0);
bh_printf("##_syscall2 called, syscall id: %d\n", arg0);
}
return 0;
}
static int32
__syscall3_wrapper(int32 arg0, int32 arg1, int32 arg2, int32 arg3)
__syscall3_wrapper(WASMModuleInstance *module_inst,
int32 arg0, int32 arg1, int32 arg2, int32 arg3)
{
WASMModuleInstance *module_inst = get_module_inst();
switch (arg0) {
case 54: /* ioctl */
{
@ -152,73 +149,83 @@ __syscall3_wrapper(int32 arg0, int32 arg1, int32 arg2, int32 arg3)
case 221: /* fcntl */
/* TODO */
default:
printf("##_syscall3 called, syscall id: %d\n", arg0);
bh_printf("##_syscall3 called, syscall id: %d\n", arg0);
}
return 0;
}
static int32
__syscall4_wrapper(int32 arg0, int32 arg1, int32 arg2,
__syscall4_wrapper(WASMModuleInstance *module_inst,
int32 arg0, int32 arg1, int32 arg2,
int32 arg3, int32 arg4)
{
printf("##_syscall4 called, syscall id: %d\n", arg0);
bh_printf("##_syscall4 called, syscall id: %d\n", arg0);
return 0;
}
static int32
__syscall5_wrapper(int32 arg0, int32 arg1, int32 arg2,
__syscall5_wrapper(WASMModuleInstance *module_inst,
int32 arg0, int32 arg1, int32 arg2,
int32 arg3, int32 arg4, int32 arg5)
{
switch (arg0) {
case 140: /* llseek */
/* TODO */
default:
printf("##_syscall5 called, args[0]: %d\n", arg0);
bh_printf("##_syscall5 called, args[0]: %d\n", arg0);
}
return 0;
}
#define GET_EMCC_SYSCALL_ARGS() \
WASMModuleInstance *module_inst = get_module_inst(); \
int32 *args; \
if (!validate_app_addr(args_off, 1)) \
return 0; \
args = addr_app_to_native(args_off) \
#define EMCC_SYSCALL_WRAPPER0(id) \
static int32 ___syscall##id##_wrapper(int32 _id) { \
return __syscall0_wrapper(id); \
#define EMCC_SYSCALL_WRAPPER0(id) \
static int32 ___syscall##id##_wrapper(WASMModuleInstance *module_inst,\
int32 _id) { \
return __syscall0_wrapper(module_inst, id); \
}
#define EMCC_SYSCALL_WRAPPER1(id) \
static int32 ___syscall##id##_wrapper(int32 _id, int32 args_off) {\
GET_EMCC_SYSCALL_ARGS(); \
return __syscall1_wrapper(id, args[0]); \
#define EMCC_SYSCALL_WRAPPER1(id) \
static int32 ___syscall##id##_wrapper(WASMModuleInstance *module_inst,\
int32 _id, int32 args_off) { \
GET_EMCC_SYSCALL_ARGS(); \
return __syscall1_wrapper(module_inst, id, args[0]); \
}
#define EMCC_SYSCALL_WRAPPER2(id) \
static int32 ___syscall##id##_wrapper(int32 _id, int32 args_off) {\
GET_EMCC_SYSCALL_ARGS(); \
return __syscall2_wrapper(id, args[0], args[1]); \
#define EMCC_SYSCALL_WRAPPER2(id) \
static int32 ___syscall##id##_wrapper(WASMModuleInstance *module_inst,\
int32 _id, int32 args_off){ \
GET_EMCC_SYSCALL_ARGS(); \
return __syscall2_wrapper(module_inst, id, args[0], args[1]); \
}
#define EMCC_SYSCALL_WRAPPER3(id) \
static int32 ___syscall##id##_wrapper(int32 _id, int32 args_off) {\
GET_EMCC_SYSCALL_ARGS(); \
return __syscall3_wrapper(id, args[0], args[1], args[2]); \
#define EMCC_SYSCALL_WRAPPER3(id) \
static int32 ___syscall##id##_wrapper(WASMModuleInstance *module_inst,\
int32 _id, int32 args_off) { \
GET_EMCC_SYSCALL_ARGS(); \
return __syscall3_wrapper(module_inst, id, \
args[0], args[1], args[2]); \
}
#define EMCC_SYSCALL_WRAPPER4(id) \
static int32 ___syscall##id##_wrapper(int32 _id, int32 args_off) {\
GET_EMCC_SYSCALL_ARGS(); \
return __syscall4_wrapper(id, args[0], args[1], args[2], args[3]);\
#define EMCC_SYSCALL_WRAPPER4(id) \
static int32 ___syscall##id##_wrapper(WASMModuleInstance *module_inst,\
int32 _id, int32 args_off) { \
GET_EMCC_SYSCALL_ARGS(); \
return __syscall4_wrapper(module_inst, id, \
args[0], args[1], args[2], args[3]); \
}
#define EMCC_SYSCALL_WRAPPER5(id) \
static int32 ___syscall##id##_wrapper(int32 _id, int32 args_off) {\
GET_EMCC_SYSCALL_ARGS(); \
return __syscall5_wrapper(id, args[0], args[1], args[2], \
args[3], args[4]); \
#define EMCC_SYSCALL_WRAPPER5(id) \
static int32 ___syscall##id##_wrapper(WASMModuleInstance *module_inst,\
int32 _id, int32 args_off) { \
GET_EMCC_SYSCALL_ARGS(); \
return __syscall5_wrapper(module_inst, id, \
args[0], args[1], args[2], \
args[3], args[4]); \
}
EMCC_SYSCALL_WRAPPER0(199)
@ -237,18 +244,16 @@ EMCC_SYSCALL_WRAPPER3(221)
EMCC_SYSCALL_WRAPPER5(140)
static int32
getTotalMemory_wrapper()
getTotalMemory_wrapper(WASMModuleInstance *module_inst)
{
WASMModuleInstance *module_inst = wasm_runtime_get_current_module_inst();
WASMMemoryInstance *memory = module_inst->default_memory;
return NumBytesPerPage * memory->cur_page_count;
}
static int32
enlargeMemory_wrapper()
enlargeMemory_wrapper(WASMModuleInstance *module_inst)
{
bool ret;
WASMModuleInstance *module_inst = wasm_runtime_get_current_module_inst();
WASMMemoryInstance *memory = module_inst->default_memory;
uint32 DYNAMICTOP_PTR_offset = module_inst->DYNAMICTOP_PTR_offset;
uint32 addr_data_offset = *(uint32*)(memory->global_data + DYNAMICTOP_PTR_offset);
@ -267,9 +272,8 @@ enlargeMemory_wrapper()
}
static void
_abort_wrapper(int32 code)
_abort_wrapper(WASMModuleInstance *module_inst, int32 code)
{
WASMModuleInstance *module_inst = wasm_runtime_get_current_module_inst();
char buf[32];
snprintf(buf, sizeof(buf), "env.abort(%i)", code);
@ -277,14 +281,13 @@ _abort_wrapper(int32 code)
}
static void
abortOnCannotGrowMemory_wrapper()
abortOnCannotGrowMemory_wrapper(WASMModuleInstance *module_inst)
{
WASMModuleInstance *module_inst = wasm_runtime_get_current_module_inst();
wasm_runtime_set_exception(module_inst, "abort on cannot grow memory");
}
static void
___setErrNo_wrapper(int32 error_no)
___setErrNo_wrapper(WASMModuleInstance *module_inst, int32 error_no)
{
errno = error_no;
}

View File

@ -0,0 +1,75 @@
/*
* 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.
* 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.
*/
.text
.align 2
.global invokeNative
.type invokeNative,function
/*
* Arguments passed in:
*
* r0 argv
* r1 argc
* r2 function pntr
*/
invokeNative:
stmfd sp!, {r4, r5, r6, r7, lr}
mov r4, r0 /* get argv */
mov r5, r1 /* get argc */
mov ip, r2 /* get function ptr */
cmp r5, #2 /* is argc < 2 ? */
blt return
ldr r0, [r4], #4 /* argv[0] */
ldr r1, [r4], #4 /* argv[1] */
mov r6, #0
cmp r5, #2
beq call_func
ldr r2, [r4], #4
cmp r5, #3
beq call_func
ldr r3, [r4], #4
subs r5, r5, #4 /* now we have r0 ~ r3 */
/* Ensure address is 8 byte aligned */
mov r6, r5, lsl#2
add r6, r6, #7
bic r6, r6, #7
add r6, r6, #4 /* +4 because only odd(5) registers are in stack */
subs sp, sp, r6 /* for stacked args */
mov r7, sp
loop_args:
cmp r5, #0
beq call_func
ldr lr, [r4], #4
str lr, [r7], #4
subs r5, r5, #1
b loop_args
call_func:
blx ip
add sp, sp, r6 /* recover sp */
return:
ldmfd sp!, {r4, r5, r6, r7, lr}
bx lr

View File

@ -0,0 +1,72 @@
// 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
.align 2
.globl invokeNative
.type invokeNative, @function
invokeNative:
/* rdi - memory */
/* rsi - n fp args */
/* rdx - n mem args */
/* rcx - function ptr */
push %rbp
mov %rsp, %rbp
/* cycle to fill all fp args */
movq 8(%rdi), %xmm0
movq 16(%rdi), %xmm1
movq 24(%rdi), %xmm2
movq 32(%rdi), %xmm3
movq 40(%rdi), %xmm4
movq 48(%rdi), %xmm5
movq 56(%rdi), %xmm6
movq 64(%rdi), %xmm7
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 */
movq %rcx, %r10 /* func ptr */
movq %rdx, %rcx /* counter */
lea 8+64+48-8(%rdi,%rcx,8), %rdx
sub %rsp, %rdx
cmpq $0, %rcx
jz cycle_end
cycle:
push 0(%rsp,%rdx)
loop cycle
cycle_end:
movq 80(%rdi), %rsi
movq 88(%rdi), %rdx
movq 96(%rdi), %rcx
movq 104(%rdi), %r8
movq 112(%rdi), %r9
movq 72(%rdi), %rdi
call *%r10
leave
ret

View File

@ -0,0 +1,85 @@
/*
* 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.
* 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.
*/
.text
.align 2
.globl invokeNative
.ent invokeNative
.type invokeNative, @function
/**
* On function entry parameters:
* $4 = args
* $5 = arg_num
* $6 = func_ptr
*/
invokeNative:
.frame $fp, 8, $0
.mask 0x00000000, 0
.fmask 0x00000000, 0
/* Fixed part of frame */
subu $sp, 8
/* save registers */
sw $31, 4($sp)
sw $fp, 0($sp)
/* set frame pointer to bottom of fixed frame */
move $fp, $sp
/* allocate enough stack space */
sll $11, $5, 2
subu $sp, $11
/* make 8-byte aligned */
and $sp, ~7
move $9, $sp
move $25, $6 /* $25 = func_ptr */
push_args:
beq $5, 0, done /* arg_num == 0 ? */
lw $8, 0($4)
sw $8, 0($9)
addu $4, 4
addu $9, 4
subu $5, 1 /* arg_index-- */
j push_args
done:
lw $4, 0($sp) /* Load $4..$7 from stack */
lw $5, 4($sp)
lw $6, 8($sp)
lw $7, 12($sp)
ldc1 $f12, 0($sp) /* Load $f12, $f13, $f14, $f15 */
ldc1 $f14, 8($sp)
jalr $25 /* call function */
nop
/* restore saved registers */
move $sp, $fp
lw $31, 4($sp)
lw $fp, 0($sp)
/* pop frame */
addu $sp, $sp, 8
j $31
.end invokeNative

View File

@ -17,11 +17,13 @@ set (VMCORE_LIB_DIR ${CMAKE_CURRENT_LIST_DIR})
include_directories(${VMCORE_LIB_DIR})
include_directories(${VMCORE_LIB_DIR}/../include)
file (GLOB_RECURSE c_source_all ${VMCORE_LIB_DIR}/*.c)
list (REMOVE_ITEM c_source_all ${VMCORE_LIB_DIR}/invokeNative_general.c)
if (${BUILD_AS_64BIT_SUPPORT} STREQUAL "YES")
file (GLOB_RECURSE source_all ${VMCORE_LIB_DIR}/*.c)
set (source_all ${c_source_all} ${VMCORE_LIB_DIR}/invokeNative_em64.s)
else ()
file (GLOB_RECURSE source_all ${VMCORE_LIB_DIR}/*.c ${VMCORE_LIB_DIR}/*.s)
list (REMOVE_ITEM source_all ${VMCORE_LIB_DIR}/invokeNative_general.c)
set (source_all ${c_source_all} ${VMCORE_LIB_DIR}/invokeNative_ia32.s)
endif ()
set (VMCORE_LIB_SOURCE ${source_all})

View File

@ -284,7 +284,7 @@ read_leb(const uint8 *buf, uint32 *p_offset, uint32 maxbits, bool sign)
}
if (sign && (shift < maxbits) && (byte & 0x40)) {
/* Sign extend */
result |= - (1 << shift);
result |= - ((uint64)1 << shift);
}
return result;
}
@ -622,21 +622,6 @@ FREE_FRAME(WASMThread *self, WASMInterpFrame *frame)
wasm_thread_free_wasm_frame(self, frame);
}
typedef void (*GenericFunctionPointer)();
int64 invokeNative(uint32 *args, uint32 sz, GenericFunctionPointer f);
typedef float64 (*Float64FuncPtr)(uint32*, uint32, GenericFunctionPointer);
typedef float32 (*Float32FuncPtr)(uint32*, uint32, GenericFunctionPointer);
typedef int64 (*Int64FuncPtr)(uint32*, uint32, GenericFunctionPointer);
typedef int32 (*Int32FuncPtr)(uint32*, uint32, GenericFunctionPointer);
typedef void (*VoidFuncPtr)(uint32*, uint32, GenericFunctionPointer);
static Int64FuncPtr invokeNative_Int64 = (Int64FuncPtr)invokeNative;
static Int32FuncPtr invokeNative_Int32 = (Int32FuncPtr)invokeNative;
static Float64FuncPtr invokeNative_Float64 = (Float64FuncPtr)invokeNative;
static Float32FuncPtr invokeNative_Float32 = (Float32FuncPtr)invokeNative;
static VoidFuncPtr invokeNative_Void = (VoidFuncPtr)invokeNative;
static void
wasm_interp_call_func_native(WASMThread *self,
WASMFunctionInstance *cur_func,
@ -644,9 +629,8 @@ wasm_interp_call_func_native(WASMThread *self,
{
unsigned local_cell_num = 2;
WASMInterpFrame *frame;
typedef void (*F)(WASMThread*, uint32 *argv);
union { F f; void *v; } u;
uint32 argv_buf[32], *argv, argc = cur_func->param_cell_num;
uint32 argv_ret[2];
bool ret;
if (!(frame = ALLOC_FRAME
(self, wasm_interp_interp_frame_size(local_cell_num), prev_frame)))
@ -658,60 +642,24 @@ wasm_interp_call_func_native(WASMThread *self,
wasm_thread_set_cur_frame (self, frame);
if (argc <= 32)
argv = argv_buf;
else {
if (!(argv = wasm_malloc(sizeof(uint32) * argc))) {
wasm_runtime_set_exception(self->module_inst,
"WASM call native failed: allocate memory failed.");
return;
}
}
ret = wasm_runtime_invoke_native(cur_func->u.func_import->func_ptr_linked,
cur_func->u.func_import->func_type,
self->module_inst,
frame->lp, cur_func->param_cell_num, argv_ret);
word_copy(argv, frame->lp, argc);
u.v = cur_func->u.func_import->func_ptr_linked;
{
WASMType *func_type = cur_func->u.func_import->func_type;
uint8 ret_type = func_type->result_count
? func_type->types[func_type->param_count]
: VALUE_TYPE_VOID;
GenericFunctionPointer f = (GenericFunctionPointer)(uintptr_t)u.v;
if (func_type->result_count == 0) {
invokeNative_Void(argv, argc, f);
}
else {
switch (ret_type) {
case VALUE_TYPE_I32:
argv[0] = invokeNative_Int32(argv, argc, f);
break;
case VALUE_TYPE_I64:
PUT_I64_TO_ADDR(argv, invokeNative_Int64(argv, argc, f));
break;
case VALUE_TYPE_F32:
*(float32*)argv = invokeNative_Float32(argv, argc, f);
break;
case VALUE_TYPE_F64:
PUT_F64_TO_ADDR(argv, invokeNative_Float64(argv, argc, f));
break;
}
}
}
if (!ret)
return;
if (cur_func->ret_cell_num == 1) {
prev_frame->sp[0] = argv[0];
prev_frame->sp[0] = argv_ret[0];
prev_frame->sp++;
}
else if (cur_func->ret_cell_num == 2) {
prev_frame->sp[0] = argv[0];
prev_frame->sp[1] = argv[1];
prev_frame->sp[0] = argv_ret[0];
prev_frame->sp[1] = argv_ret[1];
prev_frame->sp += 2;
}
if (argc > 32)
wasm_free(argv);
FREE_FRAME(self, frame);
wasm_thread_set_cur_frame(self, prev_frame);
}

View File

@ -72,7 +72,7 @@ read_leb(const uint8 *buf, const uint8 *buf_end,
}
if (sign && (shift < maxbits) && (byte & 0x40)) {
/* Sign extend */
result |= - (1 << shift);
result |= - ((uint64)1 << shift);
}
*p_result = result;
return true;

View File

@ -70,33 +70,41 @@ wasm_runtime_call_wasm(WASMModuleInstance *module_inst,
WASMFunctionInstance *function,
unsigned argc, uint32 argv[])
{
if (!exec_env) {
if (!module_inst->wasm_stack) {
if (!(module_inst->wasm_stack =
wasm_malloc(module_inst->wasm_stack_size))) {
wasm_runtime_set_exception(module_inst, "allocate memory failed.");
return false;
/* Only init stack when no application is running. */
if (!wasm_runtime_get_self()->cur_frame) {
if (!exec_env) {
if (!module_inst->wasm_stack) {
if (!(module_inst->wasm_stack =
wasm_malloc(module_inst->wasm_stack_size))) {
wasm_runtime_set_exception(module_inst,
"allocate memory failed.");
return false;
}
init_wasm_stack(&module_inst->main_tlr.wasm_stack,
module_inst->wasm_stack,
module_inst->wasm_stack_size);
}
}
}
else {
uintptr_t stack = (uintptr_t)exec_env->stack;
uint32 stack_size;
init_wasm_stack(&module_inst->main_tlr.wasm_stack,
module_inst->wasm_stack, module_inst->wasm_stack_size);
}
else {
uintptr_t stack = (uintptr_t)exec_env->stack;
uint32 stack_size;
/* Set to 8 bytes align */
stack = (stack + 7) & ~7;
stack_size = exec_env->stack_size
- (stack - (uintptr_t)exec_env->stack);
/* Set to 8 bytes align */
stack = (stack + 7) & ~7;
stack_size = exec_env->stack_size - (stack - (uintptr_t)exec_env->stack);
if (!exec_env->stack || exec_env->stack_size <= 0
|| exec_env->stack_size < stack - (uintptr_t)exec_env->stack) {
wasm_runtime_set_exception(module_inst,
"Invalid execution stack info.");
return false;
}
if (!exec_env->stack || exec_env->stack_size <= 0
|| exec_env->stack_size < stack - (uintptr_t)exec_env->stack) {
wasm_runtime_set_exception(module_inst, "Invalid execution stack info.");
return false;
}
init_wasm_stack(&module_inst->main_tlr.wasm_stack, (uint8*)stack, stack_size);
init_wasm_stack(&module_inst->main_tlr.wasm_stack,
(uint8*)stack, stack_size);
}
}
wasm_interp_call_wasm(function, argc, argv);
@ -1419,3 +1427,248 @@ wasm_runtime_load_aot(uint8 *aot_file, uint32 aot_file_size,
return NULL;
}
static inline void
word_copy(uint32 *dest, uint32 *src, unsigned num)
{
for (; num > 0; num--)
*dest++ = *src++;
}
#define PUT_I64_TO_ADDR(addr, value) do { \
union { int64 val; uint32 parts[2]; } u; \
u.val = (value); \
(addr)[0] = u.parts[0]; \
(addr)[1] = u.parts[1]; \
} while (0)
#define PUT_F64_TO_ADDR(addr, value) do { \
union { float64 val; uint32 parts[2]; } u; \
u.val = (value); \
(addr)[0] = u.parts[0]; \
(addr)[1] = u.parts[1]; \
} while (0)
#if !defined(__x86_64__) && !defined(__amd_64__)
typedef void (*GenericFunctionPointer)();
int64 invokeNative(uint32 *args, uint32 sz, GenericFunctionPointer f);
typedef float64 (*Float64FuncPtr)(uint32*, uint32, GenericFunctionPointer);
typedef float32 (*Float32FuncPtr)(uint32*, uint32, GenericFunctionPointer);
typedef int64 (*Int64FuncPtr)(uint32*, uint32, GenericFunctionPointer);
typedef int32 (*Int32FuncPtr)(uint32*, uint32, GenericFunctionPointer);
typedef void (*VoidFuncPtr)(uint32*, uint32, GenericFunctionPointer);
static Int64FuncPtr invokeNative_Int64 = (Int64FuncPtr)invokeNative;
static Int32FuncPtr invokeNative_Int32 = (Int32FuncPtr)invokeNative;
static Float64FuncPtr invokeNative_Float64 = (Float64FuncPtr)invokeNative;
static Float32FuncPtr invokeNative_Float32 = (Float32FuncPtr)invokeNative;
static VoidFuncPtr invokeNative_Void = (VoidFuncPtr)invokeNative;
/* As JavaScript can't represent int64s, emcc compiles C int64 argument
into two WASM i32 arguments, see:
https://github.com/emscripten-core/emscripten/issues/7199
And also JavaScript float point is always 64-bit, emcc compiles
float32 argument into WASM f64 argument.
But clang compiles C int64 argument into WASM i64 argument, and
compiles C float32 argument into WASM f32 argument.
So for the compatability of emcc and clang, we treat i64 as two i32s,
treat f32 as f64 while passing arguments to the native function, and
require the native function uses two i32 arguments instead one i64
argument, and uses double argument instead of float argment. */
bool
wasm_runtime_invoke_native(void *func_ptr, WASMType *func_type,
WASMModuleInstance *module_inst,
uint32 *argv, uint32 argc, uint32 *ret)
{
union { float64 val; int32 parts[2]; } u;
uint32 argv_buf[32], *argv1 = argv_buf, argc1, i, j = 0;
uint64 size;
argc1 = func_type->param_count * 2 + 2;
if (argc1 > sizeof(argv_buf) / sizeof(uint32)) {
size = ((uint64)sizeof(uint32)) * argc1;
if (size >= UINT_MAX
|| !(argv1 = wasm_malloc((uint32)size))) {
wasm_runtime_set_exception(module_inst, "allocate memory failed.");
return false;
}
}
for (i = 0; i < sizeof(WASMModuleInstance*) / sizeof(uint32); i++)
argv1[j++] = ((uint32*)&module_inst)[i];
for (i = 0; i < func_type->param_count; i++) {
switch (func_type->types[i]) {
case VALUE_TYPE_I32:
argv1[j++] = *argv++;
break;
case VALUE_TYPE_I64:
case VALUE_TYPE_F64:
argv1[j++] = *argv++;
argv1[j++] = *argv++;
break;
case VALUE_TYPE_F32:
u.val = *(float32*)argv++;
#if defined(__arm__) || defined(__mips__)
/* 64-bit data must be 8 bytes alined in arm and mips */
if (j & 1)
j++;
#endif
argv1[j++] = u.parts[0];
argv1[j++] = u.parts[1];
break;
default:
wasm_assert(0);
break;
}
}
if (func_type->result_count == 0) {
invokeNative_Void(argv1, argc1, func_ptr);
}
else {
switch (func_type->types[func_type->param_count]) {
case VALUE_TYPE_I32:
ret[0] = invokeNative_Int32(argv1, argc1, func_ptr);
break;
case VALUE_TYPE_I64:
PUT_I64_TO_ADDR(ret, invokeNative_Int64(argv1, argc1, func_ptr));
break;
case VALUE_TYPE_F32:
*(float32*)ret = invokeNative_Float32(argv1, argc1, func_ptr);
break;
case VALUE_TYPE_F64:
PUT_F64_TO_ADDR(ret, invokeNative_Float64(argv1, argc1, func_ptr));
break;
}
}
if (argv1 != argv_buf)
wasm_free(argv1);
return true;
}
#else /* else of !defined(__x86_64__) && !defined(__amd_64__) */
typedef void (*GenericFunctionPointer)();
int64 invokeNative(uint64 *args, uint64 n_fps, uint64 n_stacks, GenericFunctionPointer f);
typedef float64 (*Float64FuncPtr)(uint64*, uint64, uint64, GenericFunctionPointer);
typedef float32 (*Float32FuncPtr)(uint64*, uint64, uint64, GenericFunctionPointer);
typedef int64 (*Int64FuncPtr)(uint64*,uint64, uint64, GenericFunctionPointer);
typedef int32 (*Int32FuncPtr)(uint64*, uint64, uint64, GenericFunctionPointer);
typedef void (*VoidFuncPtr)(uint64*, uint64, uint64, GenericFunctionPointer);
static Float64FuncPtr invokeNative_Float64 = (Float64FuncPtr)invokeNative;
static Float32FuncPtr invokeNative_Float32 = (Float32FuncPtr)invokeNative;
static Int64FuncPtr invokeNative_Int64 = (Int64FuncPtr)invokeNative;
static Int32FuncPtr invokeNative_Int32 = (Int32FuncPtr)invokeNative;
static VoidFuncPtr invokeNative_Void = (VoidFuncPtr)invokeNative;
#if defined(_WIN32) || defined(_WIN32_)
#define MAX_REG_FLOATS 4
#define MAX_REG_INTS 4
#else
#define MAX_REG_FLOATS 8
#define MAX_REG_INTS 6
#endif
bool
wasm_runtime_invoke_native(void *func_ptr, WASMType *func_type,
WASMModuleInstance *module_inst,
uint32 *argv, uint32 argc, uint32 *ret)
{
uint64 argv_buf[32], *argv1 = argv_buf, *fps, *ints, *stacks, size;
uint32 *argv_src = argv, i, j, argc1, n_ints = 0, n_stacks = 0;
#if defined(_WIN32) || defined(_WIN32_)
/* important difference in calling conventions */
#define n_fps n_ints
#else
int n_fps = 0;
#endif
argc1 = 1 + MAX_REG_FLOATS + func_type->param_count + 2;
if (argc1 > sizeof(argv_buf) / sizeof(uint64)) {
size = sizeof(uint64) * argc1;
if (size >= UINT32_MAX
|| !(argv1 = wasm_malloc(size))) {
wasm_runtime_set_exception(module_inst, "allocate memory failed.");
return false;
}
}
fps = argv1 + 1;
ints = fps + MAX_REG_FLOATS;
stacks = ints + MAX_REG_INTS;
ints[n_ints++] = (uint64)(uintptr_t)module_inst;
for (i = 0; i < func_type->param_count; i++) {
switch (func_type->types[i]) {
case VALUE_TYPE_I32:
if (n_ints < MAX_REG_INTS)
ints[n_ints++] = *argv_src++;
else
stacks[n_stacks++] = *argv_src++;
break;
case VALUE_TYPE_I64:
for (j = 0; j < 2; j++) {
if (n_ints < MAX_REG_INTS)
ints[n_ints++] = *argv_src++;
else
stacks[n_stacks++] = *argv_src++;
}
break;
case VALUE_TYPE_F32:
if (n_fps < MAX_REG_FLOATS)
*(float64*)&fps[n_fps++] = *(float32*)argv_src++;
else
*(float64*)&stacks[n_stacks++] = *(float32*)argv_src++;
break;
case VALUE_TYPE_F64:
if (n_fps < MAX_REG_FLOATS)
*(float64*)&fps[n_fps++] = *(float64*)argv_src;
else
*(float64*)&stacks[n_stacks++] = *(float64*)argv_src;
argv_src += 2;
break;
default:
wasm_assert(0);
break;
}
}
if (func_type->result_count == 0) {
invokeNative_Void(argv1, n_fps, n_stacks, func_ptr);
}
else {
switch (func_type->types[func_type->param_count]) {
case VALUE_TYPE_I32:
ret[0] = invokeNative_Int32(argv1, n_fps, n_stacks, func_ptr);
break;
case VALUE_TYPE_I64:
PUT_I64_TO_ADDR(ret, invokeNative_Int64(argv1, n_fps, n_stacks, func_ptr));
break;
case VALUE_TYPE_F32:
*(float32*)ret = invokeNative_Float32(argv1, n_fps, n_stacks, func_ptr);
break;
case VALUE_TYPE_F64:
PUT_F64_TO_ADDR(ret, invokeNative_Float64(argv1, n_fps, n_stacks, func_ptr));
break;
default:
wasm_assert(0);
break;
}
}
if (argv1 != argv_buf)
wasm_free(argv1);
return true;
}
#endif /* end of !defined(__x86_64__) && !defined(__amd_64__) */

View File

@ -315,6 +315,11 @@ int32
wasm_runtime_addr_native_to_app(WASMModuleInstance *module_inst,
void *native_ptr);
bool
wasm_runtime_invoke_native(void *func_ptr, WASMType *func_type,
WASMModuleInstance *module_inst,
uint32 *argv, uint32 argc, uint32 *ret);
#ifdef __cplusplus
}
#endif