wasm_application.c 21 KB

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