aot.c 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include "aot.h"
  6. static char aot_error[128];
  7. char *
  8. aot_get_last_error()
  9. {
  10. return aot_error[0] == '\0' ? "" : aot_error;
  11. }
  12. void
  13. aot_set_last_error_v(const char *format, ...)
  14. {
  15. va_list args;
  16. va_start(args, format);
  17. vsnprintf(aot_error, sizeof(aot_error), format, args);
  18. va_end(args);
  19. }
  20. void
  21. aot_set_last_error(const char *error)
  22. {
  23. if (error)
  24. snprintf(aot_error, sizeof(aot_error), "Error: %s", error);
  25. else
  26. aot_error[0] = '\0';
  27. }
  28. static AOTImportMemory *
  29. aot_create_import_memories(const WASMModule *module, uint32 import_memory_count)
  30. {
  31. uint64 size;
  32. AOTImportMemory *import_memories;
  33. unsigned i;
  34. bh_assert(import_memory_count == module->import_memory_count);
  35. size = sizeof(AOTImportMemory) * (uint64)import_memory_count;
  36. if (size >= UINT32_MAX) {
  37. aot_set_last_error("too big allocate size");
  38. return NULL;
  39. }
  40. import_memories = wasm_runtime_malloc((uint32)size);
  41. if (!import_memories) {
  42. aot_set_last_error("allocate import memories failed.");
  43. return NULL;
  44. }
  45. memset(import_memories, 0, (uint32)size);
  46. for (i = 0; i < module->import_memory_count; i++) {
  47. AOTImportMemory *memory_aot = import_memories + i;
  48. WASMImport *memory_wasm = module->import_memories + i;
  49. memory_aot->module_name = memory_wasm->u.memory.module_name;
  50. memory_aot->memory_name = memory_wasm->u.memory.field_name;
  51. memory_aot->mem_type.flags = memory_wasm->u.memory.mem_type.flags;
  52. memory_aot->mem_type.init_page_count =
  53. memory_wasm->u.memory.mem_type.init_page_count;
  54. memory_aot->mem_type.max_page_count =
  55. memory_wasm->u.memory.mem_type.max_page_count;
  56. memory_aot->mem_type.num_bytes_per_page =
  57. memory_wasm->u.memory.mem_type.num_bytes_per_page;
  58. }
  59. return import_memories;
  60. }
  61. static AOTMemory *
  62. aot_create_memories(const WASMModule *module, uint32 memory_count)
  63. {
  64. uint64 size;
  65. AOTMemory *memories;
  66. unsigned i;
  67. size = (uint64)memory_count * sizeof(AOTMemory);
  68. if (size >= UINT32_MAX) {
  69. aot_set_last_error("too big allocate size");
  70. return NULL;
  71. }
  72. memories = wasm_runtime_malloc((uint32)size);
  73. if (!memories) {
  74. aot_set_last_error("create memories array failed.\n");
  75. return NULL;
  76. }
  77. memset(memories, 0, size);
  78. /* in reserved case, assign nothing */
  79. for (i = 0; i < module->memory_count; i++) {
  80. AOTMemory *memory_aot = memories + i;
  81. WASMMemory *memory_wasm = module->memories + i;
  82. memory_aot->flags = memory_wasm->flags;
  83. memory_aot->init_page_count = memory_wasm->init_page_count;
  84. memory_aot->max_page_count = memory_wasm->max_page_count;
  85. memory_aot->num_bytes_per_page = memory_wasm->num_bytes_per_page;
  86. }
  87. return memories;
  88. }
  89. static void
  90. aot_destroy_mem_init_data_list(AOTMemInitData **data_list, uint32 count)
  91. {
  92. uint32 i;
  93. for (i = 0; i < count; i++)
  94. if (data_list[i]) {
  95. if (data_list[i]->bytes)
  96. wasm_runtime_free(data_list[i]->bytes);
  97. wasm_runtime_free(data_list[i]);
  98. }
  99. wasm_runtime_free(data_list);
  100. }
  101. static AOTMemInitData **
  102. aot_create_mem_init_data_list(const WASMModule *module)
  103. {
  104. AOTMemInitData **data_list;
  105. uint64 size;
  106. uint32 i;
  107. /* Allocate memory */
  108. size = sizeof(AOTMemInitData *) * (uint64)module->data_seg_count;
  109. if (size >= UINT32_MAX
  110. || !(data_list = wasm_runtime_malloc((uint32)size))) {
  111. aot_set_last_error("allocate memory failed.");
  112. return NULL;
  113. }
  114. memset(data_list, 0, size);
  115. /* Create each memory data segment */
  116. for (i = 0; i < module->data_seg_count; i++) {
  117. size = sizeof(AOTMemInitData);
  118. if (size >= UINT32_MAX
  119. || !(data_list[i] = wasm_runtime_malloc((uint32)size))) {
  120. aot_set_last_error("allocate memory failed.");
  121. goto fail;
  122. }
  123. #if WASM_ENABLE_BULK_MEMORY != 0
  124. /* Set bulk memory specific properties if enabled */
  125. data_list[i]->is_passive = module->data_segments[i]->is_passive;
  126. data_list[i]->memory_index = module->data_segments[i]->memory_index;
  127. #endif
  128. data_list[i]->offset = module->data_segments[i]->base_offset;
  129. data_list[i]->byte_count = module->data_segments[i]->data_length;
  130. data_list[i]->bytes = NULL;
  131. /* Allocate memory for AOT compiler is OK, because the data segment
  132. * is small and the host memory is enough */
  133. if (data_list[i]->byte_count > 0) {
  134. data_list[i]->bytes = wasm_runtime_malloc(data_list[i]->byte_count);
  135. if (!data_list[i]->bytes) {
  136. aot_set_last_error("allocate memory failed.");
  137. goto fail;
  138. }
  139. /* Copy the actual data bytes from the WASM module */
  140. memcpy(data_list[i]->bytes, module->data_segments[i]->data,
  141. module->data_segments[i]->data_length);
  142. }
  143. }
  144. return data_list;
  145. fail:
  146. /* Clean up allocated memory in case of failure */
  147. aot_destroy_mem_init_data_list(data_list, module->data_seg_count);
  148. return NULL;
  149. }
  150. static AOTImportTable *
  151. aot_create_import_tables(const WASMModule *module)
  152. {
  153. uint64 size = sizeof(AOTImportTable) * (uint64)module->import_table_count;
  154. if (size >= UINT32_MAX) {
  155. aot_set_last_error("too big allocate size");
  156. return NULL;
  157. }
  158. AOTImportTable *import_tables = wasm_runtime_malloc((uint32)size);
  159. if (!import_tables) {
  160. aot_set_last_error("allocate import tables failed.");
  161. return NULL;
  162. }
  163. memset(import_tables, 0, (uint32)size);
  164. for (uint32 i = 0; i < module->import_table_count; i++) {
  165. AOTImportTable *table_aot = import_tables + i;
  166. WASMImport *table_wasm = module->import_tables + i;
  167. table_aot->module_name = table_wasm->u.table.module_name;
  168. table_aot->table_name = table_wasm->u.table.field_name;
  169. table_aot->table_type.elem_type =
  170. table_wasm->u.table.table_type.elem_type;
  171. table_aot->table_type.flags = table_wasm->u.table.table_type.flags;
  172. table_aot->table_type.init_size =
  173. table_wasm->u.table.table_type.init_size;
  174. table_aot->table_type.max_size =
  175. table_wasm->u.table.table_type.max_size;
  176. #if WASM_ENABLE_GC != 0
  177. table_aot->table_type.elem_ref_type =
  178. table_wasm->u.table.table_type.elem_ref_type;
  179. #endif
  180. table_aot->table_type.possible_grow =
  181. table_wasm->u.table.table_type.possible_grow;
  182. }
  183. return import_tables;
  184. }
  185. static AOTTable *
  186. aot_create_tables(const WASMModule *module)
  187. {
  188. uint64 size = sizeof(AOTTable) * (uint64)module->table_count;
  189. if (size >= UINT32_MAX) {
  190. aot_set_last_error("too big allocate size");
  191. return NULL;
  192. }
  193. AOTTable *tables = wasm_runtime_malloc((uint32)size);
  194. if (!tables) {
  195. aot_set_last_error("allocate tables failed.");
  196. return NULL;
  197. }
  198. memset(tables, 0, (uint32)size);
  199. for (uint32 i = 0; i < module->table_count; i++) {
  200. AOTTable *table_aot = tables + i;
  201. WASMTable *table_wasm = module->tables + i;
  202. table_aot->table_type.elem_type = table_wasm->table_type.elem_type;
  203. table_aot->table_type.flags = table_wasm->table_type.flags;
  204. table_aot->table_type.init_size = table_wasm->table_type.init_size;
  205. table_aot->table_type.max_size = table_wasm->table_type.max_size;
  206. table_aot->table_type.possible_grow =
  207. table_wasm->table_type.possible_grow;
  208. #if WASM_ENABLE_GC != 0
  209. table_aot->table_type.elem_ref_type =
  210. table_wasm->table_type.elem_ref_type;
  211. /* Note: if the init_expr contains extra data for struct/array
  212. * initialization information (init_expr.u.data), the pointer is
  213. * copied.
  214. * The pointers should still belong to wasm module, so DO NOT
  215. * free the pointers copied to comp_data */
  216. table_aot->init_expr = table_wasm->init_expr;
  217. #endif
  218. }
  219. return tables;
  220. }
  221. static void
  222. aot_destroy_table_init_data_list(AOTTableInitData **data_list, uint32 count)
  223. {
  224. uint32 i;
  225. for (i = 0; i < count; i++)
  226. if (data_list[i])
  227. wasm_runtime_free(data_list[i]);
  228. wasm_runtime_free(data_list);
  229. }
  230. static AOTTableInitData **
  231. aot_create_table_init_data_list(const WASMModule *module)
  232. {
  233. AOTTableInitData **data_list;
  234. uint64 size;
  235. uint32 i;
  236. /* Allocate memory */
  237. size = sizeof(AOTTableInitData *) * (uint64)module->table_seg_count;
  238. if (size >= UINT32_MAX
  239. || !(data_list = wasm_runtime_malloc((uint32)size))) {
  240. aot_set_last_error("allocate memory failed.");
  241. return NULL;
  242. }
  243. memset(data_list, 0, size);
  244. /* Create each table data segment */
  245. for (i = 0; i < module->table_seg_count; i++) {
  246. size = offsetof(AOTTableInitData, init_values)
  247. + sizeof(InitializerExpression)
  248. * (uint64)module->table_segments[i].value_count;
  249. if (size >= UINT32_MAX
  250. || !(data_list[i] = wasm_runtime_malloc((uint32)size))) {
  251. aot_set_last_error("allocate memory failed.");
  252. goto fail;
  253. }
  254. data_list[i]->offset = module->table_segments[i].base_offset;
  255. data_list[i]->value_count = module->table_segments[i].value_count;
  256. data_list[i]->mode = module->table_segments[i].mode;
  257. data_list[i]->elem_type = module->table_segments[i].elem_type;
  258. /* runtime control it */
  259. data_list[i]->table_index = module->table_segments[i].table_index;
  260. bh_memcpy_s(&data_list[i]->offset, sizeof(AOTInitExpr),
  261. &module->table_segments[i].base_offset,
  262. sizeof(AOTInitExpr));
  263. data_list[i]->value_count = module->table_segments[i].value_count;
  264. #if WASM_ENABLE_GC != 0
  265. data_list[i]->elem_ref_type = module->table_segments[i].elem_ref_type;
  266. #endif
  267. bh_memcpy_s(data_list[i]->init_values,
  268. sizeof(InitializerExpression)
  269. * module->table_segments[i].value_count,
  270. module->table_segments[i].init_values,
  271. sizeof(InitializerExpression)
  272. * module->table_segments[i].value_count);
  273. }
  274. return data_list;
  275. fail:
  276. aot_destroy_table_init_data_list(data_list, module->table_seg_count);
  277. return NULL;
  278. }
  279. static void
  280. get_value_type_size(uint8 value_type, bool gc_enabled, uint32 *p_size_64bit,
  281. uint32 *p_size_32bit)
  282. {
  283. uint32 size_64bit = 0, size_32bit = 0;
  284. if (value_type == VALUE_TYPE_I32 || value_type == VALUE_TYPE_F32)
  285. size_64bit = size_32bit = sizeof(int32);
  286. else if (value_type == VALUE_TYPE_I64 || value_type == VALUE_TYPE_F64)
  287. size_64bit = size_32bit = sizeof(int64);
  288. else if (value_type == VALUE_TYPE_V128)
  289. size_64bit = size_32bit = sizeof(int64) * 2;
  290. else if (!gc_enabled
  291. && (value_type == VALUE_TYPE_FUNCREF
  292. || value_type == VALUE_TYPE_EXTERNREF))
  293. size_64bit = size_32bit = sizeof(int32);
  294. else if (gc_enabled
  295. && ((value_type >= (uint8)REF_TYPE_ARRAYREF
  296. && value_type <= (uint8)REF_TYPE_NULLFUNCREF)
  297. || (value_type >= (uint8)REF_TYPE_HT_NULLABLE
  298. && value_type <= (uint8)REF_TYPE_HT_NON_NULLABLE)
  299. #if WASM_ENABLE_STRINGREF != 0
  300. || (value_type >= (uint8)REF_TYPE_STRINGVIEWWTF8
  301. && value_type <= (uint8)REF_TYPE_STRINGREF)
  302. || (value_type >= (uint8)REF_TYPE_STRINGVIEWITER
  303. && value_type <= (uint8)REF_TYPE_STRINGVIEWWTF16)
  304. #endif
  305. )) {
  306. size_64bit = sizeof(uint64);
  307. size_32bit = sizeof(uint32);
  308. }
  309. else if (gc_enabled && value_type == PACKED_TYPE_I8) {
  310. size_64bit = size_32bit = sizeof(int8);
  311. }
  312. else if (gc_enabled && value_type == PACKED_TYPE_I16) {
  313. size_64bit = size_32bit = sizeof(int16);
  314. }
  315. else {
  316. bh_assert(0);
  317. }
  318. *p_size_64bit = size_64bit;
  319. *p_size_32bit = size_32bit;
  320. }
  321. static AOTImportGlobal *
  322. aot_create_import_globals(const WASMModule *module, bool gc_enabled,
  323. uint32 *p_import_global_data_size_64bit,
  324. uint32 *p_import_global_data_size_32bit)
  325. {
  326. AOTImportGlobal *import_globals;
  327. uint64 size;
  328. uint32 i, data_offset_64bit = 0, data_offset_32bit = 0;
  329. uint32 value_size_64bit, value_size_32bit;
  330. /* Allocate memory */
  331. size = sizeof(AOTImportGlobal) * (uint64)module->import_global_count;
  332. if (size >= UINT32_MAX
  333. || !(import_globals = wasm_runtime_malloc((uint32)size))) {
  334. aot_set_last_error("allocate memory failed.");
  335. return NULL;
  336. }
  337. memset(import_globals, 0, (uint32)size);
  338. /* Create each import global */
  339. for (i = 0; i < module->import_global_count; i++) {
  340. WASMGlobalImport *import_global = &module->import_globals[i].u.global;
  341. import_globals[i].module_name = import_global->module_name;
  342. import_globals[i].global_name = import_global->field_name;
  343. import_globals[i].type.val_type = import_global->type.val_type;
  344. import_globals[i].type.is_mutable = import_global->type.is_mutable;
  345. import_globals[i].global_data_linked =
  346. import_global->global_data_linked;
  347. import_globals[i].data_offset_64bit = data_offset_64bit;
  348. import_globals[i].data_offset_32bit = data_offset_32bit;
  349. get_value_type_size(import_global->type.val_type, gc_enabled,
  350. &value_size_64bit, &value_size_32bit);
  351. import_globals[i].size_64bit = value_size_64bit;
  352. import_globals[i].size_32bit = value_size_32bit;
  353. data_offset_64bit += value_size_64bit;
  354. data_offset_32bit += value_size_32bit;
  355. }
  356. *p_import_global_data_size_64bit = data_offset_64bit;
  357. *p_import_global_data_size_32bit = data_offset_32bit;
  358. return import_globals;
  359. }
  360. static AOTGlobal *
  361. aot_create_globals(const WASMModule *module, bool gc_enabled,
  362. uint32 global_data_start_offset_64bit,
  363. uint32 global_data_start_offset_32bit,
  364. uint32 *p_global_data_size_64bit,
  365. uint32 *p_global_data_size_32bit)
  366. {
  367. AOTGlobal *globals;
  368. uint64 size;
  369. uint32 i;
  370. uint32 data_offset_64bit = global_data_start_offset_64bit;
  371. uint32 data_offset_32bit = global_data_start_offset_32bit;
  372. uint32 value_size_64bit, value_size_32bit;
  373. /* Allocate memory */
  374. size = sizeof(AOTGlobal) * (uint64)module->global_count;
  375. if (size >= UINT32_MAX || !(globals = wasm_runtime_malloc((uint32)size))) {
  376. aot_set_last_error("allocate memory failed.");
  377. return NULL;
  378. }
  379. memset(globals, 0, (uint32)size);
  380. /* Create each global */
  381. for (i = 0; i < module->global_count; i++) {
  382. WASMGlobal *global = &module->globals[i];
  383. globals[i].type.val_type = global->type.val_type;
  384. globals[i].type.is_mutable = global->type.is_mutable;
  385. memcpy(&globals[i].init_expr, &global->init_expr,
  386. sizeof(global->init_expr));
  387. globals[i].data_offset_64bit = data_offset_64bit;
  388. globals[i].data_offset_32bit = data_offset_32bit;
  389. get_value_type_size(global->type.val_type, gc_enabled,
  390. &value_size_64bit, &value_size_32bit);
  391. globals[i].size_64bit = value_size_64bit;
  392. globals[i].size_32bit = value_size_32bit;
  393. data_offset_64bit += value_size_64bit;
  394. data_offset_32bit += value_size_32bit;
  395. }
  396. *p_global_data_size_64bit =
  397. data_offset_64bit - global_data_start_offset_64bit;
  398. *p_global_data_size_32bit =
  399. data_offset_32bit - global_data_start_offset_32bit;
  400. return globals;
  401. }
  402. static AOTImportFunc *
  403. aot_create_import_funcs(const WASMModule *module)
  404. {
  405. AOTImportFunc *import_funcs;
  406. uint64 size;
  407. uint32 i, j;
  408. /* Allocate memory */
  409. size = sizeof(AOTImportFunc) * (uint64)module->import_function_count;
  410. if (size >= UINT32_MAX
  411. || !(import_funcs = wasm_runtime_malloc((uint32)size))) {
  412. aot_set_last_error("allocate memory failed.");
  413. return NULL;
  414. }
  415. /* Create each import function */
  416. for (i = 0; i < module->import_function_count; i++) {
  417. WASMFunctionImport *import_func =
  418. &module->import_functions[i].u.function;
  419. import_funcs[i].module_name = import_func->module_name;
  420. import_funcs[i].func_name = import_func->field_name;
  421. import_funcs[i].func_ptr_linked = import_func->func_ptr_linked;
  422. import_funcs[i].func_type = import_func->func_type;
  423. import_funcs[i].signature = import_func->signature;
  424. import_funcs[i].attachment = import_func->attachment;
  425. import_funcs[i].call_conv_raw = import_func->call_conv_raw;
  426. #if WASM_ENABLE_MULTI_MODULE != 0
  427. import_funcs[i].call_conv_wasm_c_api = false;
  428. #endif
  429. /* Resolve function type index */
  430. for (j = 0; j < module->type_count; j++)
  431. if (import_func->func_type == (WASMFuncType *)module->types[j]) {
  432. import_funcs[i].func_type_index = j;
  433. break;
  434. }
  435. }
  436. return import_funcs;
  437. }
  438. static void
  439. aot_destroy_funcs(AOTFunc **funcs, uint32 count)
  440. {
  441. uint32 i;
  442. for (i = 0; i < count; i++)
  443. if (funcs[i]) {
  444. if (funcs[i]->local_offsets)
  445. wasm_runtime_free(funcs[i]->local_offsets);
  446. wasm_runtime_free(funcs[i]);
  447. }
  448. wasm_runtime_free(funcs);
  449. }
  450. static AOTFunc **
  451. aot_create_funcs(const WASMModule *module, uint32 pointer_size)
  452. {
  453. AOTFunc **funcs;
  454. uint64 size;
  455. uint32 i, j;
  456. /* Allocate memory */
  457. size = sizeof(AOTFunc *) * (uint64)module->function_count;
  458. if (size >= UINT32_MAX || !(funcs = wasm_runtime_malloc((uint32)size))) {
  459. aot_set_last_error("allocate memory failed.");
  460. return NULL;
  461. }
  462. memset(funcs, 0, size);
  463. /* Create each function */
  464. for (i = 0; i < module->function_count; i++) {
  465. WASMFunction *func = module->functions[i];
  466. AOTFuncType *func_type = NULL;
  467. AOTFunc *aot_func = NULL;
  468. uint64 total_size;
  469. uint32 offset = 0;
  470. size = sizeof(AOTFunc);
  471. if (!(aot_func = funcs[i] = wasm_runtime_malloc((uint32)size))) {
  472. aot_set_last_error("allocate memory failed.");
  473. goto fail;
  474. }
  475. memset(aot_func, 0, sizeof(AOTFunc));
  476. func_type = aot_func->func_type = func->func_type;
  477. /* Resolve function type index */
  478. for (j = 0; j < module->type_count; j++) {
  479. if (func_type == (WASMFuncType *)module->types[j]) {
  480. aot_func->func_type_index = j;
  481. break;
  482. }
  483. }
  484. total_size = sizeof(uint16)
  485. * ((uint64)func_type->param_count + func->local_count);
  486. if ((total_size > 0)
  487. && (total_size >= UINT32_MAX
  488. || !(aot_func->local_offsets =
  489. wasm_runtime_malloc((uint32)total_size)))) {
  490. aot_set_last_error("allocate memory failed.");
  491. goto fail;
  492. }
  493. /* Resolve local variable info and code info */
  494. aot_func->local_count = func->local_count;
  495. aot_func->local_types_wp = func->local_types;
  496. aot_func->code = func->code;
  497. aot_func->code_size = func->code_size;
  498. /* Resolve local offsets */
  499. for (j = 0; j < func_type->param_count; j++) {
  500. aot_func->local_offsets[j] = (uint16)offset;
  501. offset += wasm_value_type_cell_num_internal(func_type->types[j],
  502. pointer_size);
  503. }
  504. aot_func->param_cell_num = offset;
  505. for (j = 0; j < func->local_count; j++) {
  506. aot_func->local_offsets[func_type->param_count + j] =
  507. (uint16)offset;
  508. offset += wasm_value_type_cell_num_internal(func->local_types[j],
  509. pointer_size);
  510. }
  511. aot_func->local_cell_num = offset - aot_func->param_cell_num;
  512. aot_func->max_stack_cell_num = func->max_stack_cell_num;
  513. /* We use max_stack_cell_num calculated from wasm_loader, which is based
  514. * on wamrc's target type.
  515. * - If the wamrc is compiled as 64bit, then the number is enough for
  516. * both 32bit and 64bit runtime target
  517. * - If the wamrc is compiled as 32bit, then we multiply this number by
  518. * two to avoid overflow on 64bit runtime target */
  519. if (sizeof(uintptr_t) == 4) {
  520. aot_func->max_stack_cell_num *= 2;
  521. }
  522. }
  523. return funcs;
  524. fail:
  525. aot_destroy_funcs(funcs, module->function_count);
  526. return NULL;
  527. }
  528. #if WASM_ENABLE_GC != 0
  529. static void
  530. calculate_struct_field_sizes_offsets(AOTCompData *comp_data, bool is_target_x86,
  531. bool gc_enabled)
  532. {
  533. uint32 i;
  534. for (i = 0; i < comp_data->type_count; i++) {
  535. if (comp_data->types[i]->type_flag == WASM_TYPE_STRUCT) {
  536. WASMStructType *struct_type = (WASMStructType *)comp_data->types[i];
  537. WASMStructFieldType *fields = struct_type->fields;
  538. uint32 field_offset_64bit, field_offset_32bit;
  539. uint32 field_size_64bit, field_size_32bit, j;
  540. /* offsetof(WASMStructObject, field_data) in 64-bit */
  541. field_offset_64bit = sizeof(uint64);
  542. /* offsetof(WASMStructObject, field_data) in 32-bit */
  543. field_offset_32bit = sizeof(uint32);
  544. for (j = 0; j < struct_type->field_count; j++) {
  545. get_value_type_size(fields[j].field_type, gc_enabled,
  546. &field_size_64bit, &field_size_32bit);
  547. fields[j].field_size_64bit = field_size_64bit;
  548. fields[j].field_size_32bit = field_size_32bit;
  549. if (!is_target_x86) {
  550. if (field_size_64bit == 2)
  551. field_offset_64bit = align_uint(field_offset_64bit, 2);
  552. else if (field_size_64bit >= 4)
  553. field_offset_64bit = align_uint(field_offset_64bit, 4);
  554. if (field_size_32bit == 2)
  555. field_offset_32bit = align_uint(field_offset_32bit, 2);
  556. else if (field_size_32bit >= 4)
  557. field_offset_32bit = align_uint(field_offset_32bit, 4);
  558. }
  559. fields[j].field_offset_64bit = field_offset_64bit;
  560. fields[j].field_offset_32bit = field_offset_32bit;
  561. field_offset_64bit += field_size_64bit;
  562. field_offset_32bit += field_size_32bit;
  563. }
  564. }
  565. }
  566. }
  567. #endif
  568. /**
  569. * Checks if target architecture is 64-bit based on target_arch string.
  570. *
  571. * @param target_arch The target architecture string (e.g. "x86_64", "aarch64")
  572. * @return true if target is 64-bit architecture, false otherwise
  573. *
  574. * If target_arch is NULL, detection is based on UINTPTR_MAX.
  575. * Otherwise looks for "64" in target_arch string.
  576. */
  577. static bool
  578. arch_is_64bit(const char *target_arch)
  579. {
  580. if (!target_arch) {
  581. #if UINTPTR_MAX == UINT64_MAX
  582. return true;
  583. #else
  584. return false;
  585. #endif
  586. }
  587. /* All 64bit targets contains "64" string in their target name */
  588. return strstr(target_arch, "64") != NULL;
  589. }
  590. /**
  591. * Checks if target architecture is x86/x64 based on target_arch string.
  592. *
  593. * @param target_arch The target architecture string (e.g. "x86_64", "i386")
  594. * @return true if target is x86/x64 architecture, false otherwise
  595. *
  596. * If target_arch is NULL, detection is based on build-time definitions.
  597. * Otherwise checks for x86_64 or i386 in target_arch string.
  598. */
  599. static bool
  600. arch_is_x86(const char *target_arch)
  601. {
  602. if (!target_arch) {
  603. #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) \
  604. || defined(BUILD_TARGET_X86_32)
  605. return true;
  606. #else
  607. return false;
  608. #endif
  609. }
  610. return !strncmp(target_arch, "x86_64", 6)
  611. || !strncmp(target_arch, "i386", 4);
  612. }
  613. /**
  614. * Initialize memory information in AOT compilation data from WASM module.
  615. *
  616. * @param comp_data the AOT compilation data structure to initialize
  617. * @param module the source WASM module containing memory information
  618. * @return true if initialization succeeded, false otherwise
  619. */
  620. static bool
  621. aot_init_memories(AOTCompData *comp_data, WASMModule *module)
  622. {
  623. /* Create import memories */
  624. comp_data->import_memory_count = module->import_memory_count;
  625. if (comp_data->import_memory_count) {
  626. comp_data->import_memories =
  627. aot_create_import_memories(module, comp_data->import_memory_count);
  628. if (!comp_data->import_memories) {
  629. return false;
  630. }
  631. }
  632. /* Create memories */
  633. comp_data->memory_count = module->memory_count;
  634. /* Allocate memory for memory array, reserve one AOTMemory space at least */
  635. if (module->import_memory_count + module->memory_count == 0)
  636. comp_data->memory_count = 1;
  637. if (comp_data->memory_count) {
  638. comp_data->memories =
  639. aot_create_memories(module, comp_data->memory_count);
  640. if (!comp_data->memories) {
  641. return false;
  642. }
  643. }
  644. /* inherit reserved memory. keep it in memories[] */
  645. if (module->import_memory_count + module->memory_count == 0) {
  646. comp_data->memories[0].num_bytes_per_page = DEFAULT_NUM_BYTES_PER_PAGE;
  647. }
  648. return true;
  649. }
  650. /**
  651. * Initialize table information in AOT compilation data from WASM module.
  652. *
  653. * @param comp_data the AOT compilation data structure to initialize
  654. * @param module the source WASM module containing table information
  655. * @return true if initialization succeeded, false otherwise
  656. */
  657. static bool
  658. aot_init_tables(AOTCompData *comp_data, WASMModule *module)
  659. {
  660. /* Create import tables */
  661. comp_data->import_table_count = module->import_table_count;
  662. if (comp_data->import_table_count > 0) {
  663. comp_data->import_tables = aot_create_import_tables(module);
  664. if (!comp_data->import_tables) {
  665. return false;
  666. }
  667. }
  668. /* Create tables */
  669. comp_data->table_count = module->table_count;
  670. if (comp_data->table_count > 0) {
  671. comp_data->tables = aot_create_tables(module);
  672. if (!comp_data->tables) {
  673. return false;
  674. }
  675. }
  676. return true;
  677. }
  678. /**
  679. * Initialize memory segment information in AOT compilation data.
  680. *
  681. * @param comp_data the AOT compilation data structure to initialize
  682. * @param module the source WASM module containing memory segments
  683. * @return true if initialization succeeded, false otherwise
  684. */
  685. static bool
  686. aot_init_memory_segments(AOTCompData *comp_data, WASMModule *module)
  687. {
  688. comp_data->mem_init_data_count = module->data_seg_count;
  689. if (comp_data->mem_init_data_count > 0
  690. && !(comp_data->mem_init_data_list =
  691. aot_create_mem_init_data_list(module))) {
  692. return false;
  693. }
  694. return true;
  695. }
  696. /**
  697. * Initialize table segment information in AOT compilation data.
  698. *
  699. * @param comp_data the AOT compilation data structure to initialize
  700. * @param module the source WASM module containing table segments
  701. * @return true if initialization succeeded, false otherwise
  702. */
  703. static bool
  704. aot_init_table_segments(AOTCompData *comp_data, WASMModule *module)
  705. {
  706. comp_data->table_init_data_count = module->table_seg_count;
  707. if (comp_data->table_init_data_count > 0
  708. && !(comp_data->table_init_data_list =
  709. aot_create_table_init_data_list(module))) {
  710. return false;
  711. }
  712. return true;
  713. }
  714. /**
  715. * Initialize global variable information in AOT compilation data.
  716. *
  717. * @param comp_data the AOT compilation data structure to initialize
  718. * @param module the source WASM module containing global information
  719. * @param gc_enabled whether garbage collection is enabled
  720. * @param import_global_data_size_64bit [out] size of imported global data for
  721. * 64-bit
  722. * @param import_global_data_size_32bit [out] size of imported global data for
  723. * 32-bit
  724. * @param global_data_size_64bit [out] size of global data for 64-bit
  725. * @param global_data_size_32bit [out] size of global data for 32-bit
  726. * @return true if initialization succeeded, false otherwise
  727. */
  728. static bool
  729. aot_init_globals(AOTCompData *comp_data, WASMModule *module, bool gc_enabled,
  730. uint32 *import_global_data_size_64bit,
  731. uint32 *import_global_data_size_32bit,
  732. uint32 *global_data_size_64bit, uint32 *global_data_size_32bit)
  733. {
  734. comp_data->import_global_count = module->import_global_count;
  735. if (comp_data->import_global_count > 0
  736. && !(comp_data->import_globals = aot_create_import_globals(
  737. module, gc_enabled, import_global_data_size_64bit,
  738. import_global_data_size_32bit))) {
  739. return false;
  740. }
  741. comp_data->global_count = module->global_count;
  742. if (comp_data->global_count
  743. && !(comp_data->globals = aot_create_globals(
  744. module, gc_enabled, *import_global_data_size_64bit,
  745. *import_global_data_size_32bit, global_data_size_64bit,
  746. global_data_size_32bit))) {
  747. return false;
  748. }
  749. comp_data->global_data_size_64bit =
  750. *import_global_data_size_64bit + *global_data_size_64bit;
  751. comp_data->global_data_size_32bit =
  752. *import_global_data_size_32bit + *global_data_size_32bit;
  753. return true;
  754. }
  755. /**
  756. * Initialize type information in AOT compilation data.
  757. *
  758. * @param comp_data the AOT compilation data structure to initialize
  759. * @param module the source WASM module containing type information
  760. * @param is_target_x86 whether the target architecture is x86
  761. * @param gc_enabled whether garbage collection is enabled
  762. * @return true if initialization succeeded, false otherwise
  763. */
  764. static bool
  765. aot_init_types(AOTCompData *comp_data, WASMModule *module, bool is_target_x86,
  766. bool gc_enabled)
  767. {
  768. comp_data->type_count = module->type_count;
  769. comp_data->types = module->types;
  770. #if WASM_ENABLE_GC != 0
  771. calculate_struct_field_sizes_offsets(comp_data, is_target_x86, gc_enabled);
  772. #endif
  773. return true;
  774. }
  775. /**
  776. * Initialize function information in AOT compilation data.
  777. *
  778. * @param comp_data the AOT compilation data structure to initialize
  779. * @param module the source WASM module containing function information
  780. * @param is_64bit_target whether the target architecture is 64-bit
  781. * @return true if initialization succeeded, false otherwise
  782. */
  783. static bool
  784. aot_init_functions(AOTCompData *comp_data, WASMModule *module,
  785. bool is_64bit_target)
  786. {
  787. comp_data->import_func_count = module->import_function_count;
  788. if (comp_data->import_func_count
  789. && !(comp_data->import_funcs = aot_create_import_funcs(module))) {
  790. return false;
  791. }
  792. comp_data->func_count = module->function_count;
  793. if (comp_data->func_count
  794. && !(comp_data->funcs =
  795. aot_create_funcs(module, is_64bit_target ? 8 : 4))) {
  796. return false;
  797. }
  798. return true;
  799. }
  800. /**
  801. * Initialize auxiliary data in AOT compilation data.
  802. *
  803. * @param comp_data the AOT compilation data structure to initialize
  804. * @param module the source WASM module containing auxiliary data
  805. */
  806. static void
  807. aot_init_aux_data(AOTCompData *comp_data, WASMModule *module)
  808. {
  809. comp_data->aux_data_end_global_index = module->aux_data_end_global_index;
  810. comp_data->aux_data_end = module->aux_data_end;
  811. comp_data->aux_heap_base_global_index = module->aux_heap_base_global_index;
  812. comp_data->aux_heap_base = module->aux_heap_base;
  813. comp_data->aux_stack_top_global_index = module->aux_stack_top_global_index;
  814. comp_data->aux_stack_bottom = module->aux_stack_bottom;
  815. comp_data->aux_stack_size = module->aux_stack_size;
  816. comp_data->start_func_index = module->start_function;
  817. comp_data->malloc_func_index = module->malloc_function;
  818. comp_data->free_func_index = module->free_function;
  819. comp_data->retain_func_index = module->retain_function;
  820. #if WASM_ENABLE_STRINGREF != 0
  821. comp_data->string_literal_count = module->string_literal_count;
  822. comp_data->string_literal_ptrs_wp = module->string_literal_ptrs;
  823. comp_data->string_literal_lengths_wp = module->string_literal_lengths;
  824. #endif
  825. }
  826. AOTCompData *
  827. aot_create_comp_data(WASMModule *module, const char *target_arch,
  828. bool gc_enabled)
  829. {
  830. AOTCompData *comp_data;
  831. uint32 import_global_data_size_64bit = 0, global_data_size_64bit = 0;
  832. uint32 import_global_data_size_32bit = 0, global_data_size_32bit = 0;
  833. bool is_64bit_target = arch_is_64bit(target_arch);
  834. bool is_target_x86 = arch_is_x86(target_arch);
  835. if (!(comp_data = wasm_runtime_malloc(sizeof(AOTCompData)))) {
  836. aot_set_last_error("create compile data failed.\n");
  837. return NULL;
  838. }
  839. memset(comp_data, 0, sizeof(AOTCompData));
  840. if (!aot_init_memories(comp_data, module)
  841. || !aot_init_memory_segments(comp_data, module)
  842. || !aot_init_tables(comp_data, module)
  843. || !aot_init_table_segments(comp_data, module)
  844. || !aot_init_globals(comp_data, module, gc_enabled,
  845. &import_global_data_size_64bit,
  846. &import_global_data_size_32bit,
  847. &global_data_size_64bit, &global_data_size_32bit)
  848. || !aot_init_types(comp_data, module, is_target_x86, gc_enabled)
  849. || !aot_init_functions(comp_data, module, is_64bit_target)) {
  850. goto fail;
  851. }
  852. #if WASM_ENABLE_CUSTOM_NAME_SECTION != 0
  853. comp_data->name_section_buf = module->name_section_buf;
  854. comp_data->name_section_buf_end = module->name_section_buf_end;
  855. #endif
  856. aot_init_aux_data(comp_data, module);
  857. comp_data->wasm_module = module;
  858. return comp_data;
  859. fail:
  860. aot_destroy_comp_data(comp_data);
  861. return NULL;
  862. }
  863. void
  864. aot_destroy_comp_data(AOTCompData *comp_data)
  865. {
  866. if (!comp_data)
  867. return;
  868. if (comp_data->import_memories)
  869. wasm_runtime_free(comp_data->import_memories);
  870. if (comp_data->memories)
  871. wasm_runtime_free(comp_data->memories);
  872. if (comp_data->mem_init_data_list)
  873. aot_destroy_mem_init_data_list(comp_data->mem_init_data_list,
  874. comp_data->mem_init_data_count);
  875. if (comp_data->import_tables)
  876. wasm_runtime_free(comp_data->import_tables);
  877. if (comp_data->tables)
  878. wasm_runtime_free(comp_data->tables);
  879. if (comp_data->table_init_data_list)
  880. aot_destroy_table_init_data_list(comp_data->table_init_data_list,
  881. comp_data->table_init_data_count);
  882. if (comp_data->import_globals)
  883. wasm_runtime_free(comp_data->import_globals);
  884. if (comp_data->globals)
  885. wasm_runtime_free(comp_data->globals);
  886. if (comp_data->import_funcs)
  887. wasm_runtime_free(comp_data->import_funcs);
  888. if (comp_data->funcs)
  889. aot_destroy_funcs(comp_data->funcs, comp_data->func_count);
  890. if (comp_data->aot_name_section_buf)
  891. wasm_runtime_free(comp_data->aot_name_section_buf);
  892. wasm_runtime_free(comp_data);
  893. }