aot_compiler.h 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790
  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. bool
  175. aot_frame_store_value(AOTCompContext *comp_ctx, LLVMValueRef value,
  176. uint8 value_type, LLVMValueRef cur_frame, uint32 offset);
  177. static inline void
  178. push_32bit(AOTCompFrame *frame, AOTValue *aot_value)
  179. {
  180. frame->sp->value = aot_value->value;
  181. frame->sp->type = aot_value->type;
  182. frame->sp->dirty = 1;
  183. frame->sp++;
  184. }
  185. static inline void
  186. push_64bit(AOTCompFrame *frame, AOTValue *aot_value)
  187. {
  188. push_32bit(frame, aot_value);
  189. push_32bit(frame, aot_value);
  190. }
  191. static inline void
  192. push_i32(AOTCompFrame *frame, AOTValue *aot_value)
  193. {
  194. bh_assert(aot_value->type == VALUE_TYPE_I32
  195. || aot_value->type == VALUE_TYPE_I1);
  196. push_32bit(frame, aot_value);
  197. }
  198. static inline void
  199. push_i64(AOTCompFrame *frame, AOTValue *aot_value)
  200. {
  201. bh_assert(aot_value->type == VALUE_TYPE_I64);
  202. push_64bit(frame, aot_value);
  203. }
  204. static inline void
  205. push_f32(AOTCompFrame *frame, AOTValue *aot_value)
  206. {
  207. bh_assert(aot_value->type == VALUE_TYPE_F32);
  208. push_32bit(frame, aot_value);
  209. }
  210. static inline void
  211. push_f64(AOTCompFrame *frame, AOTValue *aot_value)
  212. {
  213. bh_assert(aot_value->type == VALUE_TYPE_F64);
  214. push_64bit(frame, aot_value);
  215. }
  216. static inline void
  217. push_v128(AOTCompFrame *frame, AOTValue *aot_value)
  218. {
  219. bh_assert(aot_value->type == VALUE_TYPE_V128);
  220. push_64bit(frame, aot_value);
  221. push_64bit(frame, aot_value);
  222. }
  223. static inline void
  224. push_ref(AOTCompFrame *frame, AOTValue *aot_value)
  225. {
  226. bh_assert(frame->comp_ctx->enable_ref_types);
  227. push_32bit(frame, aot_value);
  228. }
  229. #if WASM_ENABLE_GC != 0
  230. static inline void
  231. push_gc_ref(AOTCompFrame *frame, AOTValue *aot_value)
  232. {
  233. bh_assert(frame->comp_ctx->enable_gc);
  234. bh_assert(aot_value->type == VALUE_TYPE_GC_REF);
  235. if (frame->comp_ctx->pointer_size == sizeof(uint64)) {
  236. push_64bit(frame, aot_value);
  237. (frame->sp - 1)->ref = (frame->sp - 2)->ref = 1;
  238. }
  239. else {
  240. push_32bit(frame, aot_value);
  241. (frame->sp - 1)->ref = 1;
  242. }
  243. }
  244. #endif
  245. /* Clear value slots except ref and committed_ref */
  246. static inline void
  247. clear_frame_value_slots(AOTValueSlot *slots, uint32 n)
  248. {
  249. uint32 i;
  250. for (i = 0; i < n; i++) {
  251. slots[i].value = 0;
  252. slots[i].type = 0;
  253. slots[i].dirty = 0;
  254. }
  255. }
  256. static inline void
  257. pop_i32(AOTCompFrame *frame)
  258. {
  259. bh_assert(frame->sp - frame->lp >= 1);
  260. bh_assert((frame->sp - 1)->type == VALUE_TYPE_I32
  261. || (frame->sp - 1)->type == VALUE_TYPE_I1);
  262. frame->sp--;
  263. clear_frame_value_slots(frame->sp, 1);
  264. }
  265. static inline void
  266. pop_i64(AOTCompFrame *frame)
  267. {
  268. bh_assert(frame->sp - frame->lp >= 2);
  269. bh_assert((frame->sp - 1)->type == VALUE_TYPE_I64
  270. && (frame->sp - 2)->type == VALUE_TYPE_I64);
  271. frame->sp -= 2;
  272. clear_frame_value_slots(frame->sp, 2);
  273. }
  274. static inline void
  275. pop_f32(AOTCompFrame *frame)
  276. {
  277. bh_assert(frame->sp - frame->lp >= 1);
  278. bh_assert((frame->sp - 1)->type == VALUE_TYPE_F32);
  279. frame->sp--;
  280. clear_frame_value_slots(frame->sp, 1);
  281. }
  282. static inline void
  283. pop_f64(AOTCompFrame *frame)
  284. {
  285. bh_assert(frame->sp - frame->lp >= 2);
  286. bh_assert((frame->sp - 1)->type == VALUE_TYPE_F64
  287. && (frame->sp - 2)->type == VALUE_TYPE_F64);
  288. frame->sp -= 2;
  289. clear_frame_value_slots(frame->sp, 2);
  290. }
  291. static inline void
  292. pop_v128(AOTCompFrame *frame)
  293. {
  294. bh_assert(frame->sp - frame->lp >= 4);
  295. bh_assert((frame->sp - 1)->type == VALUE_TYPE_V128
  296. && (frame->sp - 2)->type == VALUE_TYPE_V128
  297. && (frame->sp - 3)->type == VALUE_TYPE_V128
  298. && (frame->sp - 4)->type == VALUE_TYPE_V128);
  299. frame->sp -= 4;
  300. clear_frame_value_slots(frame->sp, 4);
  301. }
  302. static inline void
  303. pop_ref(AOTCompFrame *frame)
  304. {
  305. bh_assert(frame->sp - frame->lp >= 1);
  306. bh_assert((frame->sp - 1)->type == VALUE_TYPE_FUNCREF
  307. || (frame->sp - 1)->type == VALUE_TYPE_EXTERNREF);
  308. frame->sp -= 1;
  309. clear_frame_value_slots(frame->sp, 1);
  310. }
  311. #if WASM_ENABLE_GC != 0
  312. static inline void
  313. pop_gc_ref(AOTCompFrame *frame)
  314. {
  315. bh_assert(frame->sp - frame->lp >= 1);
  316. bh_assert((frame->sp - 1)->type == VALUE_TYPE_GC_REF);
  317. frame->sp -= 1;
  318. clear_frame_value_slots(frame->sp, 1);
  319. frame->sp->ref = 0;
  320. if (frame->comp_ctx->pointer_size == sizeof(uint64)) {
  321. bh_assert(frame->sp - frame->lp >= 1);
  322. bh_assert((frame->sp - 1)->type == VALUE_TYPE_GC_REF);
  323. frame->sp -= 1;
  324. clear_frame_value_slots(frame->sp, 1);
  325. frame->sp->ref = 0;
  326. }
  327. }
  328. #endif
  329. static inline void
  330. set_local_i32(AOTCompFrame *frame, int n, LLVMValueRef value)
  331. {
  332. frame->lp[n].value = value;
  333. frame->lp[n].type = VALUE_TYPE_I32;
  334. frame->lp[n].dirty = 1;
  335. }
  336. static inline void
  337. set_local_i64(AOTCompFrame *frame, int n, LLVMValueRef value)
  338. {
  339. frame->lp[n].value = value;
  340. frame->lp[n].type = VALUE_TYPE_I64;
  341. frame->lp[n].dirty = 1;
  342. frame->lp[n + 1].value = value;
  343. frame->lp[n + 1].type = VALUE_TYPE_I64;
  344. frame->lp[n + 1].dirty = 1;
  345. }
  346. static inline void
  347. set_local_f32(AOTCompFrame *frame, int n, LLVMValueRef value)
  348. {
  349. frame->lp[n].value = value;
  350. frame->lp[n].type = VALUE_TYPE_F32;
  351. frame->lp[n].dirty = 1;
  352. }
  353. static inline void
  354. set_local_f64(AOTCompFrame *frame, int n, LLVMValueRef value)
  355. {
  356. frame->lp[n].value = value;
  357. frame->lp[n].type = VALUE_TYPE_F64;
  358. frame->lp[n].dirty = 1;
  359. frame->lp[n + 1].value = value;
  360. frame->lp[n + 1].type = VALUE_TYPE_F64;
  361. frame->lp[n + 1].dirty = 1;
  362. }
  363. static inline void
  364. set_local_v128(AOTCompFrame *frame, int n, LLVMValueRef value)
  365. {
  366. uint32 i;
  367. for (i = 0; i < 4; i++) {
  368. frame->lp[n + i].value = value;
  369. frame->lp[n + i].type = VALUE_TYPE_V128;
  370. frame->lp[n + i].dirty = 1;
  371. }
  372. }
  373. static inline void
  374. set_local_ref(AOTCompFrame *frame, int n, LLVMValueRef value, uint8 ref_type)
  375. {
  376. bh_assert(frame->comp_ctx->enable_ref_types);
  377. frame->lp[n].value = value;
  378. frame->lp[n].type = ref_type;
  379. frame->lp[n].dirty = 1;
  380. }
  381. #if WASM_ENABLE_GC != 0
  382. static inline void
  383. set_local_gc_ref(AOTCompFrame *frame, int n, LLVMValueRef value, uint8 ref_type)
  384. {
  385. bh_assert(frame->comp_ctx->enable_gc);
  386. bh_assert(ref_type == VALUE_TYPE_GC_REF);
  387. frame->lp[n].value = value;
  388. frame->lp[n].type = ref_type;
  389. frame->lp[n].dirty = 1;
  390. frame->lp[n].ref = 1;
  391. if (frame->comp_ctx->pointer_size == sizeof(uint64)) {
  392. frame->lp[n + 1].value = value;
  393. frame->lp[n + 1].type = ref_type;
  394. frame->lp[n + 1].dirty = 1;
  395. frame->lp[n + 1].ref = 1;
  396. }
  397. }
  398. #endif
  399. #define CHECK_STACK() \
  400. do { \
  401. if (!func_ctx->block_stack.block_list_end) { \
  402. aot_set_last_error("WASM block stack underflow."); \
  403. goto fail; \
  404. } \
  405. if (!func_ctx->block_stack.block_list_end->value_stack \
  406. .value_list_end) { \
  407. aot_set_last_error("WASM data stack underflow."); \
  408. goto fail; \
  409. } \
  410. } while (0)
  411. #if WASM_ENABLE_GC != 0
  412. #define GET_GC_REF_FROM_STACK(llvm_value) \
  413. do { \
  414. AOTValue *aot_value; \
  415. CHECK_STACK(); \
  416. aot_value = \
  417. func_ctx->block_stack.block_list_end->value_stack.value_list_end; \
  418. if (aot_value->type != VALUE_TYPE_GC_REF) { \
  419. aot_set_last_error("WASM stack data type is not reference"); \
  420. goto fail; \
  421. } \
  422. llvm_value = aot_value->value; \
  423. } while (0)
  424. #endif
  425. #define POP(llvm_value, value_type) \
  426. do { \
  427. AOTValue *aot_value; \
  428. uint8 val_type_to_pop = value_type; \
  429. CHECK_STACK(); \
  430. aot_value = aot_value_stack_pop( \
  431. comp_ctx, &func_ctx->block_stack.block_list_end->value_stack); \
  432. if (comp_ctx->enable_gc && aot_is_type_gc_reftype(value_type)) \
  433. val_type_to_pop = VALUE_TYPE_GC_REF; \
  434. if (!check_type_compatible(comp_ctx, aot_value->type, \
  435. val_type_to_pop)) { \
  436. aot_set_last_error("invalid WASM stack data type."); \
  437. wasm_runtime_free(aot_value); \
  438. goto fail; \
  439. } \
  440. if (aot_value->type == val_type_to_pop) \
  441. llvm_value = aot_value->value; \
  442. else { \
  443. if (aot_value->type == VALUE_TYPE_I1) { \
  444. if (!(llvm_value = \
  445. LLVMBuildZExt(comp_ctx->builder, aot_value->value, \
  446. I32_TYPE, "i1toi32"))) { \
  447. aot_set_last_error("invalid WASM stack data type."); \
  448. wasm_runtime_free(aot_value); \
  449. goto fail; \
  450. } \
  451. } \
  452. else { \
  453. bh_assert( \
  454. aot_value->type == VALUE_TYPE_I32 \
  455. || (comp_ctx->enable_ref_types \
  456. && (aot_value->type == VALUE_TYPE_FUNCREF \
  457. || aot_value->type == VALUE_TYPE_EXTERNREF))); \
  458. bh_assert( \
  459. val_type_to_pop == VALUE_TYPE_I32 \
  460. || (comp_ctx->enable_ref_types \
  461. && (val_type_to_pop == VALUE_TYPE_FUNCREF \
  462. || val_type_to_pop == VALUE_TYPE_EXTERNREF))); \
  463. llvm_value = aot_value->value; \
  464. } \
  465. } \
  466. wasm_runtime_free(aot_value); \
  467. } while (0)
  468. #define POP_I32(v) POP(v, VALUE_TYPE_I32)
  469. #define POP_I64(v) POP(v, VALUE_TYPE_I64)
  470. #define POP_F32(v) POP(v, VALUE_TYPE_F32)
  471. #define POP_F64(v) POP(v, VALUE_TYPE_F64)
  472. #define POP_V128(v) POP(v, VALUE_TYPE_V128)
  473. #define POP_FUNCREF(v) POP(v, VALUE_TYPE_FUNCREF)
  474. #define POP_EXTERNREF(v) POP(v, VALUE_TYPE_EXTERNREF)
  475. #define POP_GC_REF(v) POP(v, VALUE_TYPE_GC_REF)
  476. #define POP_COND(llvm_value) \
  477. do { \
  478. AOTValue *aot_value; \
  479. CHECK_STACK(); \
  480. aot_value = aot_value_stack_pop( \
  481. comp_ctx, &func_ctx->block_stack.block_list_end->value_stack); \
  482. if (aot_value->type != VALUE_TYPE_I1 \
  483. && aot_value->type != VALUE_TYPE_I32) { \
  484. aot_set_last_error("invalid WASM stack data type."); \
  485. wasm_runtime_free(aot_value); \
  486. goto fail; \
  487. } \
  488. if (aot_value->type == VALUE_TYPE_I1) \
  489. llvm_value = aot_value->value; \
  490. else { \
  491. if (!(llvm_value = \
  492. LLVMBuildICmp(comp_ctx->builder, LLVMIntNE, \
  493. aot_value->value, I32_ZERO, "i1_cond"))) { \
  494. aot_set_last_error("llvm build trunc failed."); \
  495. wasm_runtime_free(aot_value); \
  496. goto fail; \
  497. } \
  498. } \
  499. wasm_runtime_free(aot_value); \
  500. } while (0)
  501. #define PUSH(llvm_value, value_type) \
  502. do { \
  503. AOTValue *aot_value; \
  504. if (!func_ctx->block_stack.block_list_end) { \
  505. aot_set_last_error("WASM block stack underflow."); \
  506. goto fail; \
  507. } \
  508. aot_value = wasm_runtime_malloc(sizeof(AOTValue)); \
  509. if (!aot_value) { \
  510. aot_set_last_error("allocate memory failed."); \
  511. goto fail; \
  512. } \
  513. memset(aot_value, 0, sizeof(AOTValue)); \
  514. if (comp_ctx->enable_gc && aot_is_type_gc_reftype(value_type)) \
  515. aot_value->type = VALUE_TYPE_GC_REF; \
  516. else if (comp_ctx->enable_ref_types \
  517. && (value_type == VALUE_TYPE_FUNCREF \
  518. || value_type == VALUE_TYPE_EXTERNREF)) \
  519. aot_value->type = VALUE_TYPE_I32; \
  520. else \
  521. aot_value->type = value_type; \
  522. aot_value->value = llvm_value; \
  523. aot_value_stack_push( \
  524. comp_ctx, &func_ctx->block_stack.block_list_end->value_stack, \
  525. aot_value); \
  526. } while (0)
  527. #define PUSH_I32(v) PUSH(v, VALUE_TYPE_I32)
  528. #define PUSH_I64(v) PUSH(v, VALUE_TYPE_I64)
  529. #define PUSH_F32(v) PUSH(v, VALUE_TYPE_F32)
  530. #define PUSH_F64(v) PUSH(v, VALUE_TYPE_F64)
  531. #define PUSH_V128(v) PUSH(v, VALUE_TYPE_V128)
  532. #define PUSH_COND(v) PUSH(v, VALUE_TYPE_I1)
  533. #define PUSH_FUNCREF(v) PUSH(v, VALUE_TYPE_FUNCREF)
  534. #define PUSH_EXTERNREF(v) PUSH(v, VALUE_TYPE_EXTERNREF)
  535. #define PUSH_GC_REF(v) PUSH(v, VALUE_TYPE_GC_REF)
  536. #define TO_LLVM_TYPE(wasm_type) \
  537. wasm_type_to_llvm_type(comp_ctx, &comp_ctx->basic_types, wasm_type)
  538. #define I32_TYPE comp_ctx->basic_types.int32_type
  539. #define I64_TYPE comp_ctx->basic_types.int64_type
  540. #define F32_TYPE comp_ctx->basic_types.float32_type
  541. #define F64_TYPE comp_ctx->basic_types.float64_type
  542. #define VOID_TYPE comp_ctx->basic_types.void_type
  543. #define INT1_TYPE comp_ctx->basic_types.int1_type
  544. #define INT8_TYPE comp_ctx->basic_types.int8_type
  545. #define INT16_TYPE comp_ctx->basic_types.int16_type
  546. #define INTPTR_T_TYPE comp_ctx->basic_types.intptr_t_type
  547. #define SIZE_T_TYPE comp_ctx->basic_types.size_t_type
  548. #define MD_TYPE comp_ctx->basic_types.meta_data_type
  549. #define INT8_PTR_TYPE comp_ctx->basic_types.int8_ptr_type
  550. #define INT16_PTR_TYPE comp_ctx->basic_types.int16_ptr_type
  551. #define INT32_PTR_TYPE comp_ctx->basic_types.int32_ptr_type
  552. #define INT64_PTR_TYPE comp_ctx->basic_types.int64_ptr_type
  553. #define INTPTR_T_PTR_TYPE comp_ctx->basic_types.intptr_t_ptr_type
  554. #define F32_PTR_TYPE comp_ctx->basic_types.float32_ptr_type
  555. #define F64_PTR_TYPE comp_ctx->basic_types.float64_ptr_type
  556. #define FUNC_REF_TYPE comp_ctx->basic_types.funcref_type
  557. #define EXTERN_REF_TYPE comp_ctx->basic_types.externref_type
  558. #define GC_REF_TYPE comp_ctx->basic_types.gc_ref_type
  559. #define GC_REF_PTR_TYPE comp_ctx->basic_types.gc_ref_ptr_type
  560. #define INT8_PTR_TYPE_GS comp_ctx->basic_types.int8_ptr_type_gs
  561. #define INT16_PTR_TYPE_GS comp_ctx->basic_types.int16_ptr_type_gs
  562. #define INT32_PTR_TYPE_GS comp_ctx->basic_types.int32_ptr_type_gs
  563. #define INT64_PTR_TYPE_GS comp_ctx->basic_types.int64_ptr_type_gs
  564. #define F32_PTR_TYPE_GS comp_ctx->basic_types.float32_ptr_type_gs
  565. #define F64_PTR_TYPE_GS comp_ctx->basic_types.float64_ptr_type_gs
  566. #define I32_CONST(v) LLVMConstInt(I32_TYPE, v, true)
  567. #define I64_CONST(v) LLVMConstInt(I64_TYPE, v, true)
  568. #define F32_CONST(v) LLVMConstReal(F32_TYPE, v)
  569. #define F64_CONST(v) LLVMConstReal(F64_TYPE, v)
  570. #define I8_CONST(v) LLVMConstInt(INT8_TYPE, v, true)
  571. #define LLVM_CONST(name) (comp_ctx->llvm_consts.name)
  572. #define I1_ZERO LLVM_CONST(i1_zero)
  573. #define I1_ONE LLVM_CONST(i1_one)
  574. #define I8_ZERO LLVM_CONST(i8_zero)
  575. #define I8_ONE LLVM_CONST(i8_one)
  576. #define I32_ZERO LLVM_CONST(i32_zero)
  577. #define I64_ZERO LLVM_CONST(i64_zero)
  578. #define F32_ZERO LLVM_CONST(f32_zero)
  579. #define F64_ZERO LLVM_CONST(f64_zero)
  580. #define I32_ONE LLVM_CONST(i32_one)
  581. #define I32_TWO LLVM_CONST(i32_two)
  582. #define I32_THREE LLVM_CONST(i32_three)
  583. #define I32_FOUR LLVM_CONST(i32_four)
  584. #define I32_FIVE LLVM_CONST(i32_five)
  585. #define I32_SIX LLVM_CONST(i32_six)
  586. #define I32_SEVEN LLVM_CONST(i32_seven)
  587. #define I32_EIGHT LLVM_CONST(i32_eight)
  588. #define I32_NINE LLVM_CONST(i32_nine)
  589. #define I32_TEN LLVM_CONST(i32_ten)
  590. #define I32_ELEVEN LLVM_CONST(i32_eleven)
  591. #define I32_TWELVE LLVM_CONST(i32_twelve)
  592. #define I32_NEG_ONE LLVM_CONST(i32_neg_one)
  593. #define I64_NEG_ONE LLVM_CONST(i64_neg_one)
  594. #define I32_MIN LLVM_CONST(i32_min)
  595. #define I64_MIN LLVM_CONST(i64_min)
  596. #define I32_31 LLVM_CONST(i32_31)
  597. #define I32_32 LLVM_CONST(i32_32)
  598. #define I64_63 LLVM_CONST(i64_63)
  599. #define I64_64 LLVM_CONST(i64_64)
  600. #define REF_NULL I32_NEG_ONE
  601. #define GC_REF_NULL LLVM_CONST(gc_ref_null)
  602. #define I8_PTR_NULL LLVM_CONST(i8_ptr_null)
  603. #define V128_TYPE comp_ctx->basic_types.v128_type
  604. #define V128_PTR_TYPE comp_ctx->basic_types.v128_ptr_type
  605. #define V128_PTR_TYPE_GS comp_ctx->basic_types.v128_ptr_type_gs
  606. #define V128_i8x16_TYPE comp_ctx->basic_types.i8x16_vec_type
  607. #define V128_i16x8_TYPE comp_ctx->basic_types.i16x8_vec_type
  608. #define V128_i32x4_TYPE comp_ctx->basic_types.i32x4_vec_type
  609. #define V128_i64x2_TYPE comp_ctx->basic_types.i64x2_vec_type
  610. #define V128_f32x4_TYPE comp_ctx->basic_types.f32x4_vec_type
  611. #define V128_f64x2_TYPE comp_ctx->basic_types.f64x2_vec_type
  612. #define V128_i8x16_ZERO LLVM_CONST(i8x16_vec_zero)
  613. #define V128_i16x8_ZERO LLVM_CONST(i16x8_vec_zero)
  614. #define V128_i32x4_ZERO LLVM_CONST(i32x4_vec_zero)
  615. #define V128_i64x2_ZERO LLVM_CONST(i64x2_vec_zero)
  616. #define V128_f32x4_ZERO LLVM_CONST(f32x4_vec_zero)
  617. #define V128_f64x2_ZERO LLVM_CONST(f64x2_vec_zero)
  618. #define TO_V128_i8x16(v) \
  619. LLVMBuildBitCast(comp_ctx->builder, v, V128_i8x16_TYPE, "i8x16_val")
  620. #define TO_V128_i16x8(v) \
  621. LLVMBuildBitCast(comp_ctx->builder, v, V128_i16x8_TYPE, "i16x8_val")
  622. #define TO_V128_i32x4(v) \
  623. LLVMBuildBitCast(comp_ctx->builder, v, V128_i32x4_TYPE, "i32x4_val")
  624. #define TO_V128_i64x2(v) \
  625. LLVMBuildBitCast(comp_ctx->builder, v, V128_i64x2_TYPE, "i64x2_val")
  626. #define TO_V128_f32x4(v) \
  627. LLVMBuildBitCast(comp_ctx->builder, v, V128_f32x4_TYPE, "f32x4_val")
  628. #define TO_V128_f64x2(v) \
  629. LLVMBuildBitCast(comp_ctx->builder, v, V128_f64x2_TYPE, "f64x2_val")
  630. #define CHECK_LLVM_CONST(v) \
  631. do { \
  632. if (!v) { \
  633. aot_set_last_error("create llvm const failed."); \
  634. goto fail; \
  635. } \
  636. } while (0)
  637. #define GET_AOT_FUNCTION(name, argc) \
  638. do { \
  639. if (!(func_type = \
  640. LLVMFunctionType(ret_type, param_types, argc, false))) { \
  641. aot_set_last_error("llvm add function type failed."); \
  642. goto fail; \
  643. } \
  644. if (comp_ctx->is_jit_mode) { \
  645. /* JIT mode, call the function directly */ \
  646. if (!(func_ptr_type = LLVMPointerType(func_type, 0))) { \
  647. aot_set_last_error("llvm add pointer type failed."); \
  648. goto fail; \
  649. } \
  650. if (!(value = I64_CONST((uint64)(uintptr_t)name)) \
  651. || !(func = LLVMConstIntToPtr(value, func_ptr_type))) { \
  652. aot_set_last_error("create LLVM value failed."); \
  653. goto fail; \
  654. } \
  655. } \
  656. else if (comp_ctx->is_indirect_mode) { \
  657. int32 func_index; \
  658. if (!(func_ptr_type = LLVMPointerType(func_type, 0))) { \
  659. aot_set_last_error("create LLVM function type failed."); \
  660. goto fail; \
  661. } \
  662. \
  663. func_index = aot_get_native_symbol_index(comp_ctx, #name); \
  664. if (func_index < 0) { \
  665. goto fail; \
  666. } \
  667. if (!(func = aot_get_func_from_table( \
  668. comp_ctx, func_ctx->native_symbol, func_ptr_type, \
  669. func_index))) { \
  670. goto fail; \
  671. } \
  672. } \
  673. else { \
  674. char *func_name = #name; \
  675. /* AOT mode, delcare the function */ \
  676. if (!(func = LLVMGetNamedFunction(func_ctx->module, func_name)) \
  677. && !(func = LLVMAddFunction(func_ctx->module, func_name, \
  678. func_type))) { \
  679. aot_set_last_error("llvm add function failed."); \
  680. goto fail; \
  681. } \
  682. } \
  683. } while (0)
  684. /* if val is a constant integer and its value is not undef or poison */
  685. static inline bool
  686. LLVMIsEfficientConstInt(LLVMValueRef val)
  687. {
  688. return LLVMIsConstant(val)
  689. && LLVMGetValueKind(val) == LLVMConstantIntValueKind
  690. && !LLVMIsUndef(val)
  691. #if LLVM_VERSION_NUMBER >= 12
  692. && !LLVMIsPoison(addr)
  693. #endif
  694. ;
  695. }
  696. bool
  697. aot_compile_wasm(AOTCompContext *comp_ctx);
  698. bool
  699. aot_emit_llvm_file(AOTCompContext *comp_ctx, const char *file_name);
  700. bool
  701. aot_emit_aot_file(AOTCompContext *comp_ctx, AOTCompData *comp_data,
  702. const char *file_name);
  703. uint8 *
  704. aot_emit_aot_file_buf(AOTCompContext *comp_ctx, AOTCompData *comp_data,
  705. uint32 *p_aot_file_size);
  706. bool
  707. aot_emit_object_file(AOTCompContext *comp_ctx, char *file_name);
  708. char *
  709. aot_generate_tempfile_name(const char *prefix, const char *extension,
  710. char *buffer, uint32 len);
  711. #ifdef __cplusplus
  712. } /* end of extern "C" */
  713. #endif
  714. #endif /* end of _AOT_COMPILER_H_ */