aot.c 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936
  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. #if WASM_ENABLE_BRANCH_HINTS != 0
  365. aot_func->code_body_begin = func->code_body_begin;
  366. #endif
  367. /* Resolve local offsets */
  368. for (j = 0; j < func_type->param_count; j++) {
  369. aot_func->local_offsets[j] = (uint16)offset;
  370. offset += wasm_value_type_cell_num_internal(func_type->types[j],
  371. pointer_size);
  372. }
  373. aot_func->param_cell_num = offset;
  374. for (j = 0; j < func->local_count; j++) {
  375. aot_func->local_offsets[func_type->param_count + j] =
  376. (uint16)offset;
  377. offset += wasm_value_type_cell_num_internal(func->local_types[j],
  378. pointer_size);
  379. }
  380. aot_func->local_cell_num = offset - aot_func->param_cell_num;
  381. aot_func->max_stack_cell_num = func->max_stack_cell_num;
  382. /* We use max_stack_cell_num calculated from wasm_loader, which is based
  383. * on wamrc's target type.
  384. * - If the wamrc is compiled as 64bit, then the number is enough for
  385. * both 32bit and 64bit runtime target
  386. * - If the wamrc is compiled as 32bit, then we multiply this number by
  387. * two to avoid overflow on 64bit runtime target */
  388. if (sizeof(uintptr_t) == 4) {
  389. aot_func->max_stack_cell_num *= 2;
  390. }
  391. }
  392. return funcs;
  393. fail:
  394. aot_destroy_funcs(funcs, module->function_count);
  395. return NULL;
  396. }
  397. #if WASM_ENABLE_GC != 0
  398. static void
  399. calculate_struct_field_sizes_offsets(AOTCompData *comp_data, bool is_target_x86,
  400. bool gc_enabled)
  401. {
  402. uint32 i;
  403. for (i = 0; i < comp_data->type_count; i++) {
  404. if (comp_data->types[i]->type_flag == WASM_TYPE_STRUCT) {
  405. WASMStructType *struct_type = (WASMStructType *)comp_data->types[i];
  406. WASMStructFieldType *fields = struct_type->fields;
  407. uint32 field_offset_64bit, field_offset_32bit;
  408. uint32 field_size_64bit, field_size_32bit, j;
  409. /* offsetof(WASMStructObject, field_data) in 64-bit */
  410. field_offset_64bit = sizeof(uint64);
  411. /* offsetof(WASMStructObject, field_data) in 32-bit */
  412. field_offset_32bit = sizeof(uint32);
  413. for (j = 0; j < struct_type->field_count; j++) {
  414. get_value_type_size(fields[j].field_type, gc_enabled,
  415. &field_size_64bit, &field_size_32bit);
  416. fields[j].field_size_64bit = field_size_64bit;
  417. fields[j].field_size_32bit = field_size_32bit;
  418. if (!is_target_x86) {
  419. if (field_size_64bit == 2)
  420. field_offset_64bit = align_uint(field_offset_64bit, 2);
  421. else if (field_size_64bit >= 4)
  422. field_offset_64bit = align_uint(field_offset_64bit, 4);
  423. if (field_size_32bit == 2)
  424. field_offset_32bit = align_uint(field_offset_32bit, 2);
  425. else if (field_size_32bit >= 4)
  426. field_offset_32bit = align_uint(field_offset_32bit, 4);
  427. }
  428. fields[j].field_offset_64bit = field_offset_64bit;
  429. fields[j].field_offset_32bit = field_offset_32bit;
  430. field_offset_64bit += field_size_64bit;
  431. field_offset_32bit += field_size_32bit;
  432. }
  433. }
  434. }
  435. }
  436. #endif
  437. /**
  438. * Checks if target architecture is 64-bit based on target_arch string.
  439. *
  440. * @param target_arch The target architecture string (e.g. "x86_64", "aarch64")
  441. * @return true if target is 64-bit architecture, false otherwise
  442. *
  443. * If target_arch is NULL, detection is based on UINTPTR_MAX.
  444. * Otherwise looks for "64" in target_arch string.
  445. */
  446. static bool
  447. arch_is_64bit(const char *target_arch)
  448. {
  449. if (!target_arch) {
  450. #if UINTPTR_MAX == UINT64_MAX
  451. return true;
  452. #else
  453. return false;
  454. #endif
  455. }
  456. /* All 64bit targets contains "64" string in their target name */
  457. return strstr(target_arch, "64") != NULL;
  458. }
  459. /**
  460. * Checks if target architecture is x86/x64 based on target_arch string.
  461. *
  462. * @param target_arch The target architecture string (e.g. "x86_64", "i386")
  463. * @return true if target is x86/x64 architecture, false otherwise
  464. *
  465. * If target_arch is NULL, detection is based on build-time definitions.
  466. * Otherwise checks for x86_64 or i386 in target_arch string.
  467. */
  468. static bool
  469. arch_is_x86(const char *target_arch)
  470. {
  471. if (!target_arch) {
  472. #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) \
  473. || defined(BUILD_TARGET_X86_32)
  474. return true;
  475. #else
  476. return false;
  477. #endif
  478. }
  479. return !strncmp(target_arch, "x86_64", 6)
  480. || !strncmp(target_arch, "i386", 4);
  481. }
  482. /**
  483. * Initialize memory information in AOT compilation data from WASM module.
  484. *
  485. * @param comp_data the AOT compilation data structure to initialize
  486. * @param module the source WASM module containing memory information
  487. * @return true if initialization succeeded, false otherwise
  488. */
  489. static bool
  490. aot_init_memories(AOTCompData *comp_data, WASMModule *module)
  491. {
  492. uint32 i, j;
  493. uint64 size;
  494. comp_data->memory_count =
  495. module->import_memory_count + module->memory_count;
  496. /* Allocate memory for memory array, reserve one AOTMemory space at least */
  497. if (!comp_data->memory_count)
  498. comp_data->memory_count = 1;
  499. size = (uint64)comp_data->memory_count * sizeof(AOTMemory);
  500. if (size >= UINT32_MAX
  501. || !(comp_data->memories = wasm_runtime_malloc((uint32)size))) {
  502. aot_set_last_error("create memories array failed.\n");
  503. return false;
  504. }
  505. memset(comp_data->memories, 0, size);
  506. if (!(module->import_memory_count + module->memory_count)) {
  507. comp_data->memories[0].num_bytes_per_page = DEFAULT_NUM_BYTES_PER_PAGE;
  508. }
  509. /* Set memory page count */
  510. for (i = 0; i < module->import_memory_count + module->memory_count; i++) {
  511. if (i < module->import_memory_count) {
  512. comp_data->memories[i].flags =
  513. module->import_memories[i].u.memory.mem_type.flags;
  514. comp_data->memories[i].num_bytes_per_page =
  515. module->import_memories[i].u.memory.mem_type.num_bytes_per_page;
  516. comp_data->memories[i].init_page_count =
  517. module->import_memories[i].u.memory.mem_type.init_page_count;
  518. comp_data->memories[i].max_page_count =
  519. module->import_memories[i].u.memory.mem_type.max_page_count;
  520. }
  521. else {
  522. j = i - module->import_memory_count;
  523. comp_data->memories[i].flags = module->memories[j].flags;
  524. comp_data->memories[i].num_bytes_per_page =
  525. module->memories[j].num_bytes_per_page;
  526. comp_data->memories[i].init_page_count =
  527. module->memories[j].init_page_count;
  528. comp_data->memories[i].max_page_count =
  529. module->memories[j].max_page_count;
  530. }
  531. }
  532. return true;
  533. }
  534. /**
  535. * Initialize table information in AOT compilation data from WASM module.
  536. *
  537. * @param comp_data the AOT compilation data structure to initialize
  538. * @param module the source WASM module containing table information
  539. * @return true if initialization succeeded, false otherwise
  540. */
  541. static bool
  542. aot_init_tables(AOTCompData *comp_data, WASMModule *module)
  543. {
  544. uint32 i, j;
  545. uint64 size;
  546. comp_data->table_count = module->import_table_count + module->table_count;
  547. if (comp_data->table_count > 0) {
  548. size = sizeof(AOTTable) * (uint64)comp_data->table_count;
  549. if (size >= UINT32_MAX
  550. || !(comp_data->tables = wasm_runtime_malloc((uint32)size))) {
  551. aot_set_last_error("create tables array failed.\n");
  552. return false;
  553. }
  554. memset(comp_data->tables, 0, size);
  555. for (i = 0; i < comp_data->table_count; i++) {
  556. if (i < module->import_table_count) {
  557. comp_data->tables[i].table_type.elem_type =
  558. module->import_tables[i].u.table.table_type.elem_type;
  559. comp_data->tables[i].table_type.flags =
  560. module->import_tables[i].u.table.table_type.flags;
  561. comp_data->tables[i].table_type.init_size =
  562. module->import_tables[i].u.table.table_type.init_size;
  563. comp_data->tables[i].table_type.max_size =
  564. module->import_tables[i].u.table.table_type.max_size;
  565. #if WASM_ENABLE_GC != 0
  566. comp_data->tables[i].table_type.elem_ref_type =
  567. module->import_tables[i].u.table.table_type.elem_ref_type;
  568. #endif
  569. comp_data->tables[i].table_type.possible_grow =
  570. module->import_tables[i].u.table.table_type.possible_grow;
  571. }
  572. else {
  573. j = i - module->import_table_count;
  574. comp_data->tables[i].table_type.elem_type =
  575. module->tables[j].table_type.elem_type;
  576. comp_data->tables[i].table_type.flags =
  577. module->tables[j].table_type.flags;
  578. comp_data->tables[i].table_type.init_size =
  579. module->tables[j].table_type.init_size;
  580. comp_data->tables[i].table_type.max_size =
  581. module->tables[j].table_type.max_size;
  582. comp_data->tables[i].table_type.possible_grow =
  583. module->tables[j].table_type.possible_grow;
  584. #if WASM_ENABLE_GC != 0
  585. comp_data->tables[j].table_type.elem_ref_type =
  586. module->tables[j].table_type.elem_ref_type;
  587. /* Note: if the init_expr contains extra data for struct/array
  588. * initialization information (init_expr.u.data), the pointer is
  589. * copied.
  590. * The pointers should still belong to wasm module, so DO NOT
  591. * free the pointers copied to comp_data */
  592. comp_data->tables[j].init_expr = module->tables[j].init_expr;
  593. #endif
  594. }
  595. }
  596. }
  597. return true;
  598. }
  599. /**
  600. * Initialize memory segment information in AOT compilation data.
  601. *
  602. * @param comp_data the AOT compilation data structure to initialize
  603. * @param module the source WASM module containing memory segments
  604. * @return true if initialization succeeded, false otherwise
  605. */
  606. static bool
  607. aot_init_memory_segments(AOTCompData *comp_data, WASMModule *module)
  608. {
  609. comp_data->mem_init_data_count = module->data_seg_count;
  610. if (comp_data->mem_init_data_count > 0
  611. && !(comp_data->mem_init_data_list =
  612. aot_create_mem_init_data_list(module))) {
  613. return false;
  614. }
  615. return true;
  616. }
  617. /**
  618. * Initialize table segment information in AOT compilation data.
  619. *
  620. * @param comp_data the AOT compilation data structure to initialize
  621. * @param module the source WASM module containing table segments
  622. * @return true if initialization succeeded, false otherwise
  623. */
  624. static bool
  625. aot_init_table_segments(AOTCompData *comp_data, WASMModule *module)
  626. {
  627. comp_data->table_init_data_count = module->table_seg_count;
  628. if (comp_data->table_init_data_count > 0
  629. && !(comp_data->table_init_data_list =
  630. aot_create_table_init_data_list(module))) {
  631. return false;
  632. }
  633. return true;
  634. }
  635. /**
  636. * Initialize global variable information in AOT compilation data.
  637. *
  638. * @param comp_data the AOT compilation data structure to initialize
  639. * @param module the source WASM module containing global information
  640. * @param gc_enabled whether garbage collection is enabled
  641. * @param import_global_data_size_64bit [out] size of imported global data for
  642. * 64-bit
  643. * @param import_global_data_size_32bit [out] size of imported global data for
  644. * 32-bit
  645. * @param global_data_size_64bit [out] size of global data for 64-bit
  646. * @param global_data_size_32bit [out] size of global data for 32-bit
  647. * @return true if initialization succeeded, false otherwise
  648. */
  649. static bool
  650. aot_init_globals(AOTCompData *comp_data, WASMModule *module, bool gc_enabled,
  651. uint32 *import_global_data_size_64bit,
  652. uint32 *import_global_data_size_32bit,
  653. uint32 *global_data_size_64bit, uint32 *global_data_size_32bit)
  654. {
  655. comp_data->import_global_count = module->import_global_count;
  656. if (comp_data->import_global_count > 0
  657. && !(comp_data->import_globals = aot_create_import_globals(
  658. module, gc_enabled, import_global_data_size_64bit,
  659. import_global_data_size_32bit))) {
  660. return false;
  661. }
  662. comp_data->global_count = module->global_count;
  663. if (comp_data->global_count
  664. && !(comp_data->globals = aot_create_globals(
  665. module, gc_enabled, *import_global_data_size_64bit,
  666. *import_global_data_size_32bit, global_data_size_64bit,
  667. global_data_size_32bit))) {
  668. return false;
  669. }
  670. comp_data->global_data_size_64bit =
  671. *import_global_data_size_64bit + *global_data_size_64bit;
  672. comp_data->global_data_size_32bit =
  673. *import_global_data_size_32bit + *global_data_size_32bit;
  674. return true;
  675. }
  676. /**
  677. * Initialize type information in AOT compilation data.
  678. *
  679. * @param comp_data the AOT compilation data structure to initialize
  680. * @param module the source WASM module containing type information
  681. * @param is_target_x86 whether the target architecture is x86
  682. * @param gc_enabled whether garbage collection is enabled
  683. * @return true if initialization succeeded, false otherwise
  684. */
  685. static bool
  686. aot_init_types(AOTCompData *comp_data, WASMModule *module, bool is_target_x86,
  687. bool gc_enabled)
  688. {
  689. comp_data->type_count = module->type_count;
  690. comp_data->types = module->types;
  691. #if WASM_ENABLE_GC != 0
  692. calculate_struct_field_sizes_offsets(comp_data, is_target_x86, gc_enabled);
  693. #endif
  694. return true;
  695. }
  696. /**
  697. * Initialize function 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 function information
  701. * @param is_64bit_target whether the target architecture is 64-bit
  702. * @return true if initialization succeeded, false otherwise
  703. */
  704. static bool
  705. aot_init_functions(AOTCompData *comp_data, WASMModule *module,
  706. bool is_64bit_target)
  707. {
  708. comp_data->import_func_count = module->import_function_count;
  709. if (comp_data->import_func_count
  710. && !(comp_data->import_funcs = aot_create_import_funcs(module))) {
  711. return false;
  712. }
  713. comp_data->func_count = module->function_count;
  714. if (comp_data->func_count
  715. && !(comp_data->funcs =
  716. aot_create_funcs(module, is_64bit_target ? 8 : 4))) {
  717. return false;
  718. }
  719. return true;
  720. }
  721. /**
  722. * Initialize auxiliary data in AOT compilation data.
  723. *
  724. * @param comp_data the AOT compilation data structure to initialize
  725. * @param module the source WASM module containing auxiliary data
  726. */
  727. static void
  728. aot_init_aux_data(AOTCompData *comp_data, WASMModule *module)
  729. {
  730. comp_data->aux_data_end_global_index = module->aux_data_end_global_index;
  731. comp_data->aux_data_end = module->aux_data_end;
  732. comp_data->aux_heap_base_global_index = module->aux_heap_base_global_index;
  733. comp_data->aux_heap_base = module->aux_heap_base;
  734. comp_data->aux_stack_top_global_index = module->aux_stack_top_global_index;
  735. comp_data->aux_stack_bottom = module->aux_stack_bottom;
  736. comp_data->aux_stack_size = module->aux_stack_size;
  737. comp_data->start_func_index = module->start_function;
  738. comp_data->malloc_func_index = module->malloc_function;
  739. comp_data->free_func_index = module->free_function;
  740. comp_data->retain_func_index = module->retain_function;
  741. #if WASM_ENABLE_STRINGREF != 0
  742. comp_data->string_literal_count = module->string_literal_count;
  743. comp_data->string_literal_ptrs_wp = module->string_literal_ptrs;
  744. comp_data->string_literal_lengths_wp = module->string_literal_lengths;
  745. #endif
  746. }
  747. AOTCompData *
  748. aot_create_comp_data(WASMModule *module, const char *target_arch,
  749. bool gc_enabled)
  750. {
  751. AOTCompData *comp_data;
  752. uint32 import_global_data_size_64bit = 0, global_data_size_64bit = 0;
  753. uint32 import_global_data_size_32bit = 0, global_data_size_32bit = 0;
  754. bool is_64bit_target = arch_is_64bit(target_arch);
  755. bool is_target_x86 = arch_is_x86(target_arch);
  756. if (!(comp_data = wasm_runtime_malloc(sizeof(AOTCompData)))) {
  757. aot_set_last_error("create compile data failed.\n");
  758. return NULL;
  759. }
  760. memset(comp_data, 0, sizeof(AOTCompData));
  761. if (!aot_init_memories(comp_data, module)
  762. || !aot_init_memory_segments(comp_data, module)
  763. || !aot_init_tables(comp_data, module)
  764. || !aot_init_table_segments(comp_data, module)
  765. || !aot_init_globals(comp_data, module, gc_enabled,
  766. &import_global_data_size_64bit,
  767. &import_global_data_size_32bit,
  768. &global_data_size_64bit, &global_data_size_32bit)
  769. || !aot_init_types(comp_data, module, is_target_x86, gc_enabled)
  770. || !aot_init_functions(comp_data, module, is_64bit_target)) {
  771. goto fail;
  772. }
  773. #if WASM_ENABLE_CUSTOM_NAME_SECTION != 0
  774. comp_data->name_section_buf = module->name_section_buf;
  775. comp_data->name_section_buf_end = module->name_section_buf_end;
  776. #endif
  777. #if WASM_ENABLE_BRANCH_HINTS != 0
  778. comp_data->function_hints = module->function_hints;
  779. #endif
  780. aot_init_aux_data(comp_data, module);
  781. comp_data->wasm_module = module;
  782. return comp_data;
  783. fail:
  784. aot_destroy_comp_data(comp_data);
  785. return NULL;
  786. }
  787. void
  788. aot_destroy_comp_data(AOTCompData *comp_data)
  789. {
  790. if (!comp_data)
  791. return;
  792. if (comp_data->import_memories)
  793. wasm_runtime_free(comp_data->import_memories);
  794. if (comp_data->memories)
  795. wasm_runtime_free(comp_data->memories);
  796. if (comp_data->mem_init_data_list)
  797. aot_destroy_mem_init_data_list(comp_data->mem_init_data_list,
  798. comp_data->mem_init_data_count);
  799. if (comp_data->import_tables)
  800. wasm_runtime_free(comp_data->import_tables);
  801. if (comp_data->tables)
  802. wasm_runtime_free(comp_data->tables);
  803. if (comp_data->table_init_data_list)
  804. aot_destroy_table_init_data_list(comp_data->table_init_data_list,
  805. comp_data->table_init_data_count);
  806. if (comp_data->import_globals)
  807. wasm_runtime_free(comp_data->import_globals);
  808. if (comp_data->globals)
  809. wasm_runtime_free(comp_data->globals);
  810. if (comp_data->import_funcs)
  811. wasm_runtime_free(comp_data->import_funcs);
  812. if (comp_data->funcs)
  813. aot_destroy_funcs(comp_data->funcs, comp_data->func_count);
  814. if (comp_data->aot_name_section_buf)
  815. wasm_runtime_free(comp_data->aot_name_section_buf);
  816. wasm_runtime_free(comp_data);
  817. }