/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 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |