1 /*
2 * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <common.h>
17 #include <utility>
18
19 using std::string, std::cout, std::endl, std::vector;
20
21 static es2panda_Impl *impl = nullptr;
22
23 static thread_local StageArena currentArena;
24
instance()25 StageArena* StageArena::instance()
26 {
27 return ¤tArena;
28 }
29
add(void * pointer)30 void StageArena::add(void* pointer)
31 {
32 if (pointer)
33 allocated.push_back(pointer);
34 }
35
cleanup()36 void StageArena::cleanup()
37 {
38 if (totalSize > 0 && false)
39 printf("cleanup %d objects %d bytes\n", (int)allocated.size(), (int)totalSize);
40 for (auto it : allocated) {
41 free(it);
42 }
43 totalSize = 0;
44 allocated.clear();
45 }
46
StageArena()47 StageArena::StageArena()
48 {
49 totalSize = 0;
50 }
51
~StageArena()52 StageArena::~StageArena()
53 {
54 cleanup();
55 }
56
strdup(const char * string)57 char* StageArena::strdup(const char* string)
58 {
59 auto* arena = StageArena::instance();
60 auto size = strlen(string) + 1;
61 char* memory = (char*)arena->alloc(size);
62 memcpy(memory, string, size);
63 return memory;
64 }
65
alloc(size_t size)66 void* StageArena::alloc(size_t size)
67 {
68 void* result = malloc(size);
69 totalSize += size;
70 add(result);
71 return result;
72 }
73
74 #ifdef KOALA_WINDOWS
75 #include <windows.h>
76 #define PLUGIN_DIR "windows_host_tools"
77 #define LIB_PREFIX ""
78 #define LIB_SUFFIX ".dll"
79 #endif
80
81 #ifdef KOALA_LINUX
82 #include <dlfcn.h>
83
84 #ifdef __x86_64__
85 #define PLUGIN_DIR "linux_host_tools"
86 #else
87 #define PLUGIN_DIR "linux_arm64_host_tools"
88 #endif
89
90 #define LIB_PREFIX "lib"
91 #define LIB_SUFFIX ".so"
92 #endif
93
94 const char* DEFAULT_SDK_PATH = "../../../incremental/tools/panda/node_modules/@panda/sdk" ;
95 const char* NAME = LIB_PREFIX "es2panda-public" LIB_SUFFIX;
96
FindLibrary()97 void* FindLibrary()
98 {
99 char* envValue = getenv("PANDA_SDK_PATH");
100 if (!envValue) {
101 std::cout << "PANDA_SDK_PATH not specified, assuming " << DEFAULT_SDK_PATH << std::endl;
102 }
103 std::string prefix = envValue ? std::string(envValue) : DEFAULT_SDK_PATH;
104 std::string libraryName = prefix + ("/" PLUGIN_DIR "/lib/") + NAME;
105 return loadLibrary(libraryName);
106 }
107
GetImpl()108 es2panda_Impl *GetImpl()
109 {
110 if (impl) {
111 return impl;
112 }
113 auto library = FindLibrary();
114 if (!library) {
115 printf("No library (es2panda_lib.cc)");
116 abort();
117 }
118 auto symbol = findSymbol(library, "es2panda_GetImpl");
119 if (!symbol) {
120 printf("no entry point");
121 abort();
122 }
123 impl = reinterpret_cast<es2panda_Impl *(*)(int)>(symbol)(ES2PANDA_LIB_VERSION);
124 return impl;
125 }
126
intToState(KInt state)127 es2panda_ContextState intToState(KInt state)
128 {
129 return es2panda_ContextState(state);
130 }
131
getString(KStringPtr ptr)132 string getString(KStringPtr ptr)
133 {
134 return ptr.data();
135 }
136
getStringCopy(KStringPtr & ptr)137 char* getStringCopy(KStringPtr& ptr)
138 {
139 return StageArena::strdup(ptr.c_str() ? ptr.c_str() : "");
140 }
141
unpackUInt(const KByte * bytes)142 inline KUInt unpackUInt(const KByte* bytes)
143 {
144 const KUInt BYTE_0 = 0;
145 const KUInt BYTE_1 = 1;
146 const KUInt BYTE_2 = 2;
147 const KUInt BYTE_3 = 3;
148
149 const KUInt BYTE_1_SHIFT = 8;
150 const KUInt BYTE_2_SHIFT = 16;
151 const KUInt BYTE_3_SHIFT = 24;
152 return (
153 bytes[BYTE_0]
154 | (bytes[BYTE_1] << BYTE_1_SHIFT)
155 | (bytes[BYTE_2] << BYTE_2_SHIFT)
156 | (bytes[BYTE_3] << BYTE_3_SHIFT)
157 );
158 }
159
impl_CreateConfig(KInt argc,KStringArray argvPtr)160 KNativePointer impl_CreateConfig(KInt argc, KStringArray argvPtr) {
161 const std::size_t headerLen = 4;
162
163 const char** argv = StageArena::allocArray<const char*>(argc);
164 std::size_t position = headerLen;
165 std::size_t strLen;
166 for (std::size_t i = 0; i < static_cast<std::size_t>(argc); ++i) {
167 strLen = unpackUInt(argvPtr + position);
168 position += headerLen;
169 argv[i] = StageArena::strdup(std::string(reinterpret_cast<const char*>(argvPtr + position), strLen).c_str());
170 position += strLen;
171 }
172 return GetImpl()->CreateConfig(argc, argv);
173 }
KOALA_INTEROP_2(CreateConfig,KNativePointer,KInt,KStringArray)174 KOALA_INTEROP_2(CreateConfig, KNativePointer, KInt, KStringArray)
175
176 KNativePointer impl_DestroyConfig(KNativePointer configPtr) {
177 auto config = reinterpret_cast<es2panda_Config*>(configPtr);
178 GetImpl()->DestroyConfig(config);
179 return nullptr;
180 }
KOALA_INTEROP_1(DestroyConfig,KNativePointer,KNativePointer)181 KOALA_INTEROP_1(DestroyConfig, KNativePointer, KNativePointer)
182
183 KNativePointer impl_DestroyContext(KNativePointer contextPtr) {
184 auto context = reinterpret_cast<es2panda_Context*>(contextPtr);
185 GetImpl()->DestroyContext(context);
186 StageArena::instance()->cleanup();
187 return nullptr;
188 }
KOALA_INTEROP_1(DestroyContext,KNativePointer,KNativePointer)189 KOALA_INTEROP_1(DestroyContext, KNativePointer, KNativePointer)
190
191 KNativePointer impl_UpdateCallExpression(
192 KNativePointer contextPtr,
193 KNativePointer nodePtr,
194 KNativePointer calleePtr,
195 KNativePointerArray argumentsPtr,
196 KInt argumentsLen,
197 KNativePointer typeParamsPtr,
198 KBoolean optionalT,
199 KBoolean trailingCommaT
200 ) {
201 auto node = reinterpret_cast<es2panda_AstNode*>(nodePtr);
202 auto context = reinterpret_cast<es2panda_Context*>(contextPtr);
203 auto callee = reinterpret_cast<es2panda_AstNode*>(calleePtr);
204 auto arguments = reinterpret_cast<es2panda_AstNode**>(argumentsPtr);
205 auto typeParams = reinterpret_cast<es2panda_AstNode*>(typeParamsPtr);
206 auto optional = static_cast<bool>(optionalT);
207 auto trailingComma = static_cast<bool>(trailingCommaT);
208
209 auto nn = GetImpl()->CreateCallExpression(
210 context, callee, arguments, argumentsLen, typeParams, optional, trailingComma
211 );
212 GetImpl()->AstNodeSetOriginalNode(context, nn, node);
213 return nn;
214 }
KOALA_INTEROP_8(UpdateCallExpression,KNativePointer,KNativePointer,KNativePointer,KNativePointer,KNativePointerArray,KInt,KNativePointer,KBoolean,KBoolean)215 KOALA_INTEROP_8(UpdateCallExpression, KNativePointer, KNativePointer, KNativePointer, KNativePointer, KNativePointerArray, KInt, KNativePointer, KBoolean, KBoolean)
216
217 KInt impl_IdentifierIdentifierFlags(KNativePointer contextPtr, KNativePointer nodePtr) {
218 auto context = reinterpret_cast<es2panda_Context*>(contextPtr);
219 auto node = reinterpret_cast<es2panda_AstNode*>(nodePtr);
220
221 return
222 (GetImpl()->IdentifierIsOptionalConst(context, node) ? (1 << 0) : 0) |
223 (GetImpl()->IdentifierIsReferenceConst(context, node) ? (1 << 1) : 0) |
224 (GetImpl()->IdentifierIsTdzConst(context, node) ? (1 << 2) : 0);
225 }
226 KOALA_INTEROP_2(IdentifierIdentifierFlags, KInt, KNativePointer, KNativePointer)
227
228 /*
229 TODO: NOT FROM API (shouldn't be there)
230 -----------------------------------------------------------------------------------------------------------------------------
231 */
232
233 es2panda_AstNode * cachedParentNode;
234 es2panda_Context * cachedContext;
235
changeParent(es2panda_AstNode * child)236 static void changeParent(es2panda_AstNode *child)
237 {
238 GetImpl()->AstNodeSetParent(cachedContext, child, cachedParentNode);
239 }
240
SetRightParent(es2panda_AstNode * node,void * arg)241 static void SetRightParent(es2panda_AstNode *node, void *arg)
242 {
243 es2panda_Context *ctx = static_cast<es2panda_Context *>(arg);
244 cachedContext = ctx;
245 cachedParentNode = node;
246
247 GetImpl()->AstNodeIterateConst(ctx, node, changeParent);
248 }
249
impl_AstNodeUpdateAll(KNativePointer contextPtr,KNativePointer programPtr)250 KNativePointer impl_AstNodeUpdateAll(KNativePointer contextPtr, KNativePointer programPtr) {
251 auto context = reinterpret_cast<es2panda_Context*>(contextPtr);
252 auto program = reinterpret_cast<es2panda_AstNode*>(programPtr);
253
254 GetImpl()->AstNodeForEach(program, SetRightParent, context);
255 return program;
256 }
KOALA_INTEROP_2(AstNodeUpdateAll,KNativePointer,KNativePointer,KNativePointer)257 KOALA_INTEROP_2(AstNodeUpdateAll, KNativePointer, KNativePointer, KNativePointer)
258
259 KNativePointer impl_AstNodeUpdateChildren(KNativePointer contextPtr, KNativePointer nodePtr) {
260 auto context = reinterpret_cast<es2panda_Context*>(contextPtr);
261 auto node = reinterpret_cast<es2panda_AstNode*>(nodePtr);
262 cachedParentNode = node;
263
264 GetImpl()->AstNodeIterateConst(context, node, changeParent);
265 return node;
266 }
267 KOALA_INTEROP_2(AstNodeUpdateChildren, KNativePointer, KNativePointer, KNativePointer)
268
269 std::vector<void*> cachedChildren;
270
visitChild(es2panda_AstNode * node)271 static void visitChild(es2panda_AstNode *node)
272 {
273 cachedChildren.emplace_back(node);
274 }
275
impl_AstNodeChildren(KNativePointer contextPtr,KNativePointer nodePtr)276 KNativePointer impl_AstNodeChildren(
277 KNativePointer contextPtr,
278 KNativePointer nodePtr
279 ) {
280 auto context = reinterpret_cast<es2panda_Context*>(contextPtr);
281 auto node = reinterpret_cast<es2panda_AstNode*>(nodePtr);
282 cachedContext = context;
283 cachedChildren.clear();
284
285 GetImpl()->AstNodeIterateConst(context, node, visitChild);
286 return StageArena::clone(cachedChildren);
287 }
288 KOALA_INTEROP_2(AstNodeChildren, KNativePointer, KNativePointer, KNativePointer)
289
290 /*
291 -----------------------------------------------------------------------------------------------------------------------------
292 */
293