Coverage Report

Created: 2025-11-24 06:51

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/WasmEdge/lib/driver/compilerTool.cpp
Line
Count
Source
1
// SPDX-License-Identifier: Apache-2.0
2
// SPDX-FileCopyrightText: 2019-2024 Second State INC
3
4
#include "common/configure.h"
5
#include "common/defines.h"
6
#include "common/filesystem.h"
7
#include "common/version.h"
8
#include "driver/compiler.h"
9
#include "loader/loader.h"
10
#include "validator/validator.h"
11
#include "llvm/codegen.h"
12
#include "llvm/compiler.h"
13
#include <cstdint>
14
#include <cstdlib>
15
#include <memory>
16
#include <string>
17
#include <utility>
18
#include <vector>
19
20
namespace WasmEdge {
21
namespace Driver {
22
23
0
int Compiler([[maybe_unused]] struct DriverCompilerOptions &Opt) noexcept {
24
0
  using namespace std::literals;
25
26
0
  std::ios::sync_with_stdio(false);
27
0
  Log::setInfoLoggingLevel();
28
29
0
#ifdef WASMEDGE_USE_LLVM
30
31
0
  Configure Conf;
32
  // WASM standard configuration has the highest priority.
33
0
  if (Opt.PropWASM1.value()) {
34
0
    Conf.setWASMStandard(Standard::WASM_1);
35
0
  }
36
0
  if (Opt.PropWASM2.value()) {
37
0
    Conf.setWASMStandard(Standard::WASM_2);
38
0
  }
39
0
  if (Opt.PropWASM3.value()) {
40
0
    Conf.setWASMStandard(Standard::WASM_3);
41
0
  }
42
43
  // Proposals adjustment.
44
0
  if (Opt.PropMutGlobals.value()) {
45
0
    Conf.removeProposal(Proposal::ImportExportMutGlobals);
46
0
  }
47
0
  if (Opt.PropNonTrapF2IConvs.value()) {
48
0
    Conf.removeProposal(Proposal::NonTrapFloatToIntConversions);
49
0
  }
50
0
  if (Opt.PropSignExtendOps.value()) {
51
0
    Conf.removeProposal(Proposal::SignExtensionOperators);
52
0
  }
53
0
  if (Opt.PropMultiValue.value()) {
54
0
    Conf.removeProposal(Proposal::MultiValue);
55
0
  }
56
0
  if (Opt.PropBulkMemOps.value()) {
57
0
    Conf.removeProposal(Proposal::BulkMemoryOperations);
58
0
  }
59
0
  if (Opt.PropSIMD.value()) {
60
0
    Conf.removeProposal(Proposal::SIMD);
61
0
  }
62
0
  if (Opt.PropTailCall.value()) {
63
0
    Conf.removeProposal(Proposal::TailCall);
64
0
  }
65
0
  if (Opt.PropExtendConst.value()) {
66
0
    Conf.removeProposal(Proposal::ExtendedConst);
67
0
  }
68
0
  if (Opt.PropMultiMem.value()) {
69
0
    Conf.removeProposal(Proposal::MultiMemories);
70
0
  }
71
0
  if (Opt.PropRelaxedSIMD.value()) {
72
0
    Conf.removeProposal(Proposal::RelaxSIMD);
73
0
  }
74
  // TODO: EXCEPTION - enable the option.
75
0
  Conf.removeProposal(Proposal::ExceptionHandling);
76
  // if (Opt.PropExceptionHandling.value()) {
77
  //   Conf.removeProposal(Proposal::ExceptionHandling);
78
  // }
79
  // TODO: MEMORY64 - enable the option.
80
  // if (Opt.PropMemory64.value()) {
81
  //   Conf.removeProposal(Proposal::Memory64);
82
  // }
83
84
  // Handle the proposal removal which has dependency.
85
  // The GC proposal depends on the func-ref proposal, and the func-ref proposal
86
  // depends on the ref-types proposal.
87
0
  if (Opt.PropGC.value()) {
88
0
    Conf.removeProposal(Proposal::GC);
89
0
  }
90
0
  if (Opt.PropFunctionReference.value()) {
91
    // This will automatically not work if the GC proposal not disabled.
92
0
    Conf.removeProposal(Proposal::FunctionReferences);
93
0
  }
94
0
  if (Opt.PropRefTypes.value()) {
95
    // This will automatically not work if the GC or func-ref proposal not
96
    // disabled.
97
0
    Conf.removeProposal(Proposal::ReferenceTypes);
98
0
  }
99
100
0
  if (Opt.PropThreads.value()) {
101
0
    Conf.addProposal(Proposal::Threads);
102
0
  }
103
0
  if (Opt.PropAll.value()) {
104
0
    Conf.setWASMStandard(Standard::WASM_3);
105
0
    Conf.removeProposal(Proposal::ExceptionHandling);
106
0
    Conf.addProposal(Proposal::Threads);
107
0
  }
108
109
0
  if (Opt.PropOptimizationLevel.value() == "0") {
110
0
    Conf.getCompilerConfigure().setOptimizationLevel(
111
0
        WasmEdge::CompilerConfigure::OptimizationLevel::O0);
112
0
  } else if (Opt.PropOptimizationLevel.value() == "1") {
113
0
    Conf.getCompilerConfigure().setOptimizationLevel(
114
0
        WasmEdge::CompilerConfigure::OptimizationLevel::O1);
115
0
  } else if (Opt.PropOptimizationLevel.value() == "3") {
116
0
    Conf.getCompilerConfigure().setOptimizationLevel(
117
0
        WasmEdge::CompilerConfigure::OptimizationLevel::O3);
118
0
  } else if (Opt.PropOptimizationLevel.value() == "s") {
119
0
    Conf.getCompilerConfigure().setOptimizationLevel(
120
0
        WasmEdge::CompilerConfigure::OptimizationLevel::Os);
121
0
  } else if (Opt.PropOptimizationLevel.value() == "z") {
122
0
    Conf.getCompilerConfigure().setOptimizationLevel(
123
0
        WasmEdge::CompilerConfigure::OptimizationLevel::Oz);
124
0
  } else {
125
0
    Conf.getCompilerConfigure().setOptimizationLevel(
126
0
        WasmEdge::CompilerConfigure::OptimizationLevel::O2);
127
0
  }
128
129
  // Set force interpreter here to load instructions of function body forcibly.
130
0
  Conf.getRuntimeConfigure().setForceInterpreter(true);
131
132
0
  std::filesystem::path InputPath =
133
0
      std::filesystem::absolute(std::filesystem::u8path(Opt.WasmName.value()));
134
0
  std::filesystem::path OutputPath =
135
0
      std::filesystem::absolute(std::filesystem::u8path(Opt.SoName.value()));
136
0
  Loader::Loader Loader(Conf);
137
138
0
  std::vector<Byte> Data;
139
0
  if (auto Res = Loader.loadFile(InputPath)) {
140
0
    Data = std::move(*Res);
141
0
  } else {
142
0
    const auto Err = static_cast<uint32_t>(Res.error());
143
0
    spdlog::error("Load failed. Error code: {}"sv, Err);
144
0
    return EXIT_FAILURE;
145
0
  }
146
147
0
  std::unique_ptr<AST::Module> Module;
148
0
  if (auto Res = Loader.parseModule(Data)) {
149
0
    Module = std::move(*Res);
150
0
  } else {
151
0
    const auto Err = static_cast<uint32_t>(Res.error());
152
0
    spdlog::error("Parse Module failed. Error code: {}"sv, Err);
153
0
    return EXIT_FAILURE;
154
0
  }
155
156
0
  {
157
0
    Validator::Validator ValidatorEngine(Conf);
158
0
    if (auto Res = ValidatorEngine.validate(*Module); !Res) {
159
0
      const auto Err = static_cast<uint32_t>(Res.error());
160
0
      spdlog::error("Validate Module failed. Error code: {}"sv, Err);
161
0
      return EXIT_FAILURE;
162
0
    }
163
0
  }
164
165
0
  {
166
0
    if (Opt.ConfDumpIR.value()) {
167
0
      Conf.getCompilerConfigure().setDumpIR(true);
168
0
    }
169
0
    if (Opt.ConfInterruptible.value()) {
170
0
      Conf.getCompilerConfigure().setInterruptible(true);
171
0
    }
172
0
    if (Opt.ConfEnableAllStatistics.value()) {
173
0
      Conf.getStatisticsConfigure().setInstructionCounting(true);
174
0
      Conf.getStatisticsConfigure().setCostMeasuring(true);
175
0
      Conf.getStatisticsConfigure().setTimeMeasuring(true);
176
0
    } else {
177
0
      if (Opt.ConfEnableInstructionCounting.value()) {
178
0
        Conf.getStatisticsConfigure().setInstructionCounting(true);
179
0
      }
180
0
      if (Opt.ConfEnableGasMeasuring.value()) {
181
0
        Conf.getStatisticsConfigure().setCostMeasuring(true);
182
0
      }
183
0
      if (Opt.ConfEnableTimeMeasuring.value()) {
184
0
        Conf.getStatisticsConfigure().setTimeMeasuring(true);
185
0
      }
186
0
    }
187
0
    if (Opt.ConfGenericBinary.value()) {
188
0
      Conf.getCompilerConfigure().setGenericBinary(true);
189
0
    }
190
0
    if (OutputPath.extension().u8string() == WASMEDGE_LIB_EXTENSION) {
191
0
      Conf.getCompilerConfigure().setOutputFormat(
192
0
          CompilerConfigure::OutputFormat::Native);
193
0
    }
194
0
    LLVM::Compiler Compiler(Conf);
195
0
    if (auto Res = Compiler.checkConfigure(); !Res) {
196
0
      const auto Err = static_cast<uint32_t>(Res.error());
197
0
      spdlog::error("Compiler Configure failed. Error code: {}"sv, Err);
198
0
      return EXIT_FAILURE;
199
0
    }
200
0
    LLVM::CodeGen CodeGen(Conf);
201
0
    if (auto Res = Compiler.compile(*Module); !Res) {
202
0
      const auto Err = static_cast<uint32_t>(Res.error());
203
0
      spdlog::error("Compilation failed. Error code: {}"sv, Err);
204
0
      return EXIT_FAILURE;
205
0
    } else if (auto Res2 = CodeGen.codegen(Data, std::move(*Res), OutputPath);
206
0
               !Res2) {
207
0
      const auto Err = static_cast<uint32_t>(Res2.error());
208
0
      spdlog::error("Code Generation failed. Error code: {}"sv, Err);
209
0
      return EXIT_FAILURE;
210
0
    }
211
0
  }
212
213
0
  return EXIT_SUCCESS;
214
#else
215
  spdlog::error("Compilation is not supported!"sv);
216
217
  return EXIT_FAILURE;
218
#endif
219
0
}
220
221
} // namespace Driver
222
} // namespace WasmEdge