aot_llvm_extra.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include <llvm/ADT/SmallVector.h>
  6. #include <llvm/ADT/Twine.h>
  7. #include <llvm/ADT/Triple.h>
  8. #include <llvm/ExecutionEngine/ExecutionEngine.h>
  9. #include <llvm/MC/MCSubtargetInfo.h>
  10. #include <llvm/Support/TargetSelect.h>
  11. #include <llvm/Target/TargetMachine.h>
  12. #include <llvm-c/Core.h>
  13. #include <llvm-c/ExecutionEngine.h>
  14. #include <llvm/ExecutionEngine/GenericValue.h>
  15. #include <llvm/ExecutionEngine/JITEventListener.h>
  16. #include <llvm/ExecutionEngine/RTDyldMemoryManager.h>
  17. #include <llvm/IR/DerivedTypes.h>
  18. #include <llvm/IR/Module.h>
  19. #include <llvm/Support/ErrorHandling.h>
  20. #include <llvm/Target/CodeGenCWrappers.h>
  21. #include <llvm/Target/TargetOptions.h>
  22. #include <cstring>
  23. using namespace llvm;
  24. extern "C" LLVMBool
  25. WAMRCreateMCJITCompilerForModule(LLVMExecutionEngineRef *OutJIT,
  26. LLVMModuleRef M,
  27. LLVMMCJITCompilerOptions *PassedOptions,
  28. size_t SizeOfPassedOptions,
  29. char **OutError);
  30. extern "C" bool
  31. aot_check_simd_compatibility(const char *arch_c_str, const char *cpu_c_str);
  32. LLVMBool
  33. WAMRCreateMCJITCompilerForModule(LLVMExecutionEngineRef *OutJIT,
  34. LLVMModuleRef M,
  35. LLVMMCJITCompilerOptions *PassedOptions,
  36. size_t SizeOfPassedOptions,
  37. char **OutError)
  38. {
  39. LLVMMCJITCompilerOptions options;
  40. // If the user passed a larger sized options struct, then they were compiled
  41. // against a newer LLVM. Tell them that something is wrong.
  42. if (SizeOfPassedOptions > sizeof(options)) {
  43. *OutError = strdup(
  44. "Refusing to use options struct that is larger than my own; assuming "
  45. "LLVM library mismatch.");
  46. return 1;
  47. }
  48. // Defend against the user having an old version of the API by ensuring that
  49. // any fields they didn't see are cleared. We must defend against fields being
  50. // set to the bitwise equivalent of zero, and assume that this means "do the
  51. // default" as if that option hadn't been available.
  52. LLVMInitializeMCJITCompilerOptions(&options, sizeof(options));
  53. memcpy(&options, PassedOptions, SizeOfPassedOptions);
  54. TargetOptions targetOptions;
  55. targetOptions.EnableFastISel = options.EnableFastISel;
  56. std::unique_ptr<Module> Mod(unwrap(M));
  57. if (Mod) {
  58. // Set function attribute "frame-pointer" based on
  59. // NoFramePointerElim.
  60. for (auto &F : *Mod) {
  61. auto Attrs = F.getAttributes();
  62. StringRef Value = options.NoFramePointerElim ? "all" : "none";
  63. Attrs = Attrs.addAttribute(F.getContext(), AttributeList::FunctionIndex,
  64. "frame-pointer", Value);
  65. F.setAttributes(Attrs);
  66. }
  67. }
  68. std::string Error;
  69. bool JIT;
  70. char *host_cpu = LLVMGetHostCPUName();
  71. if (!host_cpu) {
  72. *OutError = NULL;
  73. return false;
  74. }
  75. std::string mcpu(host_cpu);
  76. LLVMDisposeMessage(host_cpu);
  77. EngineBuilder builder(std::move(Mod));
  78. builder.setEngineKind(EngineKind::JIT)
  79. .setErrorStr(&Error)
  80. .setMCPU(mcpu)
  81. .setOptLevel((CodeGenOpt::Level)options.OptLevel)
  82. .setTargetOptions(targetOptions);
  83. if (Optional<CodeModel::Model> CM = unwrap(options.CodeModel, JIT))
  84. builder.setCodeModel(*CM);
  85. if (options.MCJMM)
  86. builder.setMCJITMemoryManager(
  87. std::unique_ptr<RTDyldMemoryManager>(unwrap(options.MCJMM)));
  88. if (ExecutionEngine *JIT = builder.create()) {
  89. *OutJIT = wrap(JIT);
  90. return 0;
  91. }
  92. *OutError = strdup(Error.c_str());
  93. return 1;
  94. }
  95. bool
  96. aot_check_simd_compatibility(const char *arch_c_str, const char *cpu_c_str)
  97. {
  98. #if WASM_ENABLE_SIMD != 0
  99. if (!arch_c_str || !cpu_c_str) {
  100. return false;
  101. }
  102. llvm::SmallVector<std::string, 1> targetAttributes;
  103. llvm::Triple targetTriple(arch_c_str, "", "");
  104. llvm::TargetMachine *targetMachine = llvm::EngineBuilder().selectTarget(
  105. targetTriple, "", std::string(cpu_c_str), targetAttributes);
  106. if (targetMachine == nullptr) {
  107. return false;
  108. }
  109. const llvm::Triple::ArchType targetArch =
  110. targetMachine->getTargetTriple().getArch();
  111. const llvm::MCSubtargetInfo *subTargetInfo =
  112. targetMachine->getMCSubtargetInfo();
  113. if (subTargetInfo == nullptr) {
  114. return false;
  115. }
  116. if (targetArch == llvm::Triple::x86_64) {
  117. return subTargetInfo->checkFeatures("+sse4.1");
  118. }
  119. else if (targetArch == llvm::Triple::aarch64) {
  120. return subTargetInfo->checkFeatures("+neon");
  121. }
  122. else {
  123. return false;
  124. }
  125. #else
  126. (void)arch_c_str;
  127. (void)cpu_c_str;
  128. return true;
  129. #endif /* WASM_ENABLE_SIMD */
  130. }