aot_compiler.h 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #ifndef _AOT_COMPILER_H_
  6. #define _AOT_COMPILER_H_
  7. #include "aot.h"
  8. #include "aot_llvm.h"
  9. #include "../interpreter/wasm_interp.h"
  10. #include "../aot/aot_runtime.h"
  11. #ifdef __cplusplus
  12. extern "C" {
  13. #endif
  14. typedef AOTIntCond IntCond;
  15. typedef AOTFloatCond FloatCond;
  16. typedef enum IntArithmetic {
  17. INT_ADD = 0,
  18. INT_SUB,
  19. INT_MUL,
  20. INT_DIV_S,
  21. INT_DIV_U,
  22. INT_REM_S,
  23. INT_REM_U
  24. } IntArithmetic;
  25. typedef enum V128Arithmetic {
  26. V128_ADD = 0,
  27. V128_SUB,
  28. V128_MUL,
  29. V128_DIV,
  30. V128_NEG,
  31. V128_MIN,
  32. V128_MAX,
  33. } V128Arithmetic;
  34. typedef enum IntBitwise {
  35. INT_AND = 0,
  36. INT_OR,
  37. INT_XOR,
  38. } IntBitwise;
  39. typedef enum V128Bitwise {
  40. V128_NOT,
  41. V128_AND,
  42. V128_ANDNOT,
  43. V128_OR,
  44. V128_XOR,
  45. V128_BITSELECT,
  46. } V128Bitwise;
  47. typedef enum IntShift {
  48. INT_SHL = 0,
  49. INT_SHR_S,
  50. INT_SHR_U,
  51. INT_ROTL,
  52. INT_ROTR
  53. } IntShift;
  54. typedef enum FloatMath {
  55. FLOAT_ABS = 0,
  56. FLOAT_NEG,
  57. FLOAT_CEIL,
  58. FLOAT_FLOOR,
  59. FLOAT_TRUNC,
  60. FLOAT_NEAREST,
  61. FLOAT_SQRT
  62. } FloatMath;
  63. typedef enum FloatArithmetic {
  64. FLOAT_ADD = 0,
  65. FLOAT_SUB,
  66. FLOAT_MUL,
  67. FLOAT_DIV,
  68. FLOAT_MIN,
  69. FLOAT_MAX,
  70. } FloatArithmetic;
  71. /**
  72. * Check whether a value type is a GC reference type,
  73. * don't use wasm_is_type_reftype since it requires
  74. * GC feature and may result in compilation error when
  75. * GC feature isn't compiled
  76. */
  77. static inline bool
  78. aot_is_type_gc_reftype(uint8 type)
  79. {
  80. return ((type >= (uint8)REF_TYPE_ARRAYREF
  81. && type <= (uint8)REF_TYPE_NULLFUNCREF)
  82. || (type >= (uint8)REF_TYPE_HT_NULLABLE
  83. && type <= (uint8)REF_TYPE_HT_NON_NULLABLE)
  84. #if WASM_ENABLE_STRINGREF != 0
  85. || (type >= (uint8)REF_TYPE_STRINGVIEWWTF8
  86. && type <= (uint8)REF_TYPE_STRINGREF)
  87. || (type >= (uint8)REF_TYPE_STRINGVIEWITER
  88. && type <= (uint8)REF_TYPE_STRINGVIEWWTF16)
  89. #endif
  90. )
  91. ? true
  92. : false;
  93. }
  94. static inline bool
  95. check_type_compatible(const AOTCompContext *comp_ctx, uint8 src_type,
  96. uint8 dst_type)
  97. {
  98. if (src_type == dst_type) {
  99. return true;
  100. }
  101. /* ext i1 to i32 */
  102. if (src_type == VALUE_TYPE_I1 && dst_type == VALUE_TYPE_I32) {
  103. return true;
  104. }
  105. /* i32 <==> func.ref, i32 <==> extern.ref */
  106. if (src_type == VALUE_TYPE_I32
  107. && (comp_ctx->enable_ref_types
  108. && (dst_type == VALUE_TYPE_EXTERNREF
  109. || dst_type == VALUE_TYPE_FUNCREF))) {
  110. return true;
  111. }
  112. if (dst_type == VALUE_TYPE_I32
  113. && (comp_ctx->enable_ref_types
  114. && (src_type == VALUE_TYPE_FUNCREF
  115. || src_type == VALUE_TYPE_EXTERNREF))) {
  116. return true;
  117. }
  118. return false;
  119. }
  120. /**
  121. * Operations for AOTCompFrame
  122. */
  123. /**
  124. * Get the offset from frame pointer to the n-th local variable slot.
  125. *
  126. * @param n the index to the local variable array
  127. *
  128. * @return the offset from frame pointer to the local variable slot
  129. */
  130. static inline uint32
  131. offset_of_local(AOTCompContext *comp_ctx, unsigned n)
  132. {
  133. if (!comp_ctx->is_jit_mode)
  134. /* In AOTFrame, there are 7 pointers before field lp */
  135. return comp_ctx->pointer_size
  136. * (offsetof(AOTFrame, lp) / sizeof(uintptr_t))
  137. + sizeof(uint32) * n;
  138. else
  139. return offsetof(WASMInterpFrame, lp) + sizeof(uint32) * n;
  140. }
  141. uint32
  142. offset_of_local_in_outs_area(AOTCompContext *comp_ctx, unsigned n);
  143. /**
  144. * Get the offset from frame pointer to the n-th local variable's
  145. * reference flag slot.
  146. *
  147. * @param n the index to the local variable array
  148. *
  149. * @return the offset from frame pointer to the local variable slot
  150. */
  151. static inline unsigned
  152. offset_of_ref(AOTCompContext *comp_ctx, unsigned n)
  153. {
  154. AOTCompFrame *frame = comp_ctx->aot_frame;
  155. uint32 all_cell_num = frame->max_local_cell_num + frame->max_stack_cell_num;
  156. return offset_of_local(comp_ctx, all_cell_num) + n;
  157. }
  158. /**
  159. * Generate instructions to commit computation result to the frame.
  160. * The general principle is to only commit values that will be used
  161. * through the frame.
  162. *
  163. * @param frame the frame information
  164. */
  165. bool
  166. aot_gen_commit_values(AOTCompFrame *frame);
  167. /**
  168. * Generate instructions to commit SP and IP pointers to the frame.
  169. *
  170. * @param frame the frame information
  171. */
  172. bool
  173. aot_gen_commit_sp_ip(AOTCompFrame *frame, bool commit_sp, bool commit_ip);
  174. /**
  175. * Generate instructions to commit IP pointer to the frame.
  176. *
  177. * @param frame the frame information
  178. */
  179. bool
  180. aot_gen_commit_ip(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  181. LLVMValueRef ip_value, bool is_64bit);
  182. bool
  183. aot_frame_store_value(AOTCompContext *comp_ctx, LLVMValueRef value,
  184. uint8 value_type, LLVMValueRef cur_frame, uint32 offset);
  185. static inline void
  186. push_32bit(AOTCompFrame *frame, AOTValue *aot_value)
  187. {
  188. frame->sp->value = aot_value->value;
  189. frame->sp->type = aot_value->type;
  190. frame->sp->dirty = 1;
  191. frame->sp++;
  192. }
  193. static inline void
  194. push_64bit(AOTCompFrame *frame, AOTValue *aot_value)
  195. {
  196. push_32bit(frame, aot_value);
  197. push_32bit(frame, aot_value);
  198. }
  199. static inline void
  200. push_i32(AOTCompFrame *frame, AOTValue *aot_value)
  201. {
  202. bh_assert(aot_value->type == VALUE_TYPE_I32
  203. || aot_value->type == VALUE_TYPE_I1);
  204. push_32bit(frame, aot_value);
  205. }
  206. static inline void
  207. push_i64(AOTCompFrame *frame, AOTValue *aot_value)
  208. {
  209. bh_assert(aot_value->type == VALUE_TYPE_I64);
  210. push_64bit(frame, aot_value);
  211. }
  212. static inline void
  213. push_f32(AOTCompFrame *frame, AOTValue *aot_value)
  214. {
  215. bh_assert(aot_value->type == VALUE_TYPE_F32);
  216. push_32bit(frame, aot_value);
  217. }
  218. static inline void
  219. push_f64(AOTCompFrame *frame, AOTValue *aot_value)
  220. {
  221. bh_assert(aot_value->type == VALUE_TYPE_F64);
  222. push_64bit(frame, aot_value);
  223. }
  224. static inline void
  225. push_v128(AOTCompFrame *frame, AOTValue *aot_value)
  226. {
  227. bh_assert(aot_value->type == VALUE_TYPE_V128);
  228. push_64bit(frame, aot_value);
  229. push_64bit(frame, aot_value);
  230. }
  231. static inline void
  232. push_ref(AOTCompFrame *frame, AOTValue *aot_value)
  233. {
  234. bh_assert(frame->comp_ctx->enable_ref_types);
  235. push_32bit(frame, aot_value);
  236. }
  237. #if WASM_ENABLE_GC != 0
  238. static inline void
  239. push_gc_ref(AOTCompFrame *frame, AOTValue *aot_value)
  240. {
  241. bh_assert(frame->comp_ctx->enable_gc);
  242. bh_assert(aot_value->type == VALUE_TYPE_GC_REF);
  243. if (frame->comp_ctx->pointer_size == sizeof(uint64)) {
  244. push_64bit(frame, aot_value);
  245. (frame->sp - 1)->ref = (frame->sp - 2)->ref = 1;
  246. }
  247. else {
  248. push_32bit(frame, aot_value);
  249. (frame->sp - 1)->ref = 1;
  250. }
  251. }
  252. #endif
  253. /* Clear value slots except ref and committed_ref */
  254. static inline void
  255. clear_frame_value_slots(AOTValueSlot *slots, uint32 n)
  256. {
  257. uint32 i;
  258. for (i = 0; i < n; i++) {
  259. slots[i].value = 0;
  260. slots[i].type = 0;
  261. slots[i].dirty = 0;
  262. }
  263. }
  264. static inline void
  265. pop_i32(AOTCompFrame *frame)
  266. {
  267. bh_assert(frame->sp - frame->lp >= 1);
  268. bh_assert((frame->sp - 1)->type == VALUE_TYPE_I32
  269. || (frame->sp - 1)->type == VALUE_TYPE_I1);
  270. frame->sp--;
  271. clear_frame_value_slots(frame->sp, 1);
  272. }
  273. static inline void
  274. pop_i64(AOTCompFrame *frame)
  275. {
  276. bh_assert(frame->sp - frame->lp >= 2);
  277. bh_assert((frame->sp - 1)->type == VALUE_TYPE_I64
  278. && (frame->sp - 2)->type == VALUE_TYPE_I64);
  279. frame->sp -= 2;
  280. clear_frame_value_slots(frame->sp, 2);
  281. }
  282. static inline void
  283. pop_f32(AOTCompFrame *frame)
  284. {
  285. bh_assert(frame->sp - frame->lp >= 1);
  286. bh_assert((frame->sp - 1)->type == VALUE_TYPE_F32);
  287. frame->sp--;
  288. clear_frame_value_slots(frame->sp, 1);
  289. }
  290. static inline void
  291. pop_f64(AOTCompFrame *frame)
  292. {
  293. bh_assert(frame->sp - frame->lp >= 2);
  294. bh_assert((frame->sp - 1)->type == VALUE_TYPE_F64
  295. && (frame->sp - 2)->type == VALUE_TYPE_F64);
  296. frame->sp -= 2;
  297. clear_frame_value_slots(frame->sp, 2);
  298. }
  299. static inline void
  300. pop_v128(AOTCompFrame *frame)
  301. {
  302. bh_assert(frame->sp - frame->lp >= 4);
  303. bh_assert((frame->sp - 1)->type == VALUE_TYPE_V128
  304. && (frame->sp - 2)->type == VALUE_TYPE_V128
  305. && (frame->sp - 3)->type == VALUE_TYPE_V128
  306. && (frame->sp - 4)->type == VALUE_TYPE_V128);
  307. frame->sp -= 4;
  308. clear_frame_value_slots(frame->sp, 4);
  309. }
  310. static inline void
  311. pop_ref(AOTCompFrame *frame)
  312. {
  313. bh_assert(frame->sp - frame->lp >= 1);
  314. bh_assert((frame->sp - 1)->type == VALUE_TYPE_FUNCREF
  315. || (frame->sp - 1)->type == VALUE_TYPE_EXTERNREF);
  316. frame->sp -= 1;
  317. clear_frame_value_slots(frame->sp, 1);
  318. }
  319. #if WASM_ENABLE_GC != 0
  320. static inline void
  321. pop_gc_ref(AOTCompFrame *frame)
  322. {
  323. bh_assert(frame->sp - frame->lp >= 1);
  324. bh_assert((frame->sp - 1)->type == VALUE_TYPE_GC_REF);
  325. frame->sp -= 1;
  326. clear_frame_value_slots(frame->sp, 1);
  327. frame->sp->ref = 0;
  328. if (frame->comp_ctx->pointer_size == sizeof(uint64)) {
  329. bh_assert(frame->sp - frame->lp >= 1);
  330. bh_assert((frame->sp - 1)->type == VALUE_TYPE_GC_REF);
  331. frame->sp -= 1;
  332. clear_frame_value_slots(frame->sp, 1);
  333. frame->sp->ref = 0;
  334. }
  335. }
  336. #endif
  337. static inline void
  338. set_local_i32(AOTCompFrame *frame, int n, LLVMValueRef value)
  339. {
  340. frame->lp[n].value = value;
  341. frame->lp[n].type = VALUE_TYPE_I32;
  342. frame->lp[n].dirty = 1;
  343. }
  344. static inline void
  345. set_local_i64(AOTCompFrame *frame, int n, LLVMValueRef value)
  346. {
  347. frame->lp[n].value = value;
  348. frame->lp[n].type = VALUE_TYPE_I64;
  349. frame->lp[n].dirty = 1;
  350. frame->lp[n + 1].value = value;
  351. frame->lp[n + 1].type = VALUE_TYPE_I64;
  352. frame->lp[n + 1].dirty = 1;
  353. }
  354. static inline void
  355. set_local_f32(AOTCompFrame *frame, int n, LLVMValueRef value)
  356. {
  357. frame->lp[n].value = value;
  358. frame->lp[n].type = VALUE_TYPE_F32;
  359. frame->lp[n].dirty = 1;
  360. }
  361. static inline void
  362. set_local_f64(AOTCompFrame *frame, int n, LLVMValueRef value)
  363. {
  364. frame->lp[n].value = value;
  365. frame->lp[n].type = VALUE_TYPE_F64;
  366. frame->lp[n].dirty = 1;
  367. frame->lp[n + 1].value = value;
  368. frame->lp[n + 1].type = VALUE_TYPE_F64;
  369. frame->lp[n + 1].dirty = 1;
  370. }
  371. static inline void
  372. set_local_v128(AOTCompFrame *frame, int n, LLVMValueRef value)
  373. {
  374. uint32 i;
  375. for (i = 0; i < 4; i++) {
  376. frame->lp[n + i].value = value;
  377. frame->lp[n + i].type = VALUE_TYPE_V128;
  378. frame->lp[n + i].dirty = 1;
  379. }
  380. }
  381. static inline void
  382. set_local_ref(AOTCompFrame *frame, int n, LLVMValueRef value, uint8 ref_type)
  383. {
  384. bh_assert(frame->comp_ctx->enable_ref_types);
  385. frame->lp[n].value = value;
  386. frame->lp[n].type = ref_type;
  387. frame->lp[n].dirty = 1;
  388. }
  389. #if WASM_ENABLE_GC != 0
  390. static inline void
  391. set_local_gc_ref(AOTCompFrame *frame, int n, LLVMValueRef value, uint8 ref_type)
  392. {
  393. bh_assert(frame->comp_ctx->enable_gc);
  394. bh_assert(ref_type == VALUE_TYPE_GC_REF);
  395. frame->lp[n].value = value;
  396. frame->lp[n].type = ref_type;
  397. frame->lp[n].dirty = 1;
  398. frame->lp[n].ref = 1;
  399. if (frame->comp_ctx->pointer_size == sizeof(uint64)) {
  400. frame->lp[n + 1].value = value;
  401. frame->lp[n + 1].type = ref_type;
  402. frame->lp[n + 1].dirty = 1;
  403. frame->lp[n + 1].ref = 1;
  404. }
  405. }
  406. #endif
  407. #define CHECK_STACK() \
  408. do { \
  409. if (!func_ctx->block_stack.block_list_end) { \
  410. aot_set_last_error("WASM block stack underflow."); \
  411. goto fail; \
  412. } \
  413. if (!func_ctx->block_stack.block_list_end->value_stack \
  414. .value_list_end) { \
  415. aot_set_last_error("WASM data stack underflow."); \
  416. goto fail; \
  417. } \
  418. } while (0)
  419. #if WASM_ENABLE_GC != 0
  420. #define GET_GC_REF_FROM_STACK(llvm_value) \
  421. do { \
  422. AOTValue *aot_value; \
  423. CHECK_STACK(); \
  424. aot_value = \
  425. func_ctx->block_stack.block_list_end->value_stack.value_list_end; \
  426. if (aot_value->type != VALUE_TYPE_GC_REF) { \
  427. aot_set_last_error("WASM stack data type is not reference"); \
  428. goto fail; \
  429. } \
  430. llvm_value = aot_value->value; \
  431. } while (0)
  432. #endif
  433. #define POP(llvm_value, value_type) \
  434. do { \
  435. AOTValue *aot_value; \
  436. uint8 val_type_to_pop = value_type; \
  437. CHECK_STACK(); \
  438. aot_value = aot_value_stack_pop( \
  439. comp_ctx, &func_ctx->block_stack.block_list_end->value_stack); \
  440. if (comp_ctx->enable_gc && aot_is_type_gc_reftype(value_type)) \
  441. val_type_to_pop = VALUE_TYPE_GC_REF; \
  442. if (!check_type_compatible(comp_ctx, aot_value->type, \
  443. val_type_to_pop)) { \
  444. aot_set_last_error("invalid WASM stack data type."); \
  445. wasm_runtime_free(aot_value); \
  446. goto fail; \
  447. } \
  448. if (aot_value->type == val_type_to_pop) \
  449. llvm_value = aot_value->value; \
  450. else { \
  451. if (aot_value->type == VALUE_TYPE_I1) { \
  452. if (!(llvm_value = \
  453. LLVMBuildZExt(comp_ctx->builder, aot_value->value, \
  454. I32_TYPE, "i1toi32"))) { \
  455. aot_set_last_error("invalid WASM stack data type."); \
  456. wasm_runtime_free(aot_value); \
  457. goto fail; \
  458. } \
  459. } \
  460. else { \
  461. bh_assert( \
  462. aot_value->type == VALUE_TYPE_I32 \
  463. || (comp_ctx->enable_ref_types \
  464. && (aot_value->type == VALUE_TYPE_FUNCREF \
  465. || aot_value->type == VALUE_TYPE_EXTERNREF))); \
  466. bh_assert( \
  467. val_type_to_pop == VALUE_TYPE_I32 \
  468. || (comp_ctx->enable_ref_types \
  469. && (val_type_to_pop == VALUE_TYPE_FUNCREF \
  470. || val_type_to_pop == VALUE_TYPE_EXTERNREF))); \
  471. llvm_value = aot_value->value; \
  472. } \
  473. } \
  474. wasm_runtime_free(aot_value); \
  475. } while (0)
  476. #if WASM_ENABLE_MEMORY64 != 0
  477. #define IS_MEMORY64 (comp_ctx->comp_data->memories[0].flags & MEMORY64_FLAG)
  478. #define MEMORY64_COND_VALUE(VAL_IF_ENABLED, VAL_IF_DISABLED) \
  479. (IS_MEMORY64 ? VAL_IF_ENABLED : VAL_IF_DISABLED)
  480. #define IS_TABLE64(i) \
  481. (comp_ctx->comp_data->tables[i].table_type.flags & TABLE64_FLAG)
  482. #define TABLE64_COND_VALUE(i, VAL_IF_ENABLED, VAL_IF_DISABLED) \
  483. (IS_TABLE64(i) ? VAL_IF_ENABLED : VAL_IF_DISABLED)
  484. #else
  485. #define MEMORY64_COND_VALUE(VAL_IF_ENABLED, VAL_IF_DISABLED) (VAL_IF_DISABLED)
  486. #define TABLE64_COND_VALUE(i, VAL_IF_ENABLED, VAL_IF_DISABLED) (VAL_IF_DISABLED)
  487. #endif
  488. #define POP_I32(v) POP(v, VALUE_TYPE_I32)
  489. #define POP_I64(v) POP(v, VALUE_TYPE_I64)
  490. #define POP_F32(v) POP(v, VALUE_TYPE_F32)
  491. #define POP_F64(v) POP(v, VALUE_TYPE_F64)
  492. #define POP_V128(v) POP(v, VALUE_TYPE_V128)
  493. #define POP_FUNCREF(v) POP(v, VALUE_TYPE_FUNCREF)
  494. #define POP_EXTERNREF(v) POP(v, VALUE_TYPE_EXTERNREF)
  495. #define POP_GC_REF(v) POP(v, VALUE_TYPE_GC_REF)
  496. #define POP_MEM_OFFSET(v) \
  497. POP(v, MEMORY64_COND_VALUE(VALUE_TYPE_I64, VALUE_TYPE_I32))
  498. #define POP_PAGE_COUNT(v) \
  499. POP(v, MEMORY64_COND_VALUE(VALUE_TYPE_I64, VALUE_TYPE_I32))
  500. #define POP_TBL_ELEM_IDX(v) \
  501. POP(v, TABLE64_COND_VALUE(tbl_idx, VALUE_TYPE_I64, VALUE_TYPE_I32))
  502. #define POP_TBL_ELEM_LEN(v) POP_TBL_ELEM_IDX(v)
  503. #define POP_COND(llvm_value) \
  504. do { \
  505. AOTValue *aot_value; \
  506. CHECK_STACK(); \
  507. aot_value = aot_value_stack_pop( \
  508. comp_ctx, &func_ctx->block_stack.block_list_end->value_stack); \
  509. if (aot_value->type != VALUE_TYPE_I1 \
  510. && aot_value->type != VALUE_TYPE_I32) { \
  511. aot_set_last_error("invalid WASM stack data type."); \
  512. wasm_runtime_free(aot_value); \
  513. goto fail; \
  514. } \
  515. if (aot_value->type == VALUE_TYPE_I1) \
  516. llvm_value = aot_value->value; \
  517. else { \
  518. if (!(llvm_value = \
  519. LLVMBuildICmp(comp_ctx->builder, LLVMIntNE, \
  520. aot_value->value, I32_ZERO, "i1_cond"))) { \
  521. aot_set_last_error("llvm build trunc failed."); \
  522. wasm_runtime_free(aot_value); \
  523. goto fail; \
  524. } \
  525. } \
  526. wasm_runtime_free(aot_value); \
  527. } while (0)
  528. #define PUSH(llvm_value, value_type) \
  529. do { \
  530. AOTValue *aot_value; \
  531. if (!func_ctx->block_stack.block_list_end) { \
  532. aot_set_last_error("WASM block stack underflow."); \
  533. goto fail; \
  534. } \
  535. aot_value = wasm_runtime_malloc(sizeof(AOTValue)); \
  536. if (!aot_value) { \
  537. aot_set_last_error("allocate memory failed."); \
  538. goto fail; \
  539. } \
  540. memset(aot_value, 0, sizeof(AOTValue)); \
  541. if (comp_ctx->enable_gc && aot_is_type_gc_reftype(value_type)) \
  542. aot_value->type = VALUE_TYPE_GC_REF; \
  543. else if (comp_ctx->enable_ref_types \
  544. && (value_type == VALUE_TYPE_FUNCREF \
  545. || value_type == VALUE_TYPE_EXTERNREF)) \
  546. aot_value->type = VALUE_TYPE_I32; \
  547. else \
  548. aot_value->type = value_type; \
  549. aot_value->value = llvm_value; \
  550. aot_value_stack_push( \
  551. comp_ctx, &func_ctx->block_stack.block_list_end->value_stack, \
  552. aot_value); \
  553. } while (0)
  554. #define PUSH_I32(v) PUSH(v, VALUE_TYPE_I32)
  555. #define PUSH_I64(v) PUSH(v, VALUE_TYPE_I64)
  556. #define PUSH_F32(v) PUSH(v, VALUE_TYPE_F32)
  557. #define PUSH_F64(v) PUSH(v, VALUE_TYPE_F64)
  558. #define PUSH_V128(v) PUSH(v, VALUE_TYPE_V128)
  559. #define PUSH_COND(v) PUSH(v, VALUE_TYPE_I1)
  560. #define PUSH_FUNCREF(v) PUSH(v, VALUE_TYPE_FUNCREF)
  561. #define PUSH_EXTERNREF(v) PUSH(v, VALUE_TYPE_EXTERNREF)
  562. #define PUSH_GC_REF(v) PUSH(v, VALUE_TYPE_GC_REF)
  563. #define PUSH_PAGE_COUNT(v) \
  564. PUSH(v, MEMORY64_COND_VALUE(VALUE_TYPE_I64, VALUE_TYPE_I32))
  565. #define PUSH_TBL_ELEM_IDX(v) \
  566. PUSH(v, TABLE64_COND_VALUE(tbl_idx, VALUE_TYPE_I64, VALUE_TYPE_I32))
  567. #define PUSH_TBL_ELEM_LEN(v) PUSH_TBL_ELEM_IDX(v)
  568. #define SET_CONST(v) \
  569. do { \
  570. AOTValue *aot_value = \
  571. func_ctx->block_stack.block_list_end->value_stack.value_list_end; \
  572. aot_value->is_const = true; \
  573. aot_value->const_value = (v); \
  574. } while (0)
  575. #define TO_LLVM_TYPE(wasm_type) \
  576. wasm_type_to_llvm_type(comp_ctx, &comp_ctx->basic_types, wasm_type)
  577. #define I32_TYPE comp_ctx->basic_types.int32_type
  578. #define I64_TYPE comp_ctx->basic_types.int64_type
  579. #define F32_TYPE comp_ctx->basic_types.float32_type
  580. #define F64_TYPE comp_ctx->basic_types.float64_type
  581. #define VOID_TYPE comp_ctx->basic_types.void_type
  582. #define INT1_TYPE comp_ctx->basic_types.int1_type
  583. #define INT8_TYPE comp_ctx->basic_types.int8_type
  584. #define INT16_TYPE comp_ctx->basic_types.int16_type
  585. #define INTPTR_T_TYPE comp_ctx->basic_types.intptr_t_type
  586. #define SIZE_T_TYPE comp_ctx->basic_types.size_t_type
  587. #define MD_TYPE comp_ctx->basic_types.meta_data_type
  588. #define INT8_PTR_TYPE comp_ctx->basic_types.int8_ptr_type
  589. #define INT16_PTR_TYPE comp_ctx->basic_types.int16_ptr_type
  590. #define INT32_PTR_TYPE comp_ctx->basic_types.int32_ptr_type
  591. #define INT64_PTR_TYPE comp_ctx->basic_types.int64_ptr_type
  592. #define INTPTR_T_PTR_TYPE comp_ctx->basic_types.intptr_t_ptr_type
  593. #define F32_PTR_TYPE comp_ctx->basic_types.float32_ptr_type
  594. #define F64_PTR_TYPE comp_ctx->basic_types.float64_ptr_type
  595. #define FUNC_REF_TYPE comp_ctx->basic_types.funcref_type
  596. #define EXTERN_REF_TYPE comp_ctx->basic_types.externref_type
  597. #define GC_REF_TYPE comp_ctx->basic_types.gc_ref_type
  598. #define GC_REF_PTR_TYPE comp_ctx->basic_types.gc_ref_ptr_type
  599. #define INT8_PTR_TYPE_GS comp_ctx->basic_types.int8_ptr_type_gs
  600. #define INT16_PTR_TYPE_GS comp_ctx->basic_types.int16_ptr_type_gs
  601. #define INT32_PTR_TYPE_GS comp_ctx->basic_types.int32_ptr_type_gs
  602. #define INT64_PTR_TYPE_GS comp_ctx->basic_types.int64_ptr_type_gs
  603. #define F32_PTR_TYPE_GS comp_ctx->basic_types.float32_ptr_type_gs
  604. #define F64_PTR_TYPE_GS comp_ctx->basic_types.float64_ptr_type_gs
  605. #define I32_CONST(v) LLVMConstInt(I32_TYPE, v, true)
  606. #define I64_CONST(v) LLVMConstInt(I64_TYPE, v, true)
  607. #define F32_CONST(v) LLVMConstReal(F32_TYPE, (double)(v))
  608. #define F64_CONST(v) LLVMConstReal(F64_TYPE, v)
  609. #define I8_CONST(v) LLVMConstInt(INT8_TYPE, v, true)
  610. #define INT_CONST(variable, value, type, is_signed) \
  611. do { \
  612. variable = LLVMConstInt(type, value, is_signed); \
  613. if (!variable) { \
  614. aot_set_last_error("llvm build const failed"); \
  615. return false; \
  616. } \
  617. } while (0)
  618. #define LLVM_CONST(name) (comp_ctx->llvm_consts.name)
  619. #define I1_ZERO LLVM_CONST(i1_zero)
  620. #define I1_ONE LLVM_CONST(i1_one)
  621. #define I8_ZERO LLVM_CONST(i8_zero)
  622. #define I8_ONE LLVM_CONST(i8_one)
  623. #define I32_ZERO LLVM_CONST(i32_zero)
  624. #define I64_ZERO LLVM_CONST(i64_zero)
  625. #define F32_ZERO LLVM_CONST(f32_zero)
  626. #define F64_ZERO LLVM_CONST(f64_zero)
  627. #define I32_ONE LLVM_CONST(i32_one)
  628. #define I32_TWO LLVM_CONST(i32_two)
  629. #define I32_THREE LLVM_CONST(i32_three)
  630. #define I32_FOUR LLVM_CONST(i32_four)
  631. #define I32_FIVE LLVM_CONST(i32_five)
  632. #define I32_SIX LLVM_CONST(i32_six)
  633. #define I32_SEVEN LLVM_CONST(i32_seven)
  634. #define I32_EIGHT LLVM_CONST(i32_eight)
  635. #define I32_NINE LLVM_CONST(i32_nine)
  636. #define I32_TEN LLVM_CONST(i32_ten)
  637. #define I32_ELEVEN LLVM_CONST(i32_eleven)
  638. #define I32_TWELVE LLVM_CONST(i32_twelve)
  639. #define I32_NEG_ONE LLVM_CONST(i32_neg_one)
  640. #define I64_NEG_ONE LLVM_CONST(i64_neg_one)
  641. #define I32_MIN LLVM_CONST(i32_min)
  642. #define I64_MIN LLVM_CONST(i64_min)
  643. #define I32_31 LLVM_CONST(i32_31)
  644. #define I32_32 LLVM_CONST(i32_32)
  645. #define I64_63 LLVM_CONST(i64_63)
  646. #define I64_64 LLVM_CONST(i64_64)
  647. #define REF_NULL I32_NEG_ONE
  648. #define GC_REF_NULL LLVM_CONST(gc_ref_null)
  649. #define I8_PTR_NULL LLVM_CONST(i8_ptr_null)
  650. #define V128_TYPE comp_ctx->basic_types.v128_type
  651. #define V128_PTR_TYPE comp_ctx->basic_types.v128_ptr_type
  652. #define V128_PTR_TYPE_GS comp_ctx->basic_types.v128_ptr_type_gs
  653. #define V128_i8x16_TYPE comp_ctx->basic_types.i8x16_vec_type
  654. #define V128_i16x8_TYPE comp_ctx->basic_types.i16x8_vec_type
  655. #define V128_i32x4_TYPE comp_ctx->basic_types.i32x4_vec_type
  656. #define V128_i64x2_TYPE comp_ctx->basic_types.i64x2_vec_type
  657. #define V128_f32x4_TYPE comp_ctx->basic_types.f32x4_vec_type
  658. #define V128_f64x2_TYPE comp_ctx->basic_types.f64x2_vec_type
  659. #define V128_i8x16_ZERO LLVM_CONST(i8x16_vec_zero)
  660. #define V128_i16x8_ZERO LLVM_CONST(i16x8_vec_zero)
  661. #define V128_i32x4_ZERO LLVM_CONST(i32x4_vec_zero)
  662. #define V128_i64x2_ZERO LLVM_CONST(i64x2_vec_zero)
  663. #define V128_f32x4_ZERO LLVM_CONST(f32x4_vec_zero)
  664. #define V128_f64x2_ZERO LLVM_CONST(f64x2_vec_zero)
  665. #define TO_V128_i8x16(v) \
  666. LLVMBuildBitCast(comp_ctx->builder, v, V128_i8x16_TYPE, "i8x16_val")
  667. #define TO_V128_i16x8(v) \
  668. LLVMBuildBitCast(comp_ctx->builder, v, V128_i16x8_TYPE, "i16x8_val")
  669. #define TO_V128_i32x4(v) \
  670. LLVMBuildBitCast(comp_ctx->builder, v, V128_i32x4_TYPE, "i32x4_val")
  671. #define TO_V128_i64x2(v) \
  672. LLVMBuildBitCast(comp_ctx->builder, v, V128_i64x2_TYPE, "i64x2_val")
  673. #define TO_V128_f32x4(v) \
  674. LLVMBuildBitCast(comp_ctx->builder, v, V128_f32x4_TYPE, "f32x4_val")
  675. #define TO_V128_f64x2(v) \
  676. LLVMBuildBitCast(comp_ctx->builder, v, V128_f64x2_TYPE, "f64x2_val")
  677. #define CHECK_LLVM_CONST(v) \
  678. do { \
  679. if (!v) { \
  680. aot_set_last_error("create llvm const failed."); \
  681. goto fail; \
  682. } \
  683. } while (0)
  684. #define GET_AOT_FUNCTION(name, argc) \
  685. do { \
  686. if (!(func_type = \
  687. LLVMFunctionType(ret_type, param_types, argc, false))) { \
  688. aot_set_last_error("llvm add function type failed."); \
  689. goto fail; \
  690. } \
  691. if (comp_ctx->is_jit_mode) { \
  692. /* JIT mode, call the function directly */ \
  693. if (!(func_ptr_type = LLVMPointerType(func_type, 0))) { \
  694. aot_set_last_error("llvm add pointer type failed."); \
  695. goto fail; \
  696. } \
  697. if (!(value = I64_CONST((uint64)(uintptr_t)name)) \
  698. || !(func = LLVMConstIntToPtr(value, func_ptr_type))) { \
  699. aot_set_last_error("create LLVM value failed."); \
  700. goto fail; \
  701. } \
  702. } \
  703. else if (comp_ctx->is_indirect_mode) { \
  704. int32 func_index; \
  705. if (!(func_ptr_type = LLVMPointerType(func_type, 0))) { \
  706. aot_set_last_error("create LLVM function type failed."); \
  707. goto fail; \
  708. } \
  709. \
  710. func_index = aot_get_native_symbol_index(comp_ctx, #name); \
  711. if (func_index < 0) { \
  712. goto fail; \
  713. } \
  714. if (!(func = aot_get_func_from_table( \
  715. comp_ctx, func_ctx->native_symbol, func_ptr_type, \
  716. func_index))) { \
  717. goto fail; \
  718. } \
  719. } \
  720. else { \
  721. char *func_name = #name; \
  722. /* AOT mode, declare the function */ \
  723. if (!(func = LLVMGetNamedFunction(func_ctx->module, func_name)) \
  724. && !(func = LLVMAddFunction(func_ctx->module, func_name, \
  725. func_type))) { \
  726. aot_set_last_error("llvm add function failed."); \
  727. goto fail; \
  728. } \
  729. } \
  730. } while (0)
  731. /* if val is a constant integer and its value is not undef or poison */
  732. static inline bool
  733. LLVMIsEfficientConstInt(LLVMValueRef val)
  734. {
  735. return LLVMIsConstant(val)
  736. && LLVMGetValueKind(val) == LLVMConstantIntValueKind
  737. && !LLVMIsUndef(val)
  738. #if LLVM_VERSION_NUMBER >= 12
  739. && !LLVMIsPoison(addr)
  740. #endif
  741. ;
  742. }
  743. bool
  744. aot_compile_wasm(AOTCompContext *comp_ctx);
  745. bool
  746. aot_emit_llvm_file(AOTCompContext *comp_ctx, const char *file_name);
  747. bool
  748. aot_emit_object_file(AOTCompContext *comp_ctx, char *file_name);
  749. char *
  750. aot_generate_tempfile_name(const char *prefix, const char *extension,
  751. char *buffer, uint32 len);
  752. #ifdef __cplusplus
  753. } /* end of extern "C" */
  754. #endif
  755. #endif /* end of _AOT_COMPILER_H_ */