Coverage Report

Created: 2026-07-16 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/WasmEdge/include/runtime/instance/function.h
Line
Count
Source
1
// SPDX-License-Identifier: Apache-2.0
2
// SPDX-FileCopyrightText: Copyright The WasmEdge Authors
3
4
//===-- wasmedge/runtime/instance/function.h - Function Instance definition ==//
5
//
6
// Part of the WasmEdge Project.
7
//
8
//===----------------------------------------------------------------------===//
9
///
10
/// \file
11
/// This file contains the function instance definition in store manager.
12
///
13
//===----------------------------------------------------------------------===//
14
#pragma once
15
16
#include "ast/instruction.h"
17
#include "common/symbol.h"
18
#include "runtime/hostfunc.h"
19
#include "runtime/instance/composite.h"
20
21
#include <cstddef>
22
#include <memory>
23
#include <numeric>
24
#include <string>
25
#include <vector>
26
27
namespace WasmEdge {
28
namespace Runtime {
29
namespace Instance {
30
31
class ModuleInstance;
32
33
class FunctionInstance : public CompositeBase {
34
public:
35
  using CompiledFunction = void;
36
37
  FunctionInstance() = delete;
38
  /// Move constructor.
39
  FunctionInstance(FunctionInstance &&Inst) noexcept
40
      : CompositeBase(Inst.ModInst, Inst.TypeIdx),
41
        CompiledCode(Inst.CompiledCode), FuncType(Inst.FuncType),
42
0
        Data(std::move(Inst.Data)) {
43
0
    assuming(ModInst);
44
0
  }
45
  /// Constructor for native function.
46
  FunctionInstance(const ModuleInstance *Mod, const uint32_t TIdx,
47
                   const AST::FunctionType &Type,
48
                   Span<const std::pair<uint32_t, ValType>> Locs,
49
                   AST::InstrView Expr) noexcept
50
0
      : CompositeBase(Mod, TIdx), FuncType(Type),
51
0
        Data(std::in_place_type_t<WasmFunction>(), Locs, Expr) {
52
0
    assuming(ModInst);
53
0
  }
54
  /// Constructor for compiled function.
55
  FunctionInstance(const ModuleInstance *Mod, const uint32_t TIdx,
56
                   const AST::FunctionType &Type,
57
                   Symbol<CompiledFunction> S) noexcept
58
0
      : CompositeBase(Mod, TIdx), CompiledCode(S.get()), FuncType(Type),
59
0
        Data(std::in_place_type_t<Symbol<CompiledFunction>>(), std::move(S)) {
60
0
    assuming(ModInst);
61
0
  }
62
  /// Constructors for host function.
63
  FunctionInstance(const ModuleInstance *Mod, const uint32_t TIdx,
64
                   std::unique_ptr<HostFunctionBase> &&Func) noexcept
65
0
      : CompositeBase(Mod, TIdx), FuncType(Func->getFuncType()),
66
0
        Data(std::in_place_type_t<std::unique_ptr<HostFunctionBase>>(),
67
0
             std::move(Func)) {
68
0
    assuming(ModInst);
69
0
  }
70
  FunctionInstance(std::unique_ptr<HostFunctionBase> &&Func) noexcept
71
0
      : CompositeBase(), FuncType(Func->getFuncType()),
72
0
        Data(std::in_place_type_t<std::unique_ptr<HostFunctionBase>>(),
73
0
             std::move(Func)) {}
74
75
  /// Check whether this is a native wasm function.
76
0
  bool isWasmFunction() const noexcept {
77
0
    return std::holds_alternative<WasmFunction>(Data);
78
0
  }
79
80
  /// Check whether this is a compiled function.
81
0
  bool isCompiledFunction() const noexcept {
82
0
    return std::holds_alternative<Symbol<CompiledFunction>>(Data);
83
0
  }
84
85
  /// Check whether this is a host function.
86
0
  bool isHostFunction() const noexcept {
87
0
    return std::holds_alternative<std::unique_ptr<HostFunctionBase>>(Data);
88
0
  }
89
90
  /// Getter for function type.
91
0
  const AST::FunctionType &getFuncType() const noexcept { return FuncType; }
92
93
  /// Getter for function local variables.
94
0
  Span<const std::pair<uint32_t, ValType>> getLocals() const noexcept {
95
0
    return std::get_if<WasmFunction>(&Data)->Locals;
96
0
  }
97
98
  /// Getter for function local number.
99
0
  uint32_t getLocalNum() const noexcept {
100
0
    return std::get_if<WasmFunction>(&Data)->LocalNum;
101
0
  }
102
103
  /// Getter for function body instrs.
104
0
  AST::InstrView getInstrs() const noexcept {
105
0
    if (std::holds_alternative<WasmFunction>(Data)) {
106
0
      return std::get<WasmFunction>(Data).Instrs;
107
0
    } else {
108
0
      return {};
109
0
    }
110
0
  }
111
112
  /// Getter for symbol.
113
0
  auto &getSymbol() const noexcept {
114
0
    return *std::get_if<Symbol<CompiledFunction>>(&Data);
115
0
  }
116
117
  /// Getter for host function.
118
0
  HostFunctionBase &getHostFunc() const noexcept {
119
0
    return *std::get_if<std::unique_ptr<HostFunctionBase>>(&Data)->get();
120
0
  }
121
122
  /// Field offsets read inline by the AOT/JIT compiler for the call_indirect
123
  /// fast path; offsetof-derived so they follow the target ABI.
124
#if defined(__GNUC__) || defined(__clang__)
125
#pragma GCC diagnostic push
126
#pragma GCC diagnostic ignored "-Winvalid-offsetof"
127
#endif
128
795
  static constexpr uint64_t getModuleOffset() noexcept {
129
795
    return offsetof(FunctionInstance, ModInst);
130
795
  }
131
795
  static constexpr uint64_t getTypeIndexOffset() noexcept {
132
795
    return offsetof(FunctionInstance, TypeIdx);
133
795
  }
134
795
  static constexpr uint64_t getCompiledCodeOffset() noexcept {
135
795
    return offsetof(FunctionInstance, CompiledCode);
136
795
  }
137
#if defined(__GNUC__) || defined(__clang__)
138
#pragma GCC diagnostic pop
139
#endif
140
141
  /// Upgrade from WasmFunction to CompiledFunction.
142
  /// Must be called under synchronization that
143
  /// prevents concurrent access to this function's body.
144
0
  bool unsafeUpgradeToCompiled(Symbol<CompiledFunction> Sym) noexcept {
145
0
    if (!isWasmFunction()) {
146
0
      return false;
147
0
    }
148
0
    CompiledCode = Sym.get();
149
0
    Data = std::move(Sym);
150
0
    return true;
151
0
  }
152
153
private:
154
  struct WasmFunction {
155
    const std::vector<std::pair<uint32_t, ValType>> Locals;
156
    const uint32_t LocalNum;
157
    AST::InstrVec Instrs;
158
    WasmFunction(Span<const std::pair<uint32_t, ValType>> Locs,
159
                 AST::InstrView Expr) noexcept
160
0
        : Locals(Locs.begin(), Locs.end()),
161
          LocalNum(
162
0
              std::accumulate(Locals.begin(), Locals.end(), UINT32_C(0),
163
0
                              [](uint32_t N, const auto &Pair) -> uint32_t {
164
0
                                return N + Pair.first;
165
0
                              })) {
166
      // FIXME: Modify the capacity to prevent connecting 2 vectors.
167
0
      Instrs.reserve(Expr.size() + 1);
168
0
      Instrs.assign(Expr.begin(), Expr.end());
169
0
    }
170
  };
171
172
  /// \name Data of function instance.
173
  /// @{
174
175
  /// Compiled code pointer, read inline at getCompiledCodeOffset() by the
176
  /// call_indirect fast path.
177
  void *CompiledCode = nullptr;
178
  const AST::FunctionType &FuncType;
179
  std::variant<WasmFunction, Symbol<CompiledFunction>,
180
               std::unique_ptr<HostFunctionBase>>
181
      Data;
182
  /// @}
183
};
184
185
} // namespace Instance
186
} // namespace Runtime
187
} // namespace WasmEdge