Coverage Report

Created: 2026-11-12 06:35

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/WasmEdge/lib/api/wasmedge_compat.cpp
Line
Count
Source
1
// SPDX-License-Identifier: Apache-2.0
2
// SPDX-FileCopyrightText: Copyright The WasmEdge Authors
3
4
// >>>>>>>> WasmEdge compat ABI shims >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
5
//
6
// Frozen previous-release implementations of the C API functions whose
7
// signatures changed, bound with `.symver` to the version node each symbol had
8
// in that release. See .github/scripts/SYMBOL_CHECKING.md.
9
//
10
//   - 0.16 -> 0.17: `WasmEdge_Limit` struct -> `WasmEdge_LimitContext`,
11
//     `@WASMEDGE_0.16` beside the `@@WASMEDGE_0.17` default.
12
//   - 0.17 -> 0.18: `WasmEdge_ModuleInstanceAdd*` return `void` ->
13
//     `WasmEdge_Result`, `@WASMEDGE_0.16` beside the `@@WASMEDGE_0.18` default.
14
//
15
// A separate TU, so the `.symver` asm does not collide with the in-IR public
16
// definitions under ThinLTO.
17
18
#include "wasmedge/wasmedge.h"
19
20
#include "ast/type.h"
21
#include "runtime/instance/module.h"
22
23
#include <algorithm>
24
#include <array>
25
#include <cstdint>
26
#include <memory>
27
#include <string_view>
28
29
#if defined(__ELF__) && (defined(__linux__) || defined(__ANDROID__))
30
31
namespace {
32
using namespace WasmEdge;
33
34
// Copies of the `wasmedge.cpp` helpers.
35
0
inline ValType genValType(const WasmEdge_ValType &T) noexcept {
36
0
  std::array<uint8_t, 8> R;
37
0
  std::copy_n(T.Data, 8, R.begin());
38
0
  return ValType(R);
39
0
}
40
0
inline auto *toTabTypeCxt(AST::TableType *Cxt) noexcept {
41
0
  return reinterpret_cast<WasmEdge_TableTypeContext *>(Cxt);
42
0
}
43
inline const auto *
44
0
fromTabTypeCxt(const WasmEdge_TableTypeContext *Cxt) noexcept {
45
0
  return reinterpret_cast<const AST::TableType *>(Cxt);
46
0
}
47
0
inline auto *toMemTypeCxt(AST::MemoryType *Cxt) noexcept {
48
0
  return reinterpret_cast<WasmEdge_MemoryTypeContext *>(Cxt);
49
0
}
50
inline const auto *
51
0
fromMemTypeCxt(const WasmEdge_MemoryTypeContext *Cxt) noexcept {
52
0
  return reinterpret_cast<const AST::MemoryType *>(Cxt);
53
0
}
54
0
inline std::string_view genStrView(const WasmEdge_String S) noexcept {
55
0
  return std::string_view(S.Buf, S.Length);
56
0
}
57
0
inline auto *fromModCxt(WasmEdge_ModuleInstanceContext *Cxt) noexcept {
58
0
  return reinterpret_cast<Runtime::Instance::ModuleInstance *>(Cxt);
59
0
}
60
0
inline auto *fromFuncCxt(WasmEdge_FunctionInstanceContext *Cxt) noexcept {
61
0
  return reinterpret_cast<Runtime::Instance::FunctionInstance *>(Cxt);
62
0
}
63
0
inline auto *fromTabCxt(WasmEdge_TableInstanceContext *Cxt) noexcept {
64
0
  return reinterpret_cast<Runtime::Instance::TableInstance *>(Cxt);
65
0
}
66
0
inline auto *fromMemCxt(WasmEdge_MemoryInstanceContext *Cxt) noexcept {
67
0
  return reinterpret_cast<Runtime::Instance::MemoryInstance *>(Cxt);
68
0
}
69
0
inline auto *fromGlobCxt(WasmEdge_GlobalInstanceContext *Cxt) noexcept {
70
0
  return reinterpret_cast<Runtime::Instance::GlobalInstance *>(Cxt);
71
0
}
72
} // namespace
73
74
extern "C" {
75
76
// The 0.16 `WasmEdge_Limit` layout, before Memory64 widened `Min`/`Max`.
77
typedef struct WasmEdge_Limit_0_16 {
78
  bool HasMax;
79
  bool Shared;
80
  uint32_t Min;
81
  uint32_t Max;
82
} WasmEdge_Limit_0_16;
83
84
__attribute__((used, visibility("default"))) bool
85
WasmEdge_LimitIsEqual_Compat_016(const WasmEdge_Limit_0_16 Lim1,
86
0
                                 const WasmEdge_Limit_0_16 Lim2) {
87
0
  return Lim1.HasMax == Lim2.HasMax && Lim1.Shared == Lim2.Shared &&
88
0
         Lim1.Min == Lim2.Min && Lim1.Max == Lim2.Max;
89
0
}
90
91
__attribute__((used, visibility("default"))) WasmEdge_TableTypeContext *
92
WasmEdge_TableTypeCreate_Compat_016(const WasmEdge_ValType RefType,
93
0
                                    const WasmEdge_Limit_0_16 Limit) {
94
0
  WasmEdge::ValType RT = genValType(RefType);
95
0
  if (!RT.isRefType()) {
96
0
    return nullptr;
97
0
  }
98
0
  if (Limit.HasMax) {
99
0
    return toTabTypeCxt(new WasmEdge::AST::TableType(RT, Limit.Min, Limit.Max));
100
0
  } else {
101
0
    return toTabTypeCxt(new WasmEdge::AST::TableType(RT, Limit.Min));
102
0
  }
103
0
}
104
105
__attribute__((used, visibility("default"))) WasmEdge_Limit_0_16
106
0
WasmEdge_TableTypeGetLimit_Compat_016(const WasmEdge_TableTypeContext *Cxt) {
107
0
  if (Cxt) {
108
0
    const auto &Lim = fromTabTypeCxt(Cxt)->getLimit();
109
0
    return WasmEdge_Limit_0_16{/* HasMax */ Lim.hasMax(),
110
0
                               /* Shared */ Lim.isShared(),
111
0
                               /* Min */ static_cast<uint32_t>(Lim.getMin()),
112
0
                               /* Max */ static_cast<uint32_t>(Lim.getMax())};
113
0
  }
114
0
  return WasmEdge_Limit_0_16{/* HasMax */ false, /* Shared */ false,
115
0
                             /* Min */ 0, /* Max */ 0};
116
0
}
117
118
__attribute__((used, visibility("default"))) WasmEdge_MemoryTypeContext *
119
0
WasmEdge_MemoryTypeCreate_Compat_016(const WasmEdge_Limit_0_16 Limit) {
120
0
  if (Limit.Shared) {
121
0
    return toMemTypeCxt(
122
0
        new WasmEdge::AST::MemoryType(Limit.Min, Limit.Max, true));
123
0
  } else if (Limit.HasMax) {
124
0
    return toMemTypeCxt(new WasmEdge::AST::MemoryType(Limit.Min, Limit.Max));
125
0
  } else {
126
0
    return toMemTypeCxt(new WasmEdge::AST::MemoryType(Limit.Min));
127
0
  }
128
0
}
129
130
__attribute__((used, visibility("default"))) WasmEdge_Limit_0_16
131
0
WasmEdge_MemoryTypeGetLimit_Compat_016(const WasmEdge_MemoryTypeContext *Cxt) {
132
0
  if (Cxt) {
133
0
    const auto &Lim = fromMemTypeCxt(Cxt)->getLimit();
134
0
    return WasmEdge_Limit_0_16{/* HasMax */ Lim.hasMax(),
135
0
                               /* Shared */ Lim.isShared(),
136
0
                               /* Min */ static_cast<uint32_t>(Lim.getMin()),
137
0
                               /* Max */ static_cast<uint32_t>(Lim.getMax())};
138
0
  }
139
0
  return WasmEdge_Limit_0_16{/* HasMax */ false, /* Shared */ false,
140
0
                             /* Min */ 0, /* Max */ 0};
141
0
}
142
143
// The 0.17 `void` versions: add and discard the result.
144
__attribute__((used, visibility("default"))) void
145
WasmEdge_ModuleInstanceAddFunction_Compat_017(
146
    WasmEdge_ModuleInstanceContext *Cxt, const WasmEdge_String Name,
147
0
    WasmEdge_FunctionInstanceContext *FuncCxt) {
148
0
  if (Cxt && FuncCxt) {
149
0
    static_cast<void>(fromModCxt(Cxt)->addHostFunc(
150
0
        genStrView(Name), std::unique_ptr<Runtime::Instance::FunctionInstance>(
151
0
                              fromFuncCxt(FuncCxt))));
152
0
  }
153
0
}
154
155
__attribute__((used, visibility("default"))) void
156
WasmEdge_ModuleInstanceAddTable_Compat_017(
157
    WasmEdge_ModuleInstanceContext *Cxt, const WasmEdge_String Name,
158
0
    WasmEdge_TableInstanceContext *TableCxt) {
159
0
  if (Cxt && TableCxt) {
160
0
    static_cast<void>(fromModCxt(Cxt)->addHostTable(
161
0
        genStrView(Name), std::unique_ptr<Runtime::Instance::TableInstance>(
162
0
                              fromTabCxt(TableCxt))));
163
0
  }
164
0
}
165
166
__attribute__((used, visibility("default"))) void
167
WasmEdge_ModuleInstanceAddMemory_Compat_017(
168
    WasmEdge_ModuleInstanceContext *Cxt, const WasmEdge_String Name,
169
0
    WasmEdge_MemoryInstanceContext *MemoryCxt) {
170
0
  if (Cxt && MemoryCxt) {
171
0
    static_cast<void>(fromModCxt(Cxt)->addHostMemory(
172
0
        genStrView(Name), std::unique_ptr<Runtime::Instance::MemoryInstance>(
173
0
                              fromMemCxt(MemoryCxt))));
174
0
  }
175
0
}
176
177
__attribute__((used, visibility("default"))) void
178
WasmEdge_ModuleInstanceAddGlobal_Compat_017(
179
    WasmEdge_ModuleInstanceContext *Cxt, const WasmEdge_String Name,
180
0
    WasmEdge_GlobalInstanceContext *GlobalCxt) {
181
0
  if (Cxt && GlobalCxt) {
182
0
    static_cast<void>(fromModCxt(Cxt)->addHostGlobal(
183
0
        genStrView(Name), std::unique_ptr<Runtime::Instance::GlobalInstance>(
184
0
                              fromGlobCxt(GlobalCxt))));
185
0
  }
186
0
}
187
188
} // extern "C"
189
190
// The shims need default visibility to export the aliases; their own names are
191
// hidden by the `local:` list in `lib/api/libwasmedge.lds`.
192
__asm__(".symver WasmEdge_LimitIsEqual_Compat_016, "
193
        "WasmEdge_LimitIsEqual@WASMEDGE_0.16");
194
__asm__(".symver WasmEdge_TableTypeCreate_Compat_016, "
195
        "WasmEdge_TableTypeCreate@WASMEDGE_0.16");
196
__asm__(".symver WasmEdge_TableTypeGetLimit_Compat_016, "
197
        "WasmEdge_TableTypeGetLimit@WASMEDGE_0.16");
198
__asm__(".symver WasmEdge_MemoryTypeCreate_Compat_016, "
199
        "WasmEdge_MemoryTypeCreate@WASMEDGE_0.16");
200
__asm__(".symver WasmEdge_MemoryTypeGetLimit_Compat_016, "
201
        "WasmEdge_MemoryTypeGetLimit@WASMEDGE_0.16");
202
__asm__(".symver WasmEdge_ModuleInstanceAddFunction_Compat_017, "
203
        "WasmEdge_ModuleInstanceAddFunction@WASMEDGE_0.16");
204
__asm__(".symver WasmEdge_ModuleInstanceAddTable_Compat_017, "
205
        "WasmEdge_ModuleInstanceAddTable@WASMEDGE_0.16");
206
__asm__(".symver WasmEdge_ModuleInstanceAddMemory_Compat_017, "
207
        "WasmEdge_ModuleInstanceAddMemory@WASMEDGE_0.16");
208
__asm__(".symver WasmEdge_ModuleInstanceAddGlobal_Compat_017, "
209
        "WasmEdge_ModuleInstanceAddGlobal@WASMEDGE_0.16");
210
211
#endif // __ELF__ && (__linux__ || __ANDROID__)
212
213
// <<<<<<<< WasmEdge compat ABI shims <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<