wasm-micro-runtime
wasm-micro-runtime copied to clipboard
REG_NATIVE_FUN strtod() renturn error
HI: When use REG_NATIVE_FUN register function return type the double, I canot get the return value.
My register code:
REG_NATIVE_FUNC(strtod, "($*)F")
static float64
strtod_wrapper(wasm_exec_env_t exec_env,
const char *nptr, char **endptr)
{
wasm_module_inst_t module_inst = get_module_inst(exec_env);
float64 num = 0;
/* nptr has been checked by runtime */
if (!validate_native_addr(endptr, sizeof(uint32)))
return 0;
num = (float64)strtol(nptr, endptr);
*(uint32*)endptr = addr_native_to_app(*endptr);
printf("num value = %f",num);
return num;
}
The very simple funcation:
char* number_c_string = "10.23";
char* agter_end = NULL;
double number = 0;
number = strtod((const char*)number_c_string, (char**)&after_end);
printf("strtod number=%f",number);
And the output:
num value = 10.23
strtod number=0.0
Thanks!
@crl7885 could you provide more details, which platform and target do you use? e.g. Linux or Windows, x86_64 or ARM? And Which mode is the runtime running on, interpreter or AOT? Thanks.
@crl7885 could you provide more details, which platform and target do you use? e.g. Linux or Windows, x86_64 or ARM? And Which mode is the runtime running on, interpreter or AOT? Thanks.
The platform is ARM64,mode is interpreter。
@crl7885 Do you enable SIMD mode (cmake -DWAMR_BUILD_SIMD=1/0) or not, and which asm file do you use, invokeNative_aarch64.s or invokeNative_aarch64_simd.s? As far as I know, the float/double return register in AARCH64 is d0, could you please debug and step into the invokeNative asm code, check the value of d0 after calling beq call_func to call the native function?
/* Directly call the fucntion if no args in stack */
cmp x21, #0
beq call_func
/* Fill all stack args: reserve stack space and fill one by one */
mov x23, sp
@crl7885 Do you enable SIMD mode (cmake -DWAMR_BUILD_SIMD=1/0) or not, and which asm file do you use, invokeNative_aarch64.s or invokeNative_aarch64_simd.s? As far as I know, the float/double return register in AARCH64 is d0, could you please debug and step into the invokeNative asm code, check the value of d0 after calling
beq call_functo call the native function?/* Directly call the fucntion if no args in stack */ cmp x21, #0 beq call_func /* Fill all stack args: reserve stack space and fill one by one */ mov x23, sp
sorry,Can I ask questions in Chinese?
Yes, and could you use objdump to dump the assembly code of strtod_wrapper? Had better remove printf in it.
@wenyongh 你好,最下边是strtod_wrapper的arm64反汇编。 我做过一个测试,在core/iwasm/common/wasm_runtime_common.c的wasm_runtime_invoke_native()函数中,强制使用core/iwasm/common/arch/invokeNative_general.c来执行native register的strtod函数。 在invokeNative()中打印strtod_wrapper函数的返回值是正确的。
void invokeNative(void (*native_code)(), uint32 argv[], uint32 argc)
{
switch(argc) {
......
case 3:{
FUNC_PTR_DOUBLE func = (FUNC_PTR_DOUBLE)native_code;
double rtv = func(argv[0], argv[1], argv[2]);
//这里rtv是正确的
// native_code(argv[0], argv[1], argv[2]);
break;
}
......
}
但是在wasm_runtime_invoke_native函数中打印返回值是错误的
bool
wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
const WASMType *func_type, const char *signature,
void *attachment,
uint32 *argv, uint32 argc, uint32 *argv_ret)
{
。。。。。。
else {
switch (func_type->types[func_type->param_count]) {
。。。。。。
case VALUE_TYPE_F64:
float64 rtv = invokeNative_Float64(func_ptr, argv1, n_stacks);
//这里rtv是错误的0.0
PUT_F64_TO_ADDR(argv_ret, rtv);
break;
default:
bh_assert(0);
break;
}
}
。。。。。。
return ret;
}
Disassembly of section .text.strtod_wrapper:
00000000 strtod_wrapper:
; {
0: f0 48 2d e9 push {r4, r5, r6, r7, r11, lr}
4: 10 b0 8d e2 add r11, sp, #16
8: 02 40 a0 e1 mov r4, r2
c: 01 60 a0 e1 mov r6, r1
; wasm_module_inst_t module_inst = get_module_inst(exec_env);
10: fe ff ff eb bl #-8 <strtod_wrapper+0x10>
; if (!validate_native_addr(endptr, sizeof(uint32)))
14: 04 10 a0 e1 mov r1, r4
18: 04 20 a0 e3 mov r2, #4
; wasm_module_inst_t module_inst = get_module_inst(exec_env);
1c: 00 50 a0 e1 mov r5, r0
; if (!validate_native_addr(endptr, sizeof(uint32)))
20: fe ff ff eb bl #-8 <strtod_wrapper+0x20>
24: 00 00 50 e3 cmp r0, #0
28: 0b 00 00 0a beq #44 <strtod_wrapper+0x5c>
; num = (float64)strtod(nptr, endptr);
2c: 06 00 a0 e1 mov r0, r6
30: 04 10 a0 e1 mov r1, r4
34: fe ff ff eb bl #-8 <strtod_wrapper+0x34>
38: 01 70 a0 e1 mov r7, r1
; *(uint32*)endptr = addr_native_to_app(*endptr);
3c: 00 10 94 e5 ldr r1, [r4]
; num = (float64)strtod(nptr, endptr);
40: 00 60 a0 e1 mov r6, r0
; *(uint32*)endptr = addr_native_to_app(*endptr);
44: 05 00 a0 e1 mov r0, r5
48: fe ff ff eb bl #-8 <strtod_wrapper+0x48>
4c: 00 00 84 e5 str r0, [r4]
; }
50: 06 00 a0 e1 mov r0, r6
54: 07 10 a0 e1 mov r1, r7
58: f0 88 bd e8 pop {r4, r5, r6, r7, r11, pc}
5c: 10 00 c0 f2 vmov.i32 d16, #0x0
60: 30 0b 51 ec vmov r0, r1, d16
64: f0 88 bd e8 pop {r4, r5, r6, r7, r11, pc}
Hi, from the objdump result of strtod_wrapper, the return value of float64 type should be passed back to caller with register r0, r1 (or d16), but not d0. Currently runtime only supports AARCH64 ABI with float/double registers enabled, so could you please check whether your hardware supports the float/double register d0 to d15 or not? If yes, could you please check whether you can set the compiler flag to enable them, e.g. -mabi=xxx? If not, could you please register the native API with raw mode with API wasm_runtime_register_natives_raw, ref to: https://github.com/bytecodealliance/wasm-micro-runtime/issues/220#issuecomment-607061112 and wasm_export.h#L768-L781 for more details, thanks.
@wenyongh 你好: 我使用了wasm的官方product-mini/app-samples,在mac平台下编译了字节码和wasm虚拟机,也有这个问题。 我把测试代码放到了我的github 你可以编译字节码测试一下看看详细情况。
虚拟机用的是/product-mini/platforms/darwin 使用默认的cmake文件进行编译。
product-mini/app-samples/hello-world/main.c的代码
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
const char* number_c_string = "8.5";
char* after_end = NULL;
double number = strtod((const char*)number_c_string, (char**)&after_end);
if(number == 8.5f){
printf("equality");
}else{
printf("not equality");
}
return 0;
}
product-mini/platforms/darwin/main.c中的修改
#define REG_NATIVE_FUNC(func_name, signature) \
{ #func_name, func_name##_wrapper, signature, NULL }
float64
strtod_wrapper(wasm_exec_env_t exec_env,
const char *nptr, char **endptr)
{
wasm_module_inst_t module_inst = get_module_inst(exec_env);
float64 num = 0;
/* nptr has been checked by runtime */
if (!wasm_runtime_validate_native_addr(module_inst,endptr, sizeof(uint32)))
return 0;
num = (float64)strtod(nptr, endptr);
*(uint32*)endptr = addr_native_to_app(*endptr);
return num;
}
static NativeSymbol native_symbols_libc_builtin[] = {
REG_NATIVE_FUNC(strtod, "($*)F")
};
int main(int argc, char *argv[])
{
......
uint32 n_native_symbols = sizeof(native_symbols_libc_builtin) / sizeof(NativeSymbol);
if(!wasm_runtime_register_natives("env",native_symbols_libc_builtin,n_native_symbols)){
printf("register failed");
goto fail1;
}
......
}
谢谢!
Hi, we had fixed the invokeNative asm issues for ARM, see #697, not sure whether it fixes you problem, could you please try again?