main.c 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include <stdlib.h>
  6. #include "bh_platform.h"
  7. #include "bh_read_file.h"
  8. #include "wasm_export.h"
  9. #include "aot_export.h"
  10. #include <llvm-c/Core.h>
  11. #include <llvm-c/Support.h>
  12. #if BH_HAS_DLFCN
  13. #include <dlfcn.h>
  14. typedef uint32 (*get_native_lib_func)(char **p_module_name,
  15. NativeSymbol **p_native_symbols);
  16. static uint32
  17. load_and_register_native_libs(const char **native_lib_list,
  18. uint32 native_lib_count,
  19. void **native_handle_list)
  20. {
  21. uint32 i, native_handle_count = 0, n_native_symbols;
  22. NativeSymbol *native_symbols;
  23. char *module_name;
  24. void *handle;
  25. for (i = 0; i < native_lib_count; i++) {
  26. /* open the native library */
  27. if (!(handle = dlopen(native_lib_list[i], RTLD_NOW | RTLD_GLOBAL))
  28. && !(handle = dlopen(native_lib_list[i], RTLD_LAZY))) {
  29. LOG_WARNING("warning: failed to load native library %s",
  30. native_lib_list[i]);
  31. continue;
  32. }
  33. /* lookup get_native_lib func */
  34. get_native_lib_func get_native_lib = dlsym(handle, "get_native_lib");
  35. if (!get_native_lib) {
  36. LOG_WARNING("warning: failed to lookup `get_native_lib` function "
  37. "from native lib %s",
  38. native_lib_list[i]);
  39. dlclose(handle);
  40. continue;
  41. }
  42. n_native_symbols = get_native_lib(&module_name, &native_symbols);
  43. /* register native symbols */
  44. if (!(n_native_symbols > 0 && module_name && native_symbols
  45. && wasm_runtime_register_natives(module_name, native_symbols,
  46. n_native_symbols))) {
  47. LOG_WARNING("warning: failed to register native lib %s",
  48. native_lib_list[i]);
  49. dlclose(handle);
  50. continue;
  51. }
  52. native_handle_list[native_handle_count++] = handle;
  53. }
  54. return native_handle_count;
  55. }
  56. static void
  57. unregister_and_unload_native_libs(uint32 native_lib_count,
  58. void **native_handle_list)
  59. {
  60. uint32 i, n_native_symbols;
  61. NativeSymbol *native_symbols;
  62. char *module_name;
  63. void *handle;
  64. for (i = 0; i < native_lib_count; i++) {
  65. handle = native_handle_list[i];
  66. /* lookup get_native_lib func */
  67. get_native_lib_func get_native_lib = dlsym(handle, "get_native_lib");
  68. if (!get_native_lib) {
  69. LOG_WARNING("warning: failed to lookup `get_native_lib` function "
  70. "from native lib %p",
  71. handle);
  72. continue;
  73. }
  74. n_native_symbols = get_native_lib(&module_name, &native_symbols);
  75. if (n_native_symbols == 0 || module_name == NULL
  76. || native_symbols == NULL) {
  77. LOG_WARNING("warning: get_native_lib returned different values for "
  78. "native lib %p",
  79. handle);
  80. continue;
  81. }
  82. /* unregister native symbols */
  83. if (!wasm_runtime_unregister_natives(module_name, native_symbols)) {
  84. LOG_WARNING("warning: failed to unregister native lib %p", handle);
  85. continue;
  86. }
  87. dlclose(handle);
  88. }
  89. }
  90. #endif
  91. /* clang-format off */
  92. static void
  93. print_help()
  94. {
  95. printf("Usage: wamrc [options] -o output_file wasm_file\n");
  96. printf(" --target=<arch-name> Set the target arch, which has the general format: <arch><sub>\n");
  97. printf(" <arch> = x86_64, i386, aarch64, arm, thumb, xtensa, mips,\n");
  98. printf(" riscv64, riscv32.\n");
  99. printf(" Default is host arch, e.g. x86_64\n");
  100. printf(" <sub> = for ex. on arm or thumb: v5, v6m, v7a, v7m, etc.\n");
  101. printf(" Use --target=help to list supported targets\n");
  102. printf(" Or, provide a triple in the format of <arch>-<vendor>-<os>-<abi>.\n");
  103. printf(" By doing this, --target-abi, --cpu, and --cpu-features will be ignored.\n");
  104. printf(" The triple will only be normalized without any further verification.\n");
  105. printf(" --target-abi=<abi> Set the target ABI, e.g. gnu, eabi, gnueabihf, msvc, etc.\n");
  106. printf(" Default is gnu if target isn't riscv64 or riscv32\n");
  107. printf(" For target riscv64 and riscv32, default is lp64d and ilp32d\n");
  108. printf(" Use --target-abi=help to list all the ABI supported\n");
  109. printf(" --cpu=<cpu> Set the target CPU (default: host CPU, e.g. skylake)\n");
  110. printf(" Use --cpu=help to list all the CPU supported\n");
  111. printf(" --cpu-features=<features> Enable or disable the CPU features\n");
  112. printf(" Use +feature to enable a feature, or -feature to disable it\n");
  113. printf(" For example, --cpu-features=+feature1,-feature2\n");
  114. printf(" Use --cpu-features=+help to list all the features supported\n");
  115. printf(" --opt-level=n Set the optimization level (0 to 3, default is 3)\n");
  116. printf(" --size-level=n Set the code size level (0 to 3, default is 3)\n");
  117. printf(" 0 - Large code model\n");
  118. printf(" 1 - Medium code model\n");
  119. printf(" 2 - Kernel code model\n");
  120. printf(" 3 - Small code model\n");
  121. printf(" -sgx Generate code for SGX platform (Intel Software Guard Extensions)\n");
  122. printf(" --bounds-checks=1/0 Enable or disable the bounds checks for memory access:\n");
  123. printf(" This flag controls bounds checking with a software check. \n");
  124. printf(" On 64-bit platforms, it is disabled by default, using a hardware \n");
  125. printf(" trap if supported, except when SGX or memory64 is enabled,\n");
  126. printf(" which defaults to a software check.\n");
  127. printf(" On 32-bit platforms, the flag is enabled by default, using a software check\n");
  128. printf(" due to the lack of hardware support.\n");
  129. printf(" CAVEAT: --bounds-checks=0 enables some optimizations\n");
  130. printf(" which make the compiled AOT module incompatible\n");
  131. printf(" with a runtime without the hardware bounds checks.\n");
  132. printf(" --stack-bounds-checks=1/0 Enable or disable the bounds checks for native stack:\n");
  133. printf(" if the option isn't set, the status is same as `--bounds-check`,\n");
  134. printf(" if the option is set, the status is same as the option value\n");
  135. printf(" --stack-usage=<file> Generate a stack-usage file.\n");
  136. printf(" Similarly to `clang -fstack-usage`.\n");
  137. printf(" --format=<format> Specifies the format of the output file\n");
  138. printf(" The format supported:\n");
  139. printf(" aot (default) AoT file\n");
  140. printf(" object Native object file\n");
  141. printf(" llvmir-unopt Unoptimized LLVM IR\n");
  142. printf(" llvmir-opt Optimized LLVM IR\n");
  143. printf(" --disable-bulk-memory Disable the MVP bulk memory feature\n");
  144. printf(" --enable-bulk-memory-opt Enable bulk memory opt feature\n");
  145. printf(" --enable-extended-const Enable extended const expr feature\n");
  146. printf(" --enable-multi-thread Enable multi-thread feature, the dependent features bulk-memory and\n");
  147. printf(" thread-mgr will be enabled automatically\n");
  148. printf(" --enable-tail-call Enable the post-MVP tail call feature\n");
  149. printf(" --disable-simd Disable the post-MVP 128-bit SIMD feature:\n");
  150. printf(" currently 128-bit SIMD is supported for x86-64 and aarch64 targets,\n");
  151. printf(" and by default it is enabled in them and disabled in other targets\n");
  152. printf(" --disable-ref-types Disable the MVP reference types feature, it will be disabled forcibly if\n");
  153. printf(" GC is enabled\n");
  154. printf(" --enable-call-indirect-overlong\n");
  155. printf(" Enable call indirect overlong feature\n");
  156. printf(" --enable-lime1 Enable Lime1\n");
  157. printf(" --disable-aux-stack-check Disable auxiliary stack overflow/underflow check\n");
  158. printf(" --enable-dump-call-stack Enable stack trace feature\n");
  159. printf(" --call-stack-features=<features>\n");
  160. printf(" A comma-separated list of features when generating call stacks.\n");
  161. printf(" By default, all features are enabled. To disable all features,\n");
  162. printf(" provide an empty list (i.e. --call-stack-features=). This flag\n");
  163. printf(" only only takes effect when --enable-dump-call-stack is set.\n");
  164. printf(" Available features: bounds-checks, ip, func-idx, trap-ip, values.\n");
  165. printf(" --enable-perf-profiling Enable function performance profiling\n");
  166. printf(" --enable-memory-profiling Enable memory usage profiling\n");
  167. printf(" --xip A shorthand of --enable-indirect-mode --disable-llvm-intrinsics\n");
  168. printf(" --enable-indirect-mode Enable call function through symbol table but not direct call\n");
  169. printf(" --enable-gc Enable GC (Garbage Collection) feature\n");
  170. printf(" --disable-llvm-intrinsics Disable the LLVM built-in intrinsics\n");
  171. printf(" --enable-builtin-intrinsics=<flags>\n");
  172. printf(" Enable the specified built-in intrinsics, it will override the default\n");
  173. printf(" settings. It only takes effect when --disable-llvm-intrinsics is set.\n");
  174. printf(" Available flags: all, i32.common, i64.common, f32.common, f64.common,\n");
  175. printf(" i32.clz, i32.ctz, etc, refer to doc/xip.md for full list\n");
  176. printf(" Use comma to separate, please refer to doc/xip.md for full list.\n");
  177. printf(" --disable-llvm-jump-tables Disable the LLVM jump tables similarly to clang's -fno-jump-tables\n");
  178. printf(" --disable-llvm-lto Disable the LLVM link time optimization\n");
  179. printf(" --enable-llvm-pgo Enable LLVM PGO (Profile-Guided Optimization)\n");
  180. printf(" --enable-llvm-passes=<passes>\n");
  181. printf(" Enable the specified LLVM passes, using comma to separate\n");
  182. printf(" --use-prof-file=<file> Use profile file collected by LLVM PGO (Profile-Guided Optimization)\n");
  183. printf(" --enable-segue[=<flags>] Enable using segment register GS as the base address of linear memory,\n");
  184. printf(" only available on linux x86-64, which may improve performance,\n");
  185. printf(" flags can be: i32.load, i64.load, f32.load, f64.load, v128.load,\n");
  186. printf(" i32.store, i64.store, f32.store, f64.store, v128.store\n");
  187. printf(" Use comma to separate, e.g. --enable-segue=i32.load,i64.store\n");
  188. printf(" and --enable-segue means all flags are added.\n");
  189. printf(" --emit-custom-sections=<section names>\n");
  190. printf(" Emit the specified custom sections to AoT file, using comma to separate\n");
  191. printf(" multiple names, e.g.\n");
  192. printf(" --emit-custom-sections=section1,section2,sectionN\n");
  193. #if BH_HAS_DLFCN
  194. printf(" --native-lib=<lib> Register native libraries to the WASM module, which\n");
  195. printf(" are shared object (.so) files, for example:\n");
  196. printf(" --native-lib=test1.so --native-lib=test2.so\n");
  197. #endif
  198. printf(" --invoke-c-api-import Treat unknown import function as wasm-c-api import function and\n");
  199. printf(" quick call it from AOT code\n");
  200. #if WASM_ENABLE_LINUX_PERF != 0
  201. printf(" --enable-linux-perf Enable linux perf support\n");
  202. #endif
  203. printf(" --mllvm=<option> Add the LLVM command line option\n");
  204. printf(" --enable-shared-heap Enable shared heap feature, assuming only one shared heap will be attached\n");
  205. printf(" --enable-shared-chain Enable shared heap chain feature, works for more than one shared heap\n");
  206. printf(" WARNING: enable this feature will largely increase code size\n");
  207. printf(" -v=n Set log verbose level (0 to 5, default is 2), larger with more log\n");
  208. printf(" --version Show version information\n");
  209. printf(" --llvm-version Show LLVM version information\n");
  210. printf("Examples: wamrc -o test.aot test.wasm\n");
  211. printf(" wamrc --target=i386 -o test.aot test.wasm\n");
  212. printf(" wamrc --target=i386 --format=object -o test.o test.wasm\n");
  213. printf(" wamrc --target-abi=help\n");
  214. printf(" wamrc --target=x86_64 --cpu=help\n");
  215. }
  216. /* clang-format on */
  217. #define PRINT_HELP_AND_EXIT() \
  218. do { \
  219. print_help(); \
  220. goto fail0; \
  221. } while (0)
  222. /**
  223. * Split a string into an array of strings
  224. * Returns NULL on failure
  225. * Memory must be freed by caller
  226. * Based on: http://stackoverflow.com/a/11198630/471795
  227. */
  228. static char **
  229. split_string(char *str, int *count, const char *delimer)
  230. {
  231. char **res = NULL, **res1;
  232. char *p;
  233. int idx = 0;
  234. /* split string and append tokens to 'res' */
  235. do {
  236. p = strtok(str, delimer);
  237. str = NULL;
  238. res1 = res;
  239. res = (char **)realloc(res1, sizeof(char *) * (uint32)(idx + 1));
  240. if (res == NULL) {
  241. free(res1);
  242. return NULL;
  243. }
  244. res[idx++] = p;
  245. } while (p);
  246. /**
  247. * Due to the section name,
  248. * res[0] might contain a '\' to indicate a space
  249. * func\name -> func name
  250. */
  251. p = strchr(res[0], '\\');
  252. while (p) {
  253. *p = ' ';
  254. p = strchr(p, '\\');
  255. }
  256. if (count) {
  257. *count = idx - 1;
  258. }
  259. return res;
  260. }
  261. static bool
  262. parse_call_stack_features(char *features_str,
  263. AOTCallStackFeatures *out_features)
  264. {
  265. int size = 0;
  266. char **features;
  267. bool ret = true;
  268. bh_assert(features_str);
  269. bh_assert(out_features);
  270. /* non-empty feature list */
  271. features = split_string(features_str, &size, ",");
  272. if (!features) {
  273. return false;
  274. }
  275. while (size--) {
  276. if (!strcmp(features[size], "bounds-checks")) {
  277. out_features->bounds_checks = true;
  278. }
  279. else if (!strcmp(features[size], "ip")) {
  280. out_features->ip = true;
  281. }
  282. else if (!strcmp(features[size], "trap-ip")) {
  283. out_features->trap_ip = true;
  284. }
  285. else if (!strcmp(features[size], "values")) {
  286. out_features->values = true;
  287. }
  288. else if (!strcmp(features[size], "func-idx")) {
  289. out_features->func_idx = true;
  290. }
  291. else {
  292. ret = false;
  293. printf("Unsupported feature %s\n", features[size]);
  294. goto finish;
  295. }
  296. }
  297. finish:
  298. free(features);
  299. return ret;
  300. }
  301. static bool
  302. can_enable_tiny_frame(const AOTCompOption *opt)
  303. {
  304. return !opt->call_stack_features.values && !opt->enable_gc
  305. && !opt->enable_perf_profiling;
  306. }
  307. static uint32
  308. resolve_segue_flags(char *str_flags)
  309. {
  310. uint32 segue_flags = 0;
  311. int32 flag_count, i;
  312. char **flag_list;
  313. flag_list = split_string(str_flags, &flag_count, ",");
  314. if (flag_list) {
  315. for (i = 0; i < flag_count; i++) {
  316. if (!strcmp(flag_list[i], "i32.load")) {
  317. segue_flags |= 1 << 0;
  318. }
  319. else if (!strcmp(flag_list[i], "i64.load")) {
  320. segue_flags |= 1 << 1;
  321. }
  322. else if (!strcmp(flag_list[i], "f32.load")) {
  323. segue_flags |= 1 << 2;
  324. }
  325. else if (!strcmp(flag_list[i], "f64.load")) {
  326. segue_flags |= 1 << 3;
  327. }
  328. else if (!strcmp(flag_list[i], "v128.load")) {
  329. segue_flags |= 1 << 4;
  330. }
  331. else if (!strcmp(flag_list[i], "i32.store")) {
  332. segue_flags |= 1 << 8;
  333. }
  334. else if (!strcmp(flag_list[i], "i64.store")) {
  335. segue_flags |= 1 << 9;
  336. }
  337. else if (!strcmp(flag_list[i], "f32.store")) {
  338. segue_flags |= 1 << 10;
  339. }
  340. else if (!strcmp(flag_list[i], "f64.store")) {
  341. segue_flags |= 1 << 11;
  342. }
  343. else if (!strcmp(flag_list[i], "v128.store")) {
  344. segue_flags |= 1 << 12;
  345. }
  346. else {
  347. /* invalid flag */
  348. segue_flags = (uint32)-1;
  349. break;
  350. }
  351. }
  352. free(flag_list);
  353. }
  354. return segue_flags;
  355. }
  356. /* When print help info for target/cpu/target-abi/cpu-features, load this dummy
  357. * wasm file content rather than from an input file, the dummy wasm file content
  358. * is: magic header + version number */
  359. static unsigned char dummy_wasm_file[8] = { 0x00, 0x61, 0x73, 0x6D,
  360. 0x01, 0x00, 0x00, 0x00 };
  361. int
  362. main(int argc, char *argv[])
  363. {
  364. char *wasm_file_name = NULL, *out_file_name = NULL;
  365. char **llvm_options = NULL;
  366. size_t llvm_options_count = 0;
  367. uint8 *wasm_file = NULL;
  368. uint32 wasm_file_size;
  369. wasm_module_t wasm_module = NULL;
  370. aot_comp_data_t comp_data = NULL;
  371. aot_comp_context_t comp_ctx = NULL;
  372. RuntimeInitArgs init_args;
  373. AOTCompOption option = { 0 };
  374. char error_buf[128];
  375. int log_verbose_level = 2;
  376. bool sgx_mode = false, size_level_set = false, use_dummy_wasm = false;
  377. int exit_status = EXIT_FAILURE;
  378. #if BH_HAS_DLFCN
  379. const char *native_lib_list[8] = { NULL };
  380. uint32 native_lib_count = 0;
  381. void *native_handle_list[8] = { NULL };
  382. uint32 native_handle_count = 0;
  383. #endif
  384. #if WASM_ENABLE_LINUX_PERF != 0
  385. bool enable_linux_perf = false;
  386. #endif
  387. option.opt_level = 3;
  388. option.size_level = 3;
  389. option.output_format = AOT_FORMAT_FILE;
  390. /* default value, enable or disable depends on the platform */
  391. option.bounds_checks = 2;
  392. /* default value, enable or disable depends on the platform */
  393. option.stack_bounds_checks = 2;
  394. option.enable_simd = true;
  395. option.enable_aux_stack_check = true;
  396. option.enable_bulk_memory = true;
  397. option.enable_bulk_memory_opt = false;
  398. option.enable_ref_types = true;
  399. option.enable_call_indirect_overlong = false;
  400. option.enable_gc = false;
  401. option.enable_extended_const = false;
  402. option.enable_lime1 = false;
  403. aot_call_stack_features_init_default(&option.call_stack_features);
  404. /* Process options */
  405. for (argc--, argv++; argc > 0 && argv[0][0] == '-'; argc--, argv++) {
  406. if (!strcmp(argv[0], "-o")) {
  407. argc--, argv++;
  408. if (argc < 2)
  409. PRINT_HELP_AND_EXIT();
  410. out_file_name = argv[0];
  411. }
  412. else if (!strncmp(argv[0], "--target=", 9)) {
  413. if (argv[0][9] == '\0')
  414. PRINT_HELP_AND_EXIT();
  415. option.target_arch = argv[0] + 9;
  416. if (!strcmp(option.target_arch, "help")) {
  417. use_dummy_wasm = true;
  418. }
  419. }
  420. else if (!strncmp(argv[0], "--target-abi=", 13)) {
  421. if (argv[0][13] == '\0')
  422. PRINT_HELP_AND_EXIT();
  423. option.target_abi = argv[0] + 13;
  424. if (!strcmp(option.target_abi, "help")) {
  425. use_dummy_wasm = true;
  426. }
  427. }
  428. else if (!strncmp(argv[0], "--cpu=", 6)) {
  429. if (argv[0][6] == '\0')
  430. PRINT_HELP_AND_EXIT();
  431. option.target_cpu = argv[0] + 6;
  432. if (!strcmp(option.target_cpu, "help")) {
  433. use_dummy_wasm = true;
  434. }
  435. }
  436. else if (!strncmp(argv[0], "--cpu-features=", 15)) {
  437. if (argv[0][15] == '\0')
  438. PRINT_HELP_AND_EXIT();
  439. option.cpu_features = argv[0] + 15;
  440. if (!strcmp(option.cpu_features, "+help")) {
  441. use_dummy_wasm = true;
  442. }
  443. }
  444. else if (!strncmp(argv[0], "--opt-level=", 12)) {
  445. if (argv[0][12] == '\0')
  446. PRINT_HELP_AND_EXIT();
  447. option.opt_level = (uint32)atoi(argv[0] + 12);
  448. if (option.opt_level > 3)
  449. option.opt_level = 3;
  450. }
  451. else if (!strncmp(argv[0], "--size-level=", 13)) {
  452. if (argv[0][13] == '\0')
  453. PRINT_HELP_AND_EXIT();
  454. option.size_level = (uint32)atoi(argv[0] + 13);
  455. if (option.size_level > 3)
  456. option.size_level = 3;
  457. size_level_set = true;
  458. }
  459. else if (!strcmp(argv[0], "-sgx")) {
  460. sgx_mode = true;
  461. }
  462. else if (!strncmp(argv[0], "--bounds-checks=", 16)) {
  463. option.bounds_checks = (atoi(argv[0] + 16) == 1) ? 1 : 0;
  464. }
  465. else if (!strncmp(argv[0], "--stack-bounds-checks=", 22)) {
  466. option.stack_bounds_checks = (atoi(argv[0] + 22) == 1) ? 1 : 0;
  467. }
  468. else if (!strncmp(argv[0], "--stack-usage=", 14)) {
  469. option.stack_usage_file = argv[0] + 14;
  470. }
  471. else if (!strncmp(argv[0], "--format=", 9)) {
  472. if (argv[0][9] == '\0')
  473. PRINT_HELP_AND_EXIT();
  474. if (!strcmp(argv[0] + 9, "aot"))
  475. option.output_format = AOT_FORMAT_FILE;
  476. else if (!strcmp(argv[0] + 9, "object"))
  477. option.output_format = AOT_OBJECT_FILE;
  478. else if (!strcmp(argv[0] + 9, "llvmir-unopt"))
  479. option.output_format = AOT_LLVMIR_UNOPT_FILE;
  480. else if (!strcmp(argv[0] + 9, "llvmir-opt"))
  481. option.output_format = AOT_LLVMIR_OPT_FILE;
  482. else {
  483. printf("Invalid format %s.\n", argv[0] + 9);
  484. PRINT_HELP_AND_EXIT();
  485. }
  486. }
  487. else if (!strncmp(argv[0], "-v=", 3)) {
  488. log_verbose_level = atoi(argv[0] + 3);
  489. if (log_verbose_level < 0 || log_verbose_level > 5)
  490. PRINT_HELP_AND_EXIT();
  491. }
  492. else if (!strcmp(argv[0], "--disable-bulk-memory")) {
  493. option.enable_bulk_memory = false;
  494. }
  495. else if (!strcmp(argv[0], "--enable-bulk-memory-opt")) {
  496. option.enable_bulk_memory_opt = true;
  497. }
  498. else if (!strcmp(argv[0], "--enable-multi-thread")) {
  499. option.enable_bulk_memory = true;
  500. option.enable_thread_mgr = true;
  501. }
  502. else if (!strcmp(argv[0], "--enable-tail-call")) {
  503. option.enable_tail_call = true;
  504. }
  505. else if (!strcmp(argv[0], "--enable-simd")) {
  506. /* obsolete option, kept for compatibility */
  507. option.enable_simd = true;
  508. }
  509. else if (!strcmp(argv[0], "--disable-simd")) {
  510. option.enable_simd = false;
  511. }
  512. else if (!strcmp(argv[0], "--disable-ref-types")) {
  513. option.enable_ref_types = false;
  514. }
  515. else if (!strcmp(argv[0], "--enable-call-indirect-overlong")) {
  516. option.enable_call_indirect_overlong = true;
  517. }
  518. else if (!strcmp(argv[0], "--disable-aux-stack-check")) {
  519. option.enable_aux_stack_check = false;
  520. }
  521. else if (!strcmp(argv[0], "--enable-extended-const")) {
  522. option.enable_extended_const = true;
  523. }
  524. else if (!strcmp(argv[0], "--enable-lime1")) {
  525. option.enable_lime1 = true;
  526. }
  527. else if (!strcmp(argv[0], "--enable-dump-call-stack")) {
  528. option.aux_stack_frame_type = AOT_STACK_FRAME_TYPE_STANDARD;
  529. }
  530. else if (!strncmp(argv[0], "--call-stack-features=", 22)) {
  531. /* Reset all the features, only enable the user-defined ones */
  532. memset(&option.call_stack_features, 0,
  533. sizeof(AOTCallStackFeatures));
  534. if (argv[0][22] != '\0') {
  535. if (!parse_call_stack_features(argv[0] + 22,
  536. &option.call_stack_features)) {
  537. printf("Failed to parse call-stack-features\n");
  538. PRINT_HELP_AND_EXIT();
  539. }
  540. }
  541. }
  542. else if (!strcmp(argv[0], "--enable-perf-profiling")) {
  543. option.aux_stack_frame_type = AOT_STACK_FRAME_TYPE_STANDARD;
  544. option.enable_perf_profiling = true;
  545. }
  546. else if (!strcmp(argv[0], "--enable-memory-profiling")) {
  547. option.enable_memory_profiling = true;
  548. option.enable_stack_estimation = true;
  549. }
  550. else if (!strcmp(argv[0], "--xip")) {
  551. option.is_indirect_mode = true;
  552. option.disable_llvm_intrinsics = true;
  553. }
  554. else if (!strcmp(argv[0], "--enable-indirect-mode")) {
  555. option.is_indirect_mode = true;
  556. }
  557. else if (!strcmp(argv[0], "--enable-gc")) {
  558. option.aux_stack_frame_type = AOT_STACK_FRAME_TYPE_STANDARD;
  559. option.enable_gc = true;
  560. }
  561. else if (!strcmp(argv[0], "--disable-llvm-intrinsics")) {
  562. option.disable_llvm_intrinsics = true;
  563. }
  564. else if (!strncmp(argv[0], "--enable-builtin-intrinsics=", 28)) {
  565. if (argv[0][28] == '\0')
  566. PRINT_HELP_AND_EXIT();
  567. option.builtin_intrinsics = argv[0] + 28;
  568. }
  569. else if (!strcmp(argv[0], "--disable-llvm-jump-tables")) {
  570. option.disable_llvm_jump_tables = true;
  571. }
  572. else if (!strcmp(argv[0], "--disable-llvm-lto")) {
  573. option.disable_llvm_lto = true;
  574. }
  575. else if (!strcmp(argv[0], "--enable-llvm-pgo")) {
  576. option.enable_llvm_pgo = true;
  577. }
  578. else if (!strncmp(argv[0], "--enable-llvm-passes=", 21)) {
  579. if (argv[0][21] == '\0')
  580. PRINT_HELP_AND_EXIT();
  581. option.llvm_passes = argv[0] + 21;
  582. }
  583. else if (!strncmp(argv[0], "--use-prof-file=", 16)) {
  584. if (argv[0][16] == '\0')
  585. PRINT_HELP_AND_EXIT();
  586. option.use_prof_file = argv[0] + 16;
  587. }
  588. else if (!strcmp(argv[0], "--enable-segue")) {
  589. /* all flags are enabled */
  590. option.segue_flags = 0x1F1F;
  591. }
  592. else if (!strncmp(argv[0], "--enable-segue=", 15)) {
  593. option.segue_flags = resolve_segue_flags(argv[0] + 15);
  594. if (option.segue_flags == (uint32)-1)
  595. PRINT_HELP_AND_EXIT();
  596. }
  597. else if (!strncmp(argv[0], "--emit-custom-sections=", 23)) {
  598. int len = 0;
  599. if (option.custom_sections) {
  600. free(option.custom_sections);
  601. }
  602. option.custom_sections = split_string(argv[0] + 23, &len, ",");
  603. if (!option.custom_sections) {
  604. printf("Failed to process emit-custom-sections: alloc "
  605. "memory failed\n");
  606. PRINT_HELP_AND_EXIT();
  607. }
  608. option.custom_sections_count = len;
  609. }
  610. #if BH_HAS_DLFCN
  611. else if (!strncmp(argv[0], "--native-lib=", 13)) {
  612. if (argv[0][13] == '\0')
  613. PRINT_HELP_AND_EXIT();
  614. if (native_lib_count >= sizeof(native_lib_list) / sizeof(char *)) {
  615. printf("Only allow max native lib number %d\n",
  616. (int)(sizeof(native_lib_list) / sizeof(char *)));
  617. goto fail0;
  618. }
  619. native_lib_list[native_lib_count++] = argv[0] + 13;
  620. }
  621. #endif
  622. else if (!strcmp(argv[0], "--invoke-c-api-import")) {
  623. option.quick_invoke_c_api_import = true;
  624. }
  625. #if WASM_ENABLE_LINUX_PERF != 0
  626. else if (!strcmp(argv[0], "--enable-linux-perf")) {
  627. enable_linux_perf = true;
  628. }
  629. #endif
  630. else if (!strncmp(argv[0], "--mllvm=", 8)) {
  631. void *np;
  632. if (argv[0][8] == '\0')
  633. PRINT_HELP_AND_EXIT();
  634. if (llvm_options_count == 0)
  635. llvm_options_count += 2;
  636. else
  637. llvm_options_count++;
  638. np = realloc(llvm_options, llvm_options_count * sizeof(char *));
  639. if (np == NULL) {
  640. printf("Memory allocation failure\n");
  641. goto fail0;
  642. }
  643. llvm_options = np;
  644. if (llvm_options_count == 2)
  645. llvm_options[llvm_options_count - 2] = "wamrc";
  646. llvm_options[llvm_options_count - 1] = argv[0] + 8;
  647. }
  648. else if (!strcmp(argv[0], "--enable-shared-heap")) {
  649. option.enable_shared_heap = true;
  650. }
  651. else if (!strcmp(argv[0], "--enable-shared-chain")) {
  652. option.enable_shared_chain = true;
  653. }
  654. else if (!strcmp(argv[0], "--version")) {
  655. uint32 major, minor, patch;
  656. wasm_runtime_get_version(&major, &minor, &patch);
  657. printf("wamrc %u.%u.%u\n", major, minor, patch);
  658. return 0;
  659. }
  660. else if (!strcmp(argv[0], "--llvm-version")) {
  661. unsigned major, minor, patch;
  662. LLVMGetVersion(&major, &minor, &patch);
  663. printf("LLVM %u.%u.%u\n", major, minor, patch);
  664. return 0;
  665. }
  666. else
  667. PRINT_HELP_AND_EXIT();
  668. }
  669. if (!use_dummy_wasm && (argc == 0 || !out_file_name))
  670. PRINT_HELP_AND_EXIT();
  671. if (option.aux_stack_frame_type == AOT_STACK_FRAME_TYPE_STANDARD
  672. && can_enable_tiny_frame(&option)) {
  673. LOG_VERBOSE("Use tiny frame mode for stack frames");
  674. option.aux_stack_frame_type = AOT_STACK_FRAME_TYPE_TINY;
  675. /* for now we only enable frame per function for a TINY frame mode */
  676. option.call_stack_features.frame_per_function = true;
  677. }
  678. if (!option.call_stack_features.func_idx
  679. && (option.enable_gc || option.enable_perf_profiling)) {
  680. LOG_WARNING("'func-idx' call stack feature will be automatically "
  681. "enabled for GC and perf profiling mode");
  682. option.call_stack_features.func_idx = true;
  683. }
  684. if (!size_level_set) {
  685. /**
  686. * Set opt level to 1 by default for Windows and MacOS as
  687. * they can not memory map out 0-2GB memory and might not
  688. * be able to meet the requirements of some AOT relocation
  689. * operations.
  690. */
  691. if (option.target_abi && !strcmp(option.target_abi, "msvc")) {
  692. LOG_VERBOSE("Set size level to 1 for Windows AOT file");
  693. option.size_level = 1;
  694. }
  695. #if defined(_WIN32) || defined(_WIN32_) \
  696. || ((defined(__APPLE__) || defined(__MACH__)) && !defined(__arm64__))
  697. if (!option.target_arch && !option.target_abi) {
  698. LOG_VERBOSE("Set size level to 1 for Windows or MacOS AOT file");
  699. option.size_level = 1;
  700. }
  701. #endif
  702. }
  703. if (option.enable_gc && !option.call_stack_features.values) {
  704. LOG_WARNING("Call stack feature 'values' must be enabled for GC. The "
  705. "feature will be enabled automatically.");
  706. option.call_stack_features.values = true;
  707. }
  708. if (sgx_mode) {
  709. option.size_level = 0;
  710. option.is_sgx_platform = true;
  711. }
  712. if (option.enable_gc) {
  713. option.enable_ref_types = false;
  714. }
  715. if (option.enable_shared_chain) {
  716. LOG_VERBOSE("Enable shared chain will overwrite shared heap and sw "
  717. "bounds control");
  718. option.enable_shared_heap = false;
  719. option.bounds_checks = true;
  720. }
  721. if (option.enable_bulk_memory) {
  722. option.enable_bulk_memory_opt = true;
  723. }
  724. if (option.enable_ref_types) {
  725. option.enable_call_indirect_overlong = true;
  726. }
  727. if (option.enable_lime1) {
  728. option.enable_call_indirect_overlong = true;
  729. option.enable_bulk_memory_opt = true;
  730. option.enable_extended_const = true;
  731. }
  732. if (!use_dummy_wasm) {
  733. wasm_file_name = argv[0];
  734. if (!strcmp(wasm_file_name, out_file_name)) {
  735. printf("Error: input file and output file are the same");
  736. return -1;
  737. }
  738. }
  739. memset(&init_args, 0, sizeof(RuntimeInitArgs));
  740. init_args.mem_alloc_type = Alloc_With_Allocator;
  741. init_args.mem_alloc_option.allocator.malloc_func = malloc;
  742. init_args.mem_alloc_option.allocator.realloc_func = realloc;
  743. init_args.mem_alloc_option.allocator.free_func = free;
  744. #if WASM_ENABLE_LINUX_PERF != 0
  745. init_args.enable_linux_perf = enable_linux_perf;
  746. #endif
  747. /* initialize runtime environment */
  748. if (!wasm_runtime_full_init(&init_args)) {
  749. printf("Init runtime environment failed.\n");
  750. return -1;
  751. }
  752. bh_log_set_verbose_level(log_verbose_level);
  753. #if BH_HAS_DLFCN
  754. bh_print_time("Begin to load native libs");
  755. native_handle_count = load_and_register_native_libs(
  756. native_lib_list, native_lib_count, native_handle_list);
  757. #endif
  758. if (llvm_options_count > 0)
  759. LLVMParseCommandLineOptions(llvm_options_count,
  760. (const char **)llvm_options, "wamrc");
  761. bh_print_time("Begin to load wasm file");
  762. if (use_dummy_wasm) {
  763. /* load WASM byte buffer from dummy buffer */
  764. wasm_file_size = sizeof(dummy_wasm_file);
  765. wasm_file = dummy_wasm_file;
  766. }
  767. else {
  768. /* load WASM byte buffer from WASM bin file */
  769. if (!(wasm_file = (uint8 *)bh_read_file_to_buffer(wasm_file_name,
  770. &wasm_file_size)))
  771. goto fail1;
  772. }
  773. if (wasm_file_size >= 4 /* length of MAGIC NUMBER */
  774. && get_package_type(wasm_file, wasm_file_size)
  775. != Wasm_Module_Bytecode) {
  776. printf("Invalid wasm file: magic header not detected\n");
  777. goto fail2;
  778. }
  779. /* load WASM module */
  780. if (!(wasm_module = wasm_runtime_load(wasm_file, wasm_file_size, error_buf,
  781. sizeof(error_buf)))) {
  782. printf("%s\n", error_buf);
  783. goto fail2;
  784. }
  785. if (!(comp_data = aot_create_comp_data(wasm_module, option.target_arch,
  786. option.enable_gc))) {
  787. printf("%s\n", aot_get_last_error());
  788. goto fail3;
  789. }
  790. #if WASM_ENABLE_DEBUG_AOT != 0
  791. if (!create_dwarf_extractor(comp_data, wasm_file_name)) {
  792. printf("%s:create dwarf extractor failed\n", wasm_file_name);
  793. }
  794. #endif
  795. bh_print_time("Begin to create compile context");
  796. if (!(comp_ctx = aot_create_comp_context(comp_data, &option))) {
  797. printf("%s\n", aot_get_last_error());
  798. goto fail4;
  799. }
  800. bh_print_time("Begin to compile");
  801. if (!aot_compile_wasm(comp_ctx)) {
  802. printf("%s\n", aot_get_last_error());
  803. goto fail5;
  804. }
  805. switch (option.output_format) {
  806. case AOT_LLVMIR_UNOPT_FILE:
  807. case AOT_LLVMIR_OPT_FILE:
  808. if (!aot_emit_llvm_file(comp_ctx, out_file_name)) {
  809. printf("%s\n", aot_get_last_error());
  810. goto fail5;
  811. }
  812. break;
  813. case AOT_OBJECT_FILE:
  814. if (!aot_emit_object_file(comp_ctx, out_file_name)) {
  815. printf("%s\n", aot_get_last_error());
  816. goto fail5;
  817. }
  818. break;
  819. case AOT_FORMAT_FILE:
  820. if (!aot_emit_aot_file(comp_ctx, comp_data, out_file_name)) {
  821. printf("%s\n", aot_get_last_error());
  822. goto fail5;
  823. }
  824. break;
  825. default:
  826. break;
  827. }
  828. bh_print_time("Compile end");
  829. printf("Compile success, file %s was generated.\n", out_file_name);
  830. exit_status = EXIT_SUCCESS;
  831. fail5:
  832. /* Destroy compiler context */
  833. aot_destroy_comp_context(comp_ctx);
  834. fail4:
  835. /* Destroy compile data */
  836. aot_destroy_comp_data(comp_data);
  837. fail3:
  838. /* Unload WASM module */
  839. wasm_runtime_unload(wasm_module);
  840. fail2:
  841. /* free the file buffer */
  842. if (!use_dummy_wasm) {
  843. wasm_runtime_free(wasm_file);
  844. }
  845. fail1:
  846. #if BH_HAS_DLFCN
  847. unregister_and_unload_native_libs(native_handle_count, native_handle_list);
  848. #endif
  849. /* Destroy runtime environment */
  850. wasm_runtime_destroy();
  851. fail0:
  852. /* free option.custom_sections */
  853. if (option.custom_sections) {
  854. free(option.custom_sections);
  855. }
  856. free(llvm_options);
  857. bh_print_time("wamrc return");
  858. return exit_status;
  859. }