wasm-micro-runtime icon indicating copy to clipboard operation
wasm-micro-runtime copied to clipboard

REG_NATIVE_FUN strtod() renturn error

Open crl7885 opened this issue 4 years ago • 9 comments
trafficstars

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 avatar Jul 13 '21 11:07 crl7885

@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.

wenyongh avatar Jul 14 '21 05:07 wenyongh

@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 avatar Jul 14 '21 11:07 crl7885

@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

wenyongh avatar Jul 15 '21 02:07 wenyongh

@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

sorry,Can I ask questions in Chinese?

crl7885 avatar Jul 15 '21 03:07 crl7885

Yes, and could you use objdump to dump the assembly code of strtod_wrapper? Had better remove printf in it.

wenyongh avatar Jul 15 '21 06:07 wenyongh

@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}

crl7885 avatar Jul 15 '21 13:07 crl7885

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 avatar Jul 16 '21 02:07 wenyongh

@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;
    }
    ......
}

谢谢!

crl7885 avatar Jul 16 '21 06:07 crl7885

Hi, we had fixed the invokeNative asm issues for ARM, see #697, not sure whether it fixes you problem, could you please try again?

wenyongh avatar Nov 15 '21 07:11 wenyongh