aot_llvm.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #ifndef _AOT_LLVM_H_
  6. #define _AOT_LLVM_H_
  7. #include "aot.h"
  8. #include "llvm/Config/llvm-config.h"
  9. #include "llvm-c/Types.h"
  10. #include "llvm-c/Target.h"
  11. #include "llvm-c/Core.h"
  12. #include "llvm-c/Object.h"
  13. #include "llvm-c/ExecutionEngine.h"
  14. #include "llvm-c/Analysis.h"
  15. #include "llvm-c/BitWriter.h"
  16. #include "llvm-c/Transforms/Utils.h"
  17. #include "llvm-c/Transforms/Scalar.h"
  18. #include "llvm-c/Transforms/Vectorize.h"
  19. #include "llvm-c/Transforms/PassManagerBuilder.h"
  20. #include "llvm-c/Orc.h"
  21. #include "llvm-c/Error.h"
  22. #include "llvm-c/Support.h"
  23. #include "llvm-c/Initialization.h"
  24. #include "llvm-c/TargetMachine.h"
  25. #include "llvm-c/LLJIT.h"
  26. #if WASM_ENABLE_DEBUG_AOT != 0
  27. #include "llvm-c/DebugInfo.h"
  28. #endif
  29. #include "aot_orc_extra.h"
  30. #ifdef __cplusplus
  31. extern "C" {
  32. #endif
  33. #if LLVM_VERSION_MAJOR < 14
  34. #define LLVMBuildLoad2(builder, type, value, name) \
  35. LLVMBuildLoad(builder, value, name)
  36. #define LLVMBuildCall2(builder, type, func, args, num_args, name) \
  37. LLVMBuildCall(builder, func, args, num_args, name)
  38. #define LLVMBuildInBoundsGEP2(builder, type, ptr, indices, num_indices, name) \
  39. LLVMBuildInBoundsGEP(builder, ptr, indices, num_indices, name)
  40. #else
  41. /* Opaque pointer type */
  42. #define OPQ_PTR_TYPE INT8_PTR_TYPE
  43. #endif
  44. #ifndef NDEBUG
  45. #undef DEBUG_PASS
  46. #undef DUMP_MODULE
  47. // #define DEBUG_PASS
  48. // #define DUMP_MODULE
  49. #else
  50. #undef DEBUG_PASS
  51. #undef DUMP_MODULE
  52. #endif
  53. /**
  54. * Value in the WASM operation stack, each stack element
  55. * is an LLVM value
  56. */
  57. typedef struct AOTValue {
  58. struct AOTValue *next;
  59. struct AOTValue *prev;
  60. LLVMValueRef value;
  61. /* VALUE_TYPE_I32/I64/F32/F64/VOID */
  62. uint8 type;
  63. bool is_local;
  64. uint32 local_idx;
  65. } AOTValue;
  66. /**
  67. * Value stack, represents stack elements in a WASM block
  68. */
  69. typedef struct AOTValueStack {
  70. AOTValue *value_list_head;
  71. AOTValue *value_list_end;
  72. } AOTValueStack;
  73. typedef struct AOTBlock {
  74. struct AOTBlock *next;
  75. struct AOTBlock *prev;
  76. /* Block index */
  77. uint32 block_index;
  78. /* LABEL_TYPE_BLOCK/LOOP/IF/FUNCTION */
  79. uint32 label_type;
  80. /* Whether it is reachable */
  81. bool is_reachable;
  82. /* Whether skip translation of wasm else branch */
  83. bool skip_wasm_code_else;
  84. /* code of else opcode of this block, if it is a IF block */
  85. uint8 *wasm_code_else;
  86. /* code end of this block */
  87. uint8 *wasm_code_end;
  88. /* LLVM label points to code begin */
  89. LLVMBasicBlockRef llvm_entry_block;
  90. /* LLVM label points to code else */
  91. LLVMBasicBlockRef llvm_else_block;
  92. /* LLVM label points to code end */
  93. LLVMBasicBlockRef llvm_end_block;
  94. /* WASM operation stack */
  95. AOTValueStack value_stack;
  96. /* Param count/types/PHIs of this block */
  97. uint32 param_count;
  98. uint8 *param_types;
  99. LLVMValueRef *param_phis;
  100. LLVMValueRef *else_param_phis;
  101. /* Result count/types/PHIs of this block */
  102. uint32 result_count;
  103. uint8 *result_types;
  104. LLVMValueRef *result_phis;
  105. } AOTBlock;
  106. /**
  107. * Block stack, represents WASM block stack elements
  108. */
  109. typedef struct AOTBlockStack {
  110. AOTBlock *block_list_head;
  111. AOTBlock *block_list_end;
  112. /* Current block index of each block type */
  113. uint32 block_index[3];
  114. } AOTBlockStack;
  115. typedef struct AOTCheckedAddr {
  116. struct AOTCheckedAddr *next;
  117. uint32 local_idx;
  118. uint32 offset;
  119. uint32 bytes;
  120. } AOTCheckedAddr, *AOTCheckedAddrList;
  121. typedef struct AOTMemInfo {
  122. LLVMValueRef mem_base_addr;
  123. LLVMValueRef mem_data_size_addr;
  124. LLVMValueRef mem_cur_page_count_addr;
  125. LLVMValueRef mem_bound_check_1byte;
  126. LLVMValueRef mem_bound_check_2bytes;
  127. LLVMValueRef mem_bound_check_4bytes;
  128. LLVMValueRef mem_bound_check_8bytes;
  129. LLVMValueRef mem_bound_check_16bytes;
  130. } AOTMemInfo;
  131. typedef struct AOTFuncContext {
  132. AOTFunc *aot_func;
  133. LLVMValueRef func;
  134. LLVMValueRef precheck_func;
  135. LLVMTypeRef func_type;
  136. LLVMModuleRef module;
  137. AOTBlockStack block_stack;
  138. LLVMValueRef exec_env;
  139. LLVMValueRef aot_inst;
  140. LLVMValueRef argv_buf;
  141. LLVMValueRef native_stack_bound;
  142. LLVMValueRef native_stack_top_min_addr;
  143. LLVMValueRef aux_stack_bound;
  144. LLVMValueRef aux_stack_bottom;
  145. LLVMValueRef native_symbol;
  146. LLVMValueRef func_ptrs;
  147. AOTMemInfo *mem_info;
  148. LLVMValueRef cur_exception;
  149. bool mem_space_unchanged;
  150. AOTCheckedAddrList checked_addr_list;
  151. LLVMBasicBlockRef got_exception_block;
  152. LLVMBasicBlockRef func_return_block;
  153. LLVMValueRef exception_id_phi;
  154. LLVMValueRef func_type_indexes;
  155. #if WASM_ENABLE_DEBUG_AOT != 0
  156. LLVMMetadataRef debug_func;
  157. #endif
  158. unsigned int stack_consumption_for_func_call;
  159. LLVMValueRef locals[1];
  160. } AOTFuncContext;
  161. typedef struct AOTLLVMTypes {
  162. LLVMTypeRef int1_type;
  163. LLVMTypeRef int8_type;
  164. LLVMTypeRef int16_type;
  165. LLVMTypeRef int32_type;
  166. LLVMTypeRef int64_type;
  167. LLVMTypeRef float32_type;
  168. LLVMTypeRef float64_type;
  169. LLVMTypeRef void_type;
  170. LLVMTypeRef int8_ptr_type;
  171. LLVMTypeRef int8_pptr_type;
  172. LLVMTypeRef int16_ptr_type;
  173. LLVMTypeRef int32_ptr_type;
  174. LLVMTypeRef int64_ptr_type;
  175. LLVMTypeRef float32_ptr_type;
  176. LLVMTypeRef float64_ptr_type;
  177. LLVMTypeRef v128_type;
  178. LLVMTypeRef v128_ptr_type;
  179. LLVMTypeRef i8x16_vec_type;
  180. LLVMTypeRef i16x8_vec_type;
  181. LLVMTypeRef i32x4_vec_type;
  182. LLVMTypeRef i64x2_vec_type;
  183. LLVMTypeRef f32x4_vec_type;
  184. LLVMTypeRef f64x2_vec_type;
  185. LLVMTypeRef int8_ptr_type_gs;
  186. LLVMTypeRef int16_ptr_type_gs;
  187. LLVMTypeRef int32_ptr_type_gs;
  188. LLVMTypeRef int64_ptr_type_gs;
  189. LLVMTypeRef float32_ptr_type_gs;
  190. LLVMTypeRef float64_ptr_type_gs;
  191. LLVMTypeRef v128_ptr_type_gs;
  192. LLVMTypeRef i1x2_vec_type;
  193. LLVMTypeRef meta_data_type;
  194. LLVMTypeRef funcref_type;
  195. LLVMTypeRef externref_type;
  196. } AOTLLVMTypes;
  197. typedef struct AOTLLVMConsts {
  198. LLVMValueRef i1_zero;
  199. LLVMValueRef i1_one;
  200. LLVMValueRef i8_zero;
  201. LLVMValueRef i32_zero;
  202. LLVMValueRef i64_zero;
  203. LLVMValueRef f32_zero;
  204. LLVMValueRef f64_zero;
  205. LLVMValueRef i32_one;
  206. LLVMValueRef i32_two;
  207. LLVMValueRef i32_three;
  208. LLVMValueRef i32_four;
  209. LLVMValueRef i32_five;
  210. LLVMValueRef i32_six;
  211. LLVMValueRef i32_seven;
  212. LLVMValueRef i32_eight;
  213. LLVMValueRef i32_nine;
  214. LLVMValueRef i32_ten;
  215. LLVMValueRef i32_eleven;
  216. LLVMValueRef i32_twelve;
  217. LLVMValueRef i32_thirteen;
  218. LLVMValueRef i32_fourteen;
  219. LLVMValueRef i32_fifteen;
  220. LLVMValueRef i32_neg_one;
  221. LLVMValueRef i64_neg_one;
  222. LLVMValueRef i32_min;
  223. LLVMValueRef i64_min;
  224. LLVMValueRef i32_31;
  225. LLVMValueRef i32_32;
  226. LLVMValueRef i64_63;
  227. LLVMValueRef i64_64;
  228. LLVMValueRef i8x16_vec_zero;
  229. LLVMValueRef i16x8_vec_zero;
  230. LLVMValueRef i32x4_vec_zero;
  231. LLVMValueRef i64x2_vec_zero;
  232. LLVMValueRef f32x4_vec_zero;
  233. LLVMValueRef f64x2_vec_zero;
  234. LLVMValueRef i8x16_undef;
  235. LLVMValueRef i16x8_undef;
  236. LLVMValueRef i32x4_undef;
  237. LLVMValueRef i64x2_undef;
  238. LLVMValueRef f32x4_undef;
  239. LLVMValueRef f64x2_undef;
  240. LLVMValueRef i32x16_zero;
  241. LLVMValueRef i32x8_zero;
  242. LLVMValueRef i32x4_zero;
  243. LLVMValueRef i32x2_zero;
  244. } AOTLLVMConsts;
  245. /**
  246. * Compiler context
  247. */
  248. typedef struct AOTCompContext {
  249. const AOTCompData *comp_data;
  250. /* LLVM variables required to emit LLVM IR */
  251. LLVMContextRef context;
  252. LLVMBuilderRef builder;
  253. #if WASM_ENABLE_DEBUG_AOT
  254. LLVMDIBuilderRef debug_builder;
  255. LLVMMetadataRef debug_file;
  256. LLVMMetadataRef debug_comp_unit;
  257. #endif
  258. LLVMTargetMachineRef target_machine;
  259. char *target_cpu;
  260. char target_arch[16];
  261. unsigned pointer_size;
  262. /* Hardware intrinsic compability flags */
  263. uint64 flags[8];
  264. /* required by JIT */
  265. LLVMOrcLLLazyJITRef orc_jit;
  266. LLVMOrcThreadSafeContextRef orc_thread_safe_context;
  267. LLVMModuleRef module;
  268. bool is_jit_mode;
  269. /* AOT indirect mode flag & symbol list */
  270. bool is_indirect_mode;
  271. bh_list native_symbols;
  272. /* Bulk memory feature */
  273. bool enable_bulk_memory;
  274. /* Bounday Check */
  275. bool enable_bound_check;
  276. /* Native stack bounday Check */
  277. bool enable_stack_bound_check;
  278. /* Native stack usage estimation */
  279. bool enable_stack_estimation;
  280. /* 128-bit SIMD */
  281. bool enable_simd;
  282. /* Auxiliary stack overflow/underflow check */
  283. bool enable_aux_stack_check;
  284. /* Generate auxiliary stack frame */
  285. bool enable_aux_stack_frame;
  286. /* Thread Manager */
  287. bool enable_thread_mgr;
  288. /* Tail Call */
  289. bool enable_tail_call;
  290. /* Reference Types */
  291. bool enable_ref_types;
  292. /* Disable LLVM built-in intrinsics */
  293. bool disable_llvm_intrinsics;
  294. /* Disable LLVM link time optimization */
  295. bool disable_llvm_lto;
  296. /* Enable LLVM PGO (Profile-Guided Optimization) */
  297. bool enable_llvm_pgo;
  298. /* Use profile file collected by LLVM PGO */
  299. char *use_prof_file;
  300. /* Enable to use segument register as the base addr
  301. of linear memory for load/store operations */
  302. bool enable_segue_i32_load;
  303. bool enable_segue_i64_load;
  304. bool enable_segue_f32_load;
  305. bool enable_segue_f64_load;
  306. bool enable_segue_v128_load;
  307. bool enable_segue_i32_store;
  308. bool enable_segue_i64_store;
  309. bool enable_segue_f32_store;
  310. bool enable_segue_f64_store;
  311. bool enable_segue_v128_store;
  312. /* Whether optimize the JITed code */
  313. bool optimize;
  314. uint32 opt_level;
  315. uint32 size_level;
  316. /* LLVM floating-point rounding mode metadata */
  317. LLVMValueRef fp_rounding_mode;
  318. /* LLVM floating-point exception behavior metadata */
  319. LLVMValueRef fp_exception_behavior;
  320. /* a global array to store stack sizes */
  321. LLVMTypeRef stack_sizes_type;
  322. LLVMValueRef stack_sizes;
  323. uint32 *jit_stack_sizes; /* for JIT */
  324. /* LLVM data types */
  325. AOTLLVMTypes basic_types;
  326. LLVMTypeRef exec_env_type;
  327. LLVMTypeRef aot_inst_type;
  328. /* LLVM const values */
  329. AOTLLVMConsts llvm_consts;
  330. /* Function contexts */
  331. /* TODO: */
  332. AOTFuncContext **func_ctxes;
  333. uint32 func_ctx_count;
  334. char **custom_sections_wp;
  335. uint32 custom_sections_count;
  336. /* 3rd-party toolchains */
  337. /* External llc compiler, if specified, wamrc will emit the llvm-ir file and
  338. * invoke the llc compiler to generate object file.
  339. * This can be used when we want to benefit from the optimization of other
  340. * LLVM based toolchains */
  341. const char *external_llc_compiler;
  342. const char *llc_compiler_flags;
  343. /* External asm compiler, if specified, wamrc will emit the text-based
  344. * assembly file (.s) and invoke the llc compiler to generate object file.
  345. * This will be useful when the upstream LLVM doesn't support to emit object
  346. * file for some architecture (such as arc) */
  347. const char *external_asm_compiler;
  348. const char *asm_compiler_flags;
  349. const char *stack_usage_file;
  350. char stack_usage_temp_file[64];
  351. const char *llvm_passes;
  352. const char *builtin_intrinsics;
  353. } AOTCompContext;
  354. enum {
  355. AOT_FORMAT_FILE,
  356. AOT_OBJECT_FILE,
  357. AOT_LLVMIR_UNOPT_FILE,
  358. AOT_LLVMIR_OPT_FILE,
  359. };
  360. typedef struct AOTCompOption {
  361. bool is_jit_mode;
  362. bool is_indirect_mode;
  363. char *target_arch;
  364. char *target_abi;
  365. char *target_cpu;
  366. char *cpu_features;
  367. bool is_sgx_platform;
  368. bool enable_bulk_memory;
  369. bool enable_thread_mgr;
  370. bool enable_tail_call;
  371. bool enable_simd;
  372. bool enable_ref_types;
  373. bool enable_aux_stack_check;
  374. bool enable_aux_stack_frame;
  375. bool disable_llvm_intrinsics;
  376. bool disable_llvm_lto;
  377. bool enable_llvm_pgo;
  378. bool enable_stack_estimation;
  379. char *use_prof_file;
  380. uint32 opt_level;
  381. uint32 size_level;
  382. uint32 output_format;
  383. uint32 bounds_checks;
  384. uint32 stack_bounds_checks;
  385. uint32 segue_flags;
  386. char **custom_sections;
  387. uint32 custom_sections_count;
  388. const char *stack_usage_file;
  389. const char *llvm_passes;
  390. const char *builtin_intrinsics;
  391. } AOTCompOption, *aot_comp_option_t;
  392. bool
  393. aot_compiler_init(void);
  394. void
  395. aot_compiler_destroy(void);
  396. AOTCompContext *
  397. aot_create_comp_context(const AOTCompData *comp_data, aot_comp_option_t option);
  398. void
  399. aot_destroy_comp_context(AOTCompContext *comp_ctx);
  400. int32
  401. aot_get_native_symbol_index(AOTCompContext *comp_ctx, const char *symbol);
  402. bool
  403. aot_compile_wasm(AOTCompContext *comp_ctx);
  404. uint8 *
  405. aot_emit_elf_file(AOTCompContext *comp_ctx, uint32 *p_elf_file_size);
  406. void
  407. aot_destroy_elf_file(uint8 *elf_file);
  408. void
  409. aot_value_stack_push(AOTValueStack *stack, AOTValue *value);
  410. AOTValue *
  411. aot_value_stack_pop(AOTValueStack *stack);
  412. void
  413. aot_value_stack_destroy(AOTValueStack *stack);
  414. void
  415. aot_block_stack_push(AOTBlockStack *stack, AOTBlock *block);
  416. AOTBlock *
  417. aot_block_stack_pop(AOTBlockStack *stack);
  418. void
  419. aot_block_stack_destroy(AOTBlockStack *stack);
  420. void
  421. aot_block_destroy(AOTBlock *block);
  422. LLVMTypeRef
  423. wasm_type_to_llvm_type(const AOTLLVMTypes *llvm_types, uint8 wasm_type);
  424. bool
  425. aot_checked_addr_list_add(AOTFuncContext *func_ctx, uint32 local_idx,
  426. uint32 offset, uint32 bytes);
  427. void
  428. aot_checked_addr_list_del(AOTFuncContext *func_ctx, uint32 local_idx);
  429. bool
  430. aot_checked_addr_list_find(AOTFuncContext *func_ctx, uint32 local_idx,
  431. uint32 offset, uint32 bytes);
  432. void
  433. aot_checked_addr_list_destroy(AOTFuncContext *func_ctx);
  434. bool
  435. aot_build_zero_function_ret(const AOTCompContext *comp_ctx,
  436. AOTFuncContext *func_ctx, AOTFuncType *func_type);
  437. LLVMValueRef
  438. aot_call_llvm_intrinsic(const AOTCompContext *comp_ctx,
  439. const AOTFuncContext *func_ctx, const char *intrinsic,
  440. LLVMTypeRef ret_type, LLVMTypeRef *param_types,
  441. int param_count, ...);
  442. LLVMValueRef
  443. aot_call_llvm_intrinsic_v(const AOTCompContext *comp_ctx,
  444. const AOTFuncContext *func_ctx, const char *intrinsic,
  445. LLVMTypeRef ret_type, LLVMTypeRef *param_types,
  446. int param_count, va_list param_value_list);
  447. LLVMValueRef
  448. aot_get_func_from_table(const AOTCompContext *comp_ctx, LLVMValueRef base,
  449. LLVMTypeRef func_type, int32 index);
  450. LLVMValueRef
  451. aot_load_const_from_table(AOTCompContext *comp_ctx, LLVMValueRef base,
  452. const WASMValue *value, uint8 value_type);
  453. bool
  454. aot_check_simd_compatibility(const char *arch_c_str, const char *cpu_c_str);
  455. void
  456. aot_add_expand_memory_op_pass(LLVMPassManagerRef pass);
  457. void
  458. aot_add_simple_loop_unswitch_pass(LLVMPassManagerRef pass);
  459. void
  460. aot_apply_llvm_new_pass_manager(AOTCompContext *comp_ctx, LLVMModuleRef module);
  461. void
  462. aot_handle_llvm_errmsg(const char *string, LLVMErrorRef err);
  463. char *
  464. aot_compress_aot_func_names(AOTCompContext *comp_ctx, uint32 *p_size);
  465. bool
  466. aot_set_cond_br_weights(AOTCompContext *comp_ctx, LLVMValueRef cond_br,
  467. int32 weights_true, int32 weights_false);
  468. bool
  469. aot_target_precheck_can_use_musttail(const AOTCompContext *comp_ctx);
  470. unsigned int
  471. aot_estimate_stack_usage_for_function_call(const AOTCompContext *comp_ctx,
  472. const AOTFuncType *callee_func_type);
  473. #ifdef __cplusplus
  474. } /* end of extern "C" */
  475. #endif
  476. #endif /* end of _AOT_LLVM_H_ */