aot.c 32 KB

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