wasm_application.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include <errno.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include "wasm.h"
  20. #include "wasm_application.h"
  21. #include "wasm_interp.h"
  22. #include "wasm_runtime.h"
  23. #include "wasm_thread.h"
  24. #include "wasm_assert.h"
  25. #include "wasm_log.h"
  26. #include "wasm_memory.h"
  27. #include "wasm_platform_log.h"
  28. static WASMFunctionInstance*
  29. resolve_main_function(const WASMModuleInstance *module_inst)
  30. {
  31. uint32 i;
  32. for (i = 0; i < module_inst->export_func_count; i++)
  33. if (!strcmp(module_inst->export_functions[i].name, "_main")
  34. || !strcmp(module_inst->export_functions[i].name, "main"))
  35. return module_inst->export_functions[i].function;
  36. LOG_ERROR("WASM execute application failed: main function not found.\n");
  37. return NULL;
  38. }
  39. static bool
  40. check_main_func_type(const WASMType *type)
  41. {
  42. if (!(type->param_count == 0 || type->param_count == 2)
  43. ||type->result_count > 1) {
  44. LOG_ERROR("WASM execute application failed: invalid main function type.\n");
  45. return false;
  46. }
  47. if (type->param_count == 2
  48. && !(type->types[0] == VALUE_TYPE_I32
  49. && type->types[1] == VALUE_TYPE_I32)) {
  50. LOG_ERROR("WASM execute application failed: invalid main function type.\n");
  51. return false;
  52. }
  53. if (type->result_count
  54. && type->types[type->param_count] != VALUE_TYPE_I32) {
  55. LOG_ERROR("WASM execute application failed: invalid main function type.\n");
  56. return false;
  57. }
  58. return true;
  59. }
  60. bool
  61. wasm_application_execute_main(WASMModuleInstance *module_inst,
  62. int argc, char *argv[])
  63. {
  64. WASMFunctionInstance *func = resolve_main_function(module_inst);
  65. uint32 argc1 = 0, argv1[2] = { 0 };
  66. uint32 total_argv_size = 0, total_size;
  67. int32 argv_buf_offset, i;
  68. char *argv_buf, *p;
  69. int32 *argv_offsets;
  70. if (!func || func->is_import_func)
  71. return false;
  72. if (!check_main_func_type(func->u.func->func_type))
  73. return false;
  74. if (func->u.func->func_type->param_count) {
  75. for (i = 0; i < argc; i++)
  76. total_argv_size += strlen(argv[i]) + 1;
  77. total_argv_size = align_uint(total_argv_size, 4);
  78. total_size = total_argv_size + sizeof(int32) * argc;
  79. if (!(argv_buf_offset = wasm_runtime_module_malloc(module_inst, total_size)))
  80. return false;
  81. argv_buf = p = wasm_runtime_addr_app_to_native(module_inst, argv_buf_offset);
  82. argv_offsets = (int32*)(p + total_argv_size);
  83. for (i = 0; i < argc; i++) {
  84. memcpy(p, argv[i], strlen(argv[i]) + 1);
  85. argv_offsets[i] = argv_buf_offset + (p - argv_buf);
  86. p += strlen(argv[i]) + 1;
  87. }
  88. argc1 = 2;
  89. argv1[0] = argc;
  90. argv1[1] = (uint32)wasm_runtime_addr_native_to_app(module_inst, argv_offsets);
  91. }
  92. return wasm_runtime_call_wasm(module_inst, NULL, func, argc1, argv1);
  93. }
  94. static WASMFunctionInstance*
  95. resolve_function(const WASMModuleInstance *module_inst, char *name)
  96. {
  97. uint32 i;
  98. for (i = 0; i < module_inst->export_func_count; i++)
  99. if (!strcmp(module_inst->export_functions[i].name, name))
  100. return module_inst->export_functions[i].function;
  101. return NULL;
  102. }
  103. union ieee754_float {
  104. float f;
  105. /* This is the IEEE 754 single-precision format. */
  106. union {
  107. struct {
  108. unsigned int negative:1;
  109. unsigned int exponent:8;
  110. unsigned int mantissa:23;
  111. } ieee_big_endian;
  112. struct {
  113. unsigned int mantissa:23;
  114. unsigned int exponent:8;
  115. unsigned int negative:1;
  116. } ieee_little_endian;
  117. } ieee;
  118. };
  119. union ieee754_double {
  120. double d;
  121. /* This is the IEEE 754 double-precision format. */
  122. union {
  123. struct {
  124. unsigned int negative:1;
  125. unsigned int exponent:11;
  126. /* Together these comprise the mantissa. */
  127. unsigned int mantissa0:20;
  128. unsigned int mantissa1:32;
  129. } ieee_big_endian;
  130. struct {
  131. /* Together these comprise the mantissa. */
  132. unsigned int mantissa1:32;
  133. unsigned int mantissa0:20;
  134. unsigned int exponent:11;
  135. unsigned int negative:1;
  136. } ieee_little_endian;
  137. } ieee;
  138. };
  139. static union {
  140. int a;
  141. char b;
  142. } __ue = { .a = 1 };
  143. #define is_little_endian() (__ue.b == 1)
  144. bool
  145. wasm_application_execute_func(WASMModuleInstance *module_inst,
  146. char *name, int argc, char *argv[])
  147. {
  148. WASMFunctionInstance *func;
  149. WASMType *type;
  150. uint32 argc1, *argv1;
  151. int32 i, p;
  152. const char *exception;
  153. wasm_assert(argc >= 0);
  154. func = resolve_function(module_inst, name);
  155. if (!func || func->is_import_func) {
  156. LOG_ERROR("Wasm lookup function %s failed.\n", name);
  157. return false;
  158. }
  159. type = func->u.func->func_type;
  160. if (type->param_count != (uint32)argc) {
  161. LOG_ERROR("Wasm prepare param failed: invalid param count.\n");
  162. return false;
  163. }
  164. argc1 = func->param_cell_num;
  165. argv1 = wasm_malloc(sizeof(uint32) * (argc1 > 2 ? argc1 : 2));
  166. if (argv1 == NULL) {
  167. LOG_ERROR("Wasm prepare param failed: malloc failed.\n");
  168. return false;
  169. }
  170. /* Parse arguments */
  171. for (i = 0, p = 0; i < argc; i++) {
  172. char *endptr;
  173. wasm_assert(argv[i] != NULL);
  174. if (argv[i][0] == '\0') {
  175. LOG_ERROR("Wasm prepare param failed: invalid num (%s).\n", argv[i]);
  176. goto fail;
  177. }
  178. switch (type->types[i]) {
  179. case VALUE_TYPE_I32:
  180. argv1[p++] = strtoul(argv[i], &endptr, 0);
  181. break;
  182. case VALUE_TYPE_I64:
  183. {
  184. union { uint64 val; uint32 parts[2]; } u;
  185. u.val = strtoull(argv[i], &endptr, 0);
  186. argv1[p++] = u.parts[0];
  187. argv1[p++] = u.parts[1];
  188. break;
  189. }
  190. case VALUE_TYPE_F32:
  191. {
  192. float32 f32 = strtof(argv[i], &endptr);
  193. if (isnan(f32)) {
  194. if (argv[i][0] == '-') {
  195. f32 = -f32;
  196. }
  197. if (endptr[0] == ':') {
  198. uint32 sig;
  199. union ieee754_float u;
  200. sig = strtoul(endptr + 1, &endptr, 0);
  201. u.f = f32;
  202. if (is_little_endian())
  203. u.ieee.ieee_little_endian.mantissa = sig;
  204. else
  205. u.ieee.ieee_big_endian.mantissa = sig;
  206. f32 = u.f;
  207. }
  208. }
  209. *(float32*)&argv1[p++] = f32;
  210. break;
  211. }
  212. case VALUE_TYPE_F64:
  213. {
  214. union { float64 val; uint32 parts[2]; } u;
  215. u.val = strtod(argv[i], &endptr);
  216. if (isnan(u.val)) {
  217. if (argv[i][0] == '-') {
  218. u.val = -u.val;
  219. }
  220. if (endptr[0] == ':') {
  221. uint64 sig;
  222. union ieee754_double ud;
  223. sig = strtoull(endptr + 1, &endptr, 0);
  224. ud.d = u.val;
  225. if (is_little_endian()) {
  226. ud.ieee.ieee_little_endian.mantissa0 = sig >> 32;
  227. ud.ieee.ieee_little_endian.mantissa1 = sig;
  228. }
  229. else {
  230. ud.ieee.ieee_big_endian.mantissa0 = sig >> 32;
  231. ud.ieee.ieee_big_endian.mantissa1 = sig;
  232. }
  233. u.val = ud.d;
  234. }
  235. }
  236. argv1[p++] = u.parts[0];
  237. argv1[p++] = u.parts[1];
  238. break;
  239. }
  240. }
  241. if (*endptr != '\0' && *endptr != '_') {
  242. LOG_ERROR("Wasm prepare param failed: invalid num (%s).\n", argv[i]);
  243. goto fail;
  244. }
  245. if (errno != 0) {
  246. LOG_ERROR("Wasm prepare param failed: errno %d.\n", errno);
  247. goto fail;
  248. }
  249. }
  250. wasm_assert(p == (int32)argc1);
  251. wasm_runtime_set_exception(module_inst, NULL);
  252. if (!wasm_runtime_call_wasm(module_inst, NULL, func, argc1, argv1)) {
  253. exception = wasm_runtime_get_exception(module_inst);
  254. wasm_printf("%s\n", exception);
  255. goto fail;
  256. }
  257. /* print return value */
  258. switch (type->types[type->param_count]) {
  259. case VALUE_TYPE_I32:
  260. wasm_printf("0x%x:i32", argv1[0]);
  261. break;
  262. case VALUE_TYPE_I64:
  263. {
  264. char buf[16];
  265. union { uint64 val; uint32 parts[2]; } u;
  266. u.parts[0] = argv1[0];
  267. u.parts[1] = argv1[1];
  268. if (sizeof(long) == 4)
  269. snprintf(buf, sizeof(buf), "%s", "0x%llx:i64");
  270. else
  271. snprintf(buf, sizeof(buf), "%s", "0x%lx:i64");
  272. wasm_printf(buf, u.val);
  273. break;
  274. }
  275. case VALUE_TYPE_F32:
  276. wasm_printf("%.7g:f32", *(float32*)argv1);
  277. break;
  278. case VALUE_TYPE_F64:
  279. {
  280. union { float64 val; uint32 parts[2]; } u;
  281. u.parts[0] = argv1[0];
  282. u.parts[1] = argv1[1];
  283. wasm_printf("%.7g:f64", u.val);
  284. break;
  285. }
  286. }
  287. wasm_printf("\n");
  288. wasm_free(argv1);
  289. return true;
  290. fail:
  291. wasm_free(argv1);
  292. return false;
  293. }
  294. static bool
  295. check_type(uint8 type, const char *p)
  296. {
  297. const char *str = "i32";
  298. if (strlen(p) < 3)
  299. return false;
  300. switch (type) {
  301. case VALUE_TYPE_I32:
  302. str = "i32";
  303. break;
  304. case VALUE_TYPE_I64:
  305. str = "i64";
  306. break;
  307. case VALUE_TYPE_F32:
  308. str = "f32";
  309. break;
  310. case VALUE_TYPE_F64:
  311. str = "f64";
  312. break;
  313. }
  314. if (strncmp(p, str, 3))
  315. return false;
  316. return true;
  317. }
  318. static bool
  319. check_function_type(const WASMType *type,
  320. const char *signature)
  321. {
  322. uint32 i;
  323. const char *p = signature;
  324. if (!p || *p++ != '(')
  325. return false;
  326. for (i = 0; i < type->param_count; i++) {
  327. if (!check_type(type->types[i], p))
  328. return false;
  329. p += 3;
  330. }
  331. if (*p++ != ')')
  332. return false;
  333. if (type->result_count) {
  334. if (!check_type(type->types[type->param_count], p))
  335. return false;
  336. p += 3;
  337. }
  338. if (*p != '\0')
  339. return false;
  340. return true;
  341. }
  342. WASMFunctionInstance*
  343. wasm_runtime_lookup_function(const WASMModuleInstance *module_inst,
  344. const char *name,
  345. const char *signature)
  346. {
  347. uint32 i;
  348. for (i = 0; i < module_inst->export_func_count; i++)
  349. if (!strcmp(module_inst->export_functions[i].name, name)
  350. && check_function_type(
  351. module_inst->export_functions[i].function->u.func->func_type,
  352. signature))
  353. return module_inst->export_functions[i].function;
  354. return NULL;
  355. }