wasm_application.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include "bh_platform.h"
  6. #if WASM_ENABLE_INTERP != 0
  7. #include "../interpreter/wasm_runtime.h"
  8. #endif
  9. #if WASM_ENABLE_AOT != 0
  10. #include "../aot/aot_runtime.h"
  11. #endif
  12. static void
  13. set_error_buf(char *error_buf, uint32 error_buf_size, const char *string)
  14. {
  15. if (error_buf != NULL)
  16. snprintf(error_buf, error_buf_size, "%s", string);
  17. }
  18. static void *
  19. runtime_malloc(uint64 size, WASMModuleInstanceCommon *module_inst,
  20. char *error_buf, uint32 error_buf_size)
  21. {
  22. void *mem;
  23. if (size >= UINT32_MAX || !(mem = wasm_runtime_malloc((uint32)size))) {
  24. if (module_inst != NULL) {
  25. wasm_runtime_set_exception(module_inst, "allocate memory failed");
  26. }
  27. else if (error_buf != NULL) {
  28. set_error_buf(error_buf, error_buf_size, "allocate memory failed");
  29. }
  30. return NULL;
  31. }
  32. memset(mem, 0, (uint32)size);
  33. return mem;
  34. }
  35. static union {
  36. int a;
  37. char b;
  38. } __ue = { .a = 1 };
  39. #define is_little_endian() (__ue.b == 1)
  40. /**
  41. * Implementation of wasm_application_execute_main()
  42. */
  43. static WASMFunctionInstanceCommon *
  44. resolve_function(const WASMModuleInstanceCommon *module_inst, const char *name);
  45. static bool
  46. check_main_func_type(const WASMType *type)
  47. {
  48. if (!(type->param_count == 0 || type->param_count == 2)
  49. || type->result_count > 1) {
  50. LOG_ERROR(
  51. "WASM execute application failed: invalid main function type.\n");
  52. return false;
  53. }
  54. if (type->param_count == 2
  55. && !(type->types[0] == VALUE_TYPE_I32
  56. && type->types[1] == VALUE_TYPE_I32)) {
  57. LOG_ERROR(
  58. "WASM execute application failed: invalid main function type.\n");
  59. return false;
  60. }
  61. if (type->result_count
  62. && type->types[type->param_count] != VALUE_TYPE_I32) {
  63. LOG_ERROR(
  64. "WASM execute application failed: invalid main function type.\n");
  65. return false;
  66. }
  67. return true;
  68. }
  69. bool
  70. wasm_application_execute_main(WASMModuleInstanceCommon *module_inst, int32 argc,
  71. char *argv[])
  72. {
  73. WASMFunctionInstanceCommon *func;
  74. WASMType *func_type = NULL;
  75. uint32 argc1 = 0, argv1[2] = { 0 };
  76. uint32 total_argv_size = 0;
  77. uint64 total_size;
  78. uint32 argv_buf_offset = 0;
  79. int32 i;
  80. char *argv_buf, *p, *p_end;
  81. uint32 *argv_offsets, module_type;
  82. bool ret, is_import_func = true;
  83. #if WASM_ENABLE_LIBC_WASI != 0
  84. if (wasm_runtime_is_wasi_mode(module_inst)) {
  85. /* In wasi mode, we should call function named "_start"
  86. which initializes the wasi envrionment and then calls
  87. the actual main function. Directly call main function
  88. may cause exception thrown. */
  89. if ((func = wasm_runtime_lookup_wasi_start_function(module_inst)))
  90. return wasm_runtime_create_exec_env_and_call_wasm(module_inst, func,
  91. 0, NULL);
  92. /* If no start function was found, we execute
  93. the main function as normal */
  94. }
  95. #endif /* end of WASM_ENABLE_LIBC_WASI */
  96. if (!(func = resolve_function(module_inst, "main"))
  97. && !(func = resolve_function(module_inst, "__main_argc_argv"))
  98. && !(func = resolve_function(module_inst, "_main"))) {
  99. wasm_runtime_set_exception(module_inst, "lookup main function failed");
  100. return false;
  101. }
  102. #if WASM_ENABLE_INTERP != 0
  103. if (module_inst->module_type == Wasm_Module_Bytecode) {
  104. is_import_func = ((WASMFunctionInstance *)func)->is_import_func;
  105. }
  106. #endif
  107. #if WASM_ENABLE_AOT != 0
  108. if (module_inst->module_type == Wasm_Module_AoT) {
  109. is_import_func = ((AOTFunctionInstance *)func)->is_import_func;
  110. }
  111. #endif
  112. if (is_import_func) {
  113. wasm_runtime_set_exception(module_inst, "lookup main function failed");
  114. return false;
  115. }
  116. module_type = module_inst->module_type;
  117. func_type = wasm_runtime_get_function_type(func, module_type);
  118. if (!func_type) {
  119. LOG_ERROR("invalid module instance type");
  120. return false;
  121. }
  122. if (!check_main_func_type(func_type)) {
  123. wasm_runtime_set_exception(module_inst,
  124. "invalid function type of main function");
  125. return false;
  126. }
  127. if (func_type->param_count) {
  128. for (i = 0; i < argc; i++)
  129. total_argv_size += (uint32)(strlen(argv[i]) + 1);
  130. total_argv_size = align_uint(total_argv_size, 4);
  131. total_size = (uint64)total_argv_size + sizeof(int32) * (uint64)argc;
  132. if (total_size >= UINT32_MAX
  133. || !(argv_buf_offset = wasm_runtime_module_malloc(
  134. module_inst, (uint32)total_size, (void **)&argv_buf))) {
  135. wasm_runtime_set_exception(module_inst, "allocate memory failed");
  136. return false;
  137. }
  138. p = argv_buf;
  139. argv_offsets = (uint32 *)(p + total_argv_size);
  140. p_end = p + total_size;
  141. for (i = 0; i < argc; i++) {
  142. bh_memcpy_s(p, (uint32)(p_end - p), argv[i],
  143. (uint32)(strlen(argv[i]) + 1));
  144. argv_offsets[i] = argv_buf_offset + (uint32)(p - argv_buf);
  145. p += strlen(argv[i]) + 1;
  146. }
  147. argc1 = 2;
  148. argv1[0] = (uint32)argc;
  149. argv1[1] =
  150. (uint32)wasm_runtime_addr_native_to_app(module_inst, argv_offsets);
  151. }
  152. ret = wasm_runtime_create_exec_env_and_call_wasm(module_inst, func, argc1,
  153. argv1);
  154. if (ret && func_type->result_count > 0 && argc > 0 && argv)
  155. /* copy the return value */
  156. *(int *)argv = (int)argv1[0];
  157. if (argv_buf_offset)
  158. wasm_runtime_module_free(module_inst, argv_buf_offset);
  159. return ret;
  160. }
  161. #if WASM_ENABLE_MULTI_MODULE != 0
  162. static WASMModuleInstance *
  163. get_sub_module_inst(const WASMModuleInstance *parent_module_inst,
  164. const char *sub_module_name)
  165. {
  166. WASMSubModInstNode *node =
  167. bh_list_first_elem(parent_module_inst->sub_module_inst_list);
  168. while (node && strcmp(node->module_name, sub_module_name)) {
  169. node = bh_list_elem_next(node);
  170. }
  171. return node ? node->module_inst : NULL;
  172. }
  173. static bool
  174. parse_function_name(char *orig_function_name, char **p_module_name,
  175. char **p_function_name)
  176. {
  177. if (orig_function_name[0] != '$') {
  178. *p_module_name = NULL;
  179. *p_function_name = orig_function_name;
  180. return true;
  181. }
  182. /**
  183. * $module_name$function_name\0
  184. * ===>
  185. * module_name\0function_name\0
  186. * ===>
  187. * module_name
  188. * function_name
  189. */
  190. char *p1 = orig_function_name;
  191. char *p2 = strchr(p1 + 1, '$');
  192. if (!p2) {
  193. LOG_DEBUG("can not parse the incoming function name");
  194. return false;
  195. }
  196. *p_module_name = p1 + 1;
  197. *p2 = '\0';
  198. *p_function_name = p2 + 1;
  199. return strlen(*p_module_name) && strlen(*p_function_name);
  200. }
  201. #endif
  202. /**
  203. * Implementation of wasm_application_execute_func()
  204. */
  205. static WASMFunctionInstanceCommon *
  206. resolve_function(const WASMModuleInstanceCommon *module_inst, const char *name)
  207. {
  208. uint32 i = 0;
  209. WASMFunctionInstanceCommon *ret = NULL;
  210. #if WASM_ENABLE_MULTI_MODULE != 0
  211. WASMModuleInstance *sub_module_inst = NULL;
  212. char *orig_name = NULL;
  213. char *sub_module_name = NULL;
  214. char *function_name = NULL;
  215. uint32 length = (uint32)(strlen(name) + 1);
  216. orig_name = runtime_malloc(sizeof(char) * length, NULL, NULL, 0);
  217. if (!orig_name) {
  218. return NULL;
  219. }
  220. strncpy(orig_name, name, length);
  221. if (!parse_function_name(orig_name, &sub_module_name, &function_name)) {
  222. goto LEAVE;
  223. }
  224. LOG_DEBUG("%s -> %s and %s", name, sub_module_name, function_name);
  225. if (sub_module_name) {
  226. sub_module_inst = get_sub_module_inst((WASMModuleInstance *)module_inst,
  227. sub_module_name);
  228. if (!sub_module_inst) {
  229. LOG_DEBUG("can not find a sub module named %s", sub_module_name);
  230. goto LEAVE;
  231. }
  232. }
  233. #else
  234. const char *function_name = name;
  235. #endif
  236. #if WASM_ENABLE_INTERP != 0
  237. if (module_inst->module_type == Wasm_Module_Bytecode) {
  238. WASMModuleInstance *wasm_inst = (WASMModuleInstance *)module_inst;
  239. #if WASM_ENABLE_MULTI_MODULE != 0
  240. wasm_inst = sub_module_inst ? sub_module_inst : wasm_inst;
  241. #endif /* WASM_ENABLE_MULTI_MODULE */
  242. for (i = 0; i < wasm_inst->export_func_count; i++) {
  243. if (!strcmp(wasm_inst->export_functions[i].name, function_name)) {
  244. ret = wasm_inst->export_functions[i].function;
  245. break;
  246. }
  247. }
  248. }
  249. #endif /* WASM_ENABLE_INTERP */
  250. #if WASM_ENABLE_AOT != 0
  251. if (module_inst->module_type == Wasm_Module_AoT) {
  252. AOTModuleInstance *aot_inst = (AOTModuleInstance *)module_inst;
  253. AOTFunctionInstance *export_funcs =
  254. (AOTFunctionInstance *)aot_inst->export_funcs.ptr;
  255. for (i = 0; i < aot_inst->export_func_count; i++) {
  256. if (!strcmp(export_funcs[i].func_name, function_name)) {
  257. ret = &export_funcs[i];
  258. break;
  259. }
  260. }
  261. }
  262. #endif
  263. #if WASM_ENABLE_MULTI_MODULE != 0
  264. LEAVE:
  265. wasm_runtime_free(orig_name);
  266. #endif
  267. return ret;
  268. }
  269. union ieee754_float {
  270. float f;
  271. /* This is the IEEE 754 single-precision format. */
  272. union {
  273. struct {
  274. unsigned int negative : 1;
  275. unsigned int exponent : 8;
  276. unsigned int mantissa : 23;
  277. } ieee_big_endian;
  278. struct {
  279. unsigned int mantissa : 23;
  280. unsigned int exponent : 8;
  281. unsigned int negative : 1;
  282. } ieee_little_endian;
  283. } ieee;
  284. };
  285. union ieee754_double {
  286. double d;
  287. /* This is the IEEE 754 double-precision format. */
  288. union {
  289. struct {
  290. unsigned int negative : 1;
  291. unsigned int exponent : 11;
  292. /* Together these comprise the mantissa. */
  293. unsigned int mantissa0 : 20;
  294. unsigned int mantissa1 : 32;
  295. } ieee_big_endian;
  296. struct {
  297. /* Together these comprise the mantissa. */
  298. unsigned int mantissa1 : 32;
  299. unsigned int mantissa0 : 20;
  300. unsigned int exponent : 11;
  301. unsigned int negative : 1;
  302. } ieee_little_endian;
  303. } ieee;
  304. };
  305. bool
  306. wasm_application_execute_func(WASMModuleInstanceCommon *module_inst,
  307. const char *name, int32 argc, char *argv[])
  308. {
  309. WASMFunctionInstanceCommon *func;
  310. WASMType *type = NULL;
  311. uint32 argc1, *argv1 = NULL, cell_num = 0, j, k = 0;
  312. int32 i, p, module_type;
  313. uint64 total_size;
  314. const char *exception;
  315. char buf[128];
  316. bh_assert(argc >= 0);
  317. LOG_DEBUG("call a function \"%s\" with %d arguments", name, argc);
  318. func = resolve_function(module_inst, name);
  319. if (!func) {
  320. snprintf(buf, sizeof(buf), "lookup function %s failed", name);
  321. wasm_runtime_set_exception(module_inst, buf);
  322. goto fail;
  323. }
  324. #if WASM_ENABLE_INTERP != 0
  325. if (module_inst->module_type == Wasm_Module_Bytecode) {
  326. WASMFunctionInstance *wasm_func = (WASMFunctionInstance *)func;
  327. if (wasm_func->is_import_func
  328. #if WASM_ENABLE_MULTI_MODULE != 0
  329. && !wasm_func->import_func_inst
  330. #endif
  331. ) {
  332. snprintf(buf, sizeof(buf), "lookup function %s failed", name);
  333. wasm_runtime_set_exception(module_inst, buf);
  334. goto fail;
  335. }
  336. }
  337. #endif
  338. module_type = module_inst->module_type;
  339. type = wasm_runtime_get_function_type(func, module_type);
  340. if (!type) {
  341. LOG_ERROR("invalid module instance type");
  342. return false;
  343. }
  344. if (type->param_count != (uint32)argc) {
  345. wasm_runtime_set_exception(module_inst, "invalid input argument count");
  346. goto fail;
  347. }
  348. argc1 = type->param_cell_num;
  349. cell_num = (argc1 > type->ret_cell_num) ? argc1 : type->ret_cell_num;
  350. total_size = sizeof(uint32) * (uint64)(cell_num > 2 ? cell_num : 2);
  351. if ((!(argv1 = runtime_malloc((uint32)total_size, module_inst, NULL, 0)))) {
  352. goto fail;
  353. }
  354. /* Parse arguments */
  355. for (i = 0, p = 0; i < argc; i++) {
  356. char *endptr = NULL;
  357. bh_assert(argv[i] != NULL);
  358. if (argv[i][0] == '\0') {
  359. snprintf(buf, sizeof(buf), "invalid input argument %" PRId32, i);
  360. wasm_runtime_set_exception(module_inst, buf);
  361. goto fail;
  362. }
  363. switch (type->types[i]) {
  364. case VALUE_TYPE_I32:
  365. argv1[p++] = (uint32)strtoul(argv[i], &endptr, 0);
  366. break;
  367. case VALUE_TYPE_I64:
  368. {
  369. union {
  370. uint64 val;
  371. uint32 parts[2];
  372. } u;
  373. u.val = strtoull(argv[i], &endptr, 0);
  374. argv1[p++] = u.parts[0];
  375. argv1[p++] = u.parts[1];
  376. break;
  377. }
  378. case VALUE_TYPE_F32:
  379. {
  380. float32 f32 = strtof(argv[i], &endptr);
  381. if (isnan(f32)) {
  382. if (argv[i][0] == '-') {
  383. union ieee754_float u;
  384. u.f = f32;
  385. if (is_little_endian())
  386. u.ieee.ieee_little_endian.negative = 1;
  387. else
  388. u.ieee.ieee_big_endian.negative = 1;
  389. memcpy(&f32, &u.f, sizeof(float));
  390. }
  391. if (endptr[0] == ':') {
  392. uint32 sig;
  393. union ieee754_float u;
  394. sig = (uint32)strtoul(endptr + 1, &endptr, 0);
  395. u.f = f32;
  396. if (is_little_endian())
  397. u.ieee.ieee_little_endian.mantissa = sig;
  398. else
  399. u.ieee.ieee_big_endian.mantissa = sig;
  400. memcpy(&f32, &u.f, sizeof(float));
  401. }
  402. }
  403. memcpy(&argv1[p++], &f32, sizeof(float));
  404. break;
  405. }
  406. case VALUE_TYPE_F64:
  407. {
  408. union {
  409. float64 val;
  410. uint32 parts[2];
  411. } u;
  412. u.val = strtod(argv[i], &endptr);
  413. if (isnan(u.val)) {
  414. if (argv[i][0] == '-') {
  415. union ieee754_double ud;
  416. ud.d = u.val;
  417. if (is_little_endian())
  418. ud.ieee.ieee_little_endian.negative = 1;
  419. else
  420. ud.ieee.ieee_big_endian.negative = 1;
  421. memcpy(&u.val, &ud.d, sizeof(double));
  422. }
  423. if (endptr[0] == ':') {
  424. uint64 sig;
  425. union ieee754_double ud;
  426. sig = strtoull(endptr + 1, &endptr, 0);
  427. ud.d = u.val;
  428. if (is_little_endian()) {
  429. ud.ieee.ieee_little_endian.mantissa0 = sig >> 32;
  430. ud.ieee.ieee_little_endian.mantissa1 = (uint32)sig;
  431. }
  432. else {
  433. ud.ieee.ieee_big_endian.mantissa0 = sig >> 32;
  434. ud.ieee.ieee_big_endian.mantissa1 = (uint32)sig;
  435. }
  436. memcpy(&u.val, &ud.d, sizeof(double));
  437. }
  438. }
  439. argv1[p++] = u.parts[0];
  440. argv1[p++] = u.parts[1];
  441. break;
  442. }
  443. #if WASM_ENABLE_SIMD != 0
  444. case VALUE_TYPE_V128:
  445. {
  446. /* it likes 0x123\0x234 or 123\234 */
  447. /* retrive first i64 */
  448. *(uint64 *)(argv1 + p) = strtoull(argv[i], &endptr, 0);
  449. /* skip \ */
  450. endptr++;
  451. /* retrive second i64 */
  452. *(uint64 *)(argv1 + p + 2) = strtoull(endptr, &endptr, 0);
  453. p += 4;
  454. break;
  455. }
  456. #endif /* WASM_ENABLE_SIMD != 0 */
  457. #if WASM_ENABLE_REF_TYPES != 0
  458. case VALUE_TYPE_FUNCREF:
  459. {
  460. if (strncmp(argv[i], "null", 4) == 0
  461. || strncmp(argv[i], "NULL", 4) == 0) {
  462. argv1[p++] = NULL_REF;
  463. }
  464. else {
  465. argv1[p++] = (uint32)strtoul(argv[i], &endptr, 0);
  466. }
  467. break;
  468. }
  469. case VALUE_TYPE_EXTERNREF:
  470. {
  471. if (strncmp(argv[i], "null", 4) == 0
  472. || strncmp(argv[i], "NULL", 4) == 0) {
  473. argv1[p++] = NULL_REF;
  474. }
  475. else {
  476. uint64 val = strtoull(argv[i], &endptr, 0);
  477. void *extern_obj = (void *)(uintptr_t)val;
  478. uint32 externref_idx;
  479. if (!wasm_externref_obj2ref(module_inst, extern_obj,
  480. &externref_idx)) {
  481. wasm_runtime_set_exception(
  482. module_inst, "map extern object to ref failed");
  483. goto fail;
  484. }
  485. argv1[p++] = externref_idx;
  486. }
  487. break;
  488. }
  489. #endif /* WASM_ENABLE_REF_TYPES */
  490. default:
  491. bh_assert(0);
  492. break;
  493. }
  494. if (endptr && *endptr != '\0' && *endptr != '_') {
  495. snprintf(buf, sizeof(buf), "invalid input argument %" PRId32 ": %s",
  496. i, argv[i]);
  497. wasm_runtime_set_exception(module_inst, buf);
  498. goto fail;
  499. }
  500. }
  501. bh_assert(p == (int32)argc1);
  502. wasm_runtime_set_exception(module_inst, NULL);
  503. if (!wasm_runtime_create_exec_env_and_call_wasm(module_inst, func, argc1,
  504. argv1)) {
  505. goto fail;
  506. }
  507. /* print return value */
  508. for (j = 0; j < type->result_count; j++) {
  509. switch (type->types[type->param_count + j]) {
  510. case VALUE_TYPE_I32:
  511. {
  512. os_printf("0x%" PRIx32 ":i32", argv1[k]);
  513. k++;
  514. break;
  515. }
  516. case VALUE_TYPE_I64:
  517. {
  518. union {
  519. uint64 val;
  520. uint32 parts[2];
  521. } u;
  522. u.parts[0] = argv1[k];
  523. u.parts[1] = argv1[k + 1];
  524. k += 2;
  525. #ifdef PRIx64
  526. os_printf("0x%" PRIx64 ":i64", u.val);
  527. #else
  528. char buf[16];
  529. if (sizeof(long) == 4)
  530. snprintf(buf, sizeof(buf), "%s", "0x%llx:i64");
  531. else
  532. snprintf(buf, sizeof(buf), "%s", "0x%lx:i64");
  533. os_printf(buf, u.val);
  534. #endif
  535. break;
  536. }
  537. case VALUE_TYPE_F32:
  538. {
  539. os_printf("%.7g:f32", *(float32 *)(argv1 + k));
  540. k++;
  541. break;
  542. }
  543. case VALUE_TYPE_F64:
  544. {
  545. union {
  546. float64 val;
  547. uint32 parts[2];
  548. } u;
  549. u.parts[0] = argv1[k];
  550. u.parts[1] = argv1[k + 1];
  551. k += 2;
  552. os_printf("%.7g:f64", u.val);
  553. break;
  554. }
  555. #if WASM_ENABLE_REF_TYPES
  556. case VALUE_TYPE_FUNCREF:
  557. {
  558. if (argv1[k] != NULL_REF)
  559. os_printf("%u:ref.func", argv1[k]);
  560. else
  561. os_printf("func:ref.null");
  562. k++;
  563. break;
  564. }
  565. case VALUE_TYPE_EXTERNREF:
  566. {
  567. if (argv1[k] != NULL_REF) {
  568. void *extern_obj = NULL;
  569. bool ret = wasm_externref_ref2obj(argv1[k], &extern_obj);
  570. bh_assert(ret);
  571. (void)ret;
  572. os_printf("%p:ref.extern", extern_obj);
  573. }
  574. else
  575. os_printf("extern:ref.null");
  576. k++;
  577. break;
  578. }
  579. #endif
  580. #if WASM_ENABLE_SIMD != 0
  581. case VALUE_TYPE_V128:
  582. {
  583. uint64 *v = (uint64 *)(argv1 + k);
  584. #if defined(PRIx64)
  585. os_printf("<0x%016" PRIx64 " 0x%016" PRIx64 ">:v128", *v,
  586. *(v + 1));
  587. #else
  588. if (4 == sizeof(long)) {
  589. os_printf("<0x%016llx 0x%016llx>:v128", *v, *(v + 1));
  590. }
  591. else {
  592. os_printf("<0x%016lx 0x%016lx>:v128", *v, *(v + 1));
  593. }
  594. #endif /* PRIx64 */
  595. k += 4;
  596. break;
  597. }
  598. #endif /* WASM_ENABLE_SIMD != 0 */
  599. default:
  600. bh_assert(0);
  601. break;
  602. }
  603. if (j < (uint32)(type->result_count - 1))
  604. os_printf(",");
  605. }
  606. os_printf("\n");
  607. wasm_runtime_free(argv1);
  608. return true;
  609. fail:
  610. if (argv1)
  611. wasm_runtime_free(argv1);
  612. exception = wasm_runtime_get_exception(module_inst);
  613. bh_assert(exception);
  614. os_printf("%s\n", exception);
  615. return false;
  616. }