wasm-application.c 11 KB

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