1 /*
2 * Copyright (c) 2021-2024 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 "assembler/assembly-emitter.h"
17 #include "assembler/assembly-field.h"
18 #include "assembler/assembly-function.h"
19 #include "assembler/assembly-ins.h"
20 #include "assembler/assembly-parser.h"
21 #include "assembler/assembly-program.h"
22 #include "assembler/assembly-record.h"
23 #include "assembler/assembly-type.h"
24 #include "ins_create_api.h"
25
26 #include "ets_coroutine.h"
27
28 #include "runtime/include/runtime.h"
29 #include "runtime/mem/vm_handle.h"
30 #include "source_lang_enum.h"
31 #include "types/ets_array.h"
32 #include "types/ets_class.h"
33 #include "types/ets_field.h"
34 #include "types/ets_method.h"
35 #include "types/ets_primitives.h"
36 #include "types/ets_string.h"
37 #include "types/ets_typeapi_create_panda_constants.h"
38 #include "types/ets_type.h"
39 #include "types/ets_typeapi.h"
40 #include "types/ets_typeapi_create.h"
41
42 namespace ark::ets::intrinsics {
43 namespace {
44
ErrorFromCtx(TypeCreatorCtx * ctx)45 EtsString *ErrorFromCtx(TypeCreatorCtx *ctx)
46 {
47 if (auto err = ctx->GetError(); err) {
48 EtsString::CreateFromMUtf8(err.value().data(), err.value().size());
49 }
50 return nullptr;
51 }
52
GetPandasmTypeFromDescriptor(TypeCreatorCtx * ctx,std::string_view descriptor)53 pandasm::Type GetPandasmTypeFromDescriptor(TypeCreatorCtx *ctx, std::string_view descriptor)
54 {
55 auto ret = pandasm::Type::FromDescriptor(descriptor);
56 if (ret.IsObject()) {
57 auto pandasmName = ret.GetPandasmName();
58 ctx->AddRefTypeAsExternal(pandasmName);
59 return pandasm::Type {std::move(pandasmName), ret.GetRank()};
60 }
61 return ret;
62 }
63
EtsTypeToPandasm(EtsType type)64 pandasm::Type EtsTypeToPandasm(EtsType type)
65 {
66 ASSERT(type != EtsType::OBJECT);
67 return pandasm::Type::FromPrimitiveId(ConvertEtsTypeToPandaType(type).GetId());
68 }
69
GetReturnStatement(EtsType type)70 pandasm::Ins GetReturnStatement(EtsType type)
71 {
72 switch (type) {
73 case EtsType::BOOLEAN:
74 case EtsType::BYTE:
75 case EtsType::CHAR:
76 case EtsType::SHORT:
77 case EtsType::INT:
78 case EtsType::FLOAT:
79 return pandasm::Create_RETURN();
80 case EtsType::LONG:
81 case EtsType::DOUBLE:
82 return pandasm::Create_RETURN_64();
83 case EtsType::VOID:
84 return pandasm::Create_RETURN_VOID();
85 case EtsType::OBJECT:
86 return pandasm::Create_RETURN_OBJ();
87 case EtsType::UNKNOWN:
88 default:
89 UNREACHABLE();
90 }
91 }
92
CreateCopiedMethod(TypeCreatorCtx * ctx,const std::string & prefix,EtsMethod * method)93 PandasmMethodCreator CreateCopiedMethod(TypeCreatorCtx *ctx, const std::string &prefix, EtsMethod *method)
94 {
95 PandasmMethodCreator fn {prefix + method->GetName(), ctx};
96
97 size_t refNum = 0;
98
99 for (size_t argNum = 0; argNum < method->GetNumArgs(); argNum++) {
100 auto etsType = method->GetArgType(argNum);
101 if (etsType == EtsType::OBJECT) {
102 fn.AddParameter(GetPandasmTypeFromDescriptor(ctx, method->GetRefArgType(refNum++)));
103 } else {
104 fn.AddParameter(EtsTypeToPandasm(etsType));
105 }
106 }
107 auto etsRetType = method->GetReturnValueType();
108 if (etsRetType == EtsType::OBJECT) {
109 fn.AddResult(GetPandasmTypeFromDescriptor(ctx, method->GetReturnTypeDescriptor()));
110 } else {
111 fn.AddResult(EtsTypeToPandasm(etsRetType));
112 }
113
114 return fn;
115 }
116
SetAccessFlags(pandasm::ItemMetadata * meta,const std::string_view & attr,EtsTypeAPIAccessModifier mod)117 void SetAccessFlags(pandasm::ItemMetadata *meta, const std::string_view &attr, EtsTypeAPIAccessModifier mod)
118 {
119 switch (mod) {
120 case EtsTypeAPIAccessModifier::PUBLIC:
121 meta->SetAttributeValue(attr, typeapi_create_consts::ATTR_ACCESS_VAL_PUBLIC);
122 break;
123 case EtsTypeAPIAccessModifier::PRIVATE:
124 meta->SetAttributeValue(attr, typeapi_create_consts::ATTR_ACCESS_VAL_PRIVATE);
125 break;
126 case EtsTypeAPIAccessModifier::PROTECTED:
127 meta->SetAttributeValue(attr, typeapi_create_consts::ATTR_ACCESS_VAL_PROTECTED);
128 break;
129 default:
130 UNREACHABLE();
131 }
132 }
133
HasFeatureAttribute(EtsInt where,EtsTypeAPIAttributes attr)134 bool HasFeatureAttribute(EtsInt where, EtsTypeAPIAttributes attr)
135 {
136 static_assert(sizeof(EtsInt) == sizeof(uint32_t));
137 return (bit_cast<uint32_t>(static_cast<EtsInt>(attr)) & bit_cast<uint32_t>(where)) != 0;
138 }
139
140 template <typename T>
PtrFromLong(EtsLong ptr)141 T *PtrFromLong(EtsLong ptr)
142 {
143 return reinterpret_cast<T *>(ptr);
144 }
145
146 template <typename T>
PtrToLong(T * ptr)147 EtsLong PtrToLong(T *ptr)
148 {
149 return reinterpret_cast<EtsLong>(ptr);
150 }
151
152 } // namespace
153
154 extern "C" {
TypeAPITypeCreatorCtxCreate()155 EtsLong TypeAPITypeCreatorCtxCreate()
156 {
157 auto ret = Runtime::GetCurrent()->GetInternalAllocator()->New<TypeCreatorCtx>();
158 return reinterpret_cast<ssize_t>(ret);
159 }
160
TypeAPITypeCreatorCtxDestroy(EtsLong ctx)161 void TypeAPITypeCreatorCtxDestroy(EtsLong ctx)
162 {
163 Runtime::GetCurrent()->GetInternalAllocator()->Delete(PtrFromLong<TypeCreatorCtx>(ctx));
164 }
165
TypeAPITypeCreatorCtxCommit(EtsLong ctxPtr,EtsArray * objects)166 EtsString *TypeAPITypeCreatorCtxCommit(EtsLong ctxPtr, EtsArray *objects)
167 {
168 auto coroutine = EtsCoroutine::GetCurrent();
169 [[maybe_unused]] HandleScope<ObjectHeader *> scope(coroutine);
170 VMHandle<EtsArray> objectsHandle {coroutine, objects->GetCoreType()};
171
172 auto ctx = PtrFromLong<TypeCreatorCtx>(ctxPtr);
173
174 ctx->FlushTypeAPICtxDataRecordsToProgram();
175
176 panda_file::MemoryWriter writer;
177 auto status = pandasm::AsmEmitter::Emit(&writer, ctx->Program());
178 if (!status) {
179 return EtsString::CreateFromMUtf8(("can't write file in memory" + pandasm::AsmEmitter::GetLastError()).c_str());
180 }
181
182 // debug
183 // panda_file::FileWriter {"/tmp/test.abc"}.WriteBytes(writer.GetData());
184
185 auto linker = Runtime::GetCurrent()->GetClassLinker();
186 auto &data = writer.GetData();
187 auto file = panda_file::OpenPandaFileFromMemory(data.data(), data.size());
188
189 ctx->SaveObjects(coroutine, objectsHandle);
190
191 linker->AddPandaFile(std::move(file));
192
193 ctx->InitializeCtxDataRecord(coroutine);
194 return nullptr;
195 }
196
TypeAPITypeCreatorCtxClassCreate(EtsLong ctxPtr,EtsString * name,EtsInt attrs)197 EtsLong TypeAPITypeCreatorCtxClassCreate(EtsLong ctxPtr, EtsString *name, EtsInt attrs)
198 {
199 auto ctx = PtrFromLong<TypeCreatorCtx>(ctxPtr);
200 pandasm::Record rec {std::string {name->GetMutf8()}, SourceLanguage::ETS};
201 rec.conflict = true;
202
203 if (HasFeatureAttribute(attrs, EtsTypeAPIAttributes::FINAL)) {
204 rec.metadata->SetAttribute(typeapi_create_consts::ATTR_FINAL);
205 }
206
207 auto nameStr = rec.name;
208 auto [iter, ok] = ctx->Program().recordTable.emplace(nameStr, std::move(rec));
209 if (!ok) {
210 ctx->AddError("duplicate class " + nameStr);
211 return 0;
212 }
213 return PtrToLong(ctx->Alloc<ClassCreator>(&iter->second, ctx));
214 }
215
TypeAPITypeCreatorCtxInterfaceCreate(EtsLong ctxPtr,EtsString * name)216 EtsLong TypeAPITypeCreatorCtxInterfaceCreate(EtsLong ctxPtr, EtsString *name)
217 {
218 auto ctx = PtrFromLong<TypeCreatorCtx>(ctxPtr);
219 pandasm::Record rec {std::string {name->GetMutf8()}, SourceLanguage::ETS};
220 rec.conflict = true;
221 auto nameStr = rec.name;
222 for (const auto &attr : typeapi_create_consts::ATTR_INTERFACE) {
223 rec.metadata->SetAttribute(attr);
224 }
225 auto [iter, ok] = ctx->Program().recordTable.emplace(nameStr, std::move(rec));
226 if (!ok) {
227 ctx->AddError("duplicate class " + nameStr);
228 return 0;
229 }
230 return PtrToLong(ctx->Alloc<InterfaceCreator>(&iter->second, ctx));
231 }
232
TypeAPITypeCreatorCtxGetError(EtsLong ctxPtr)233 EtsString *TypeAPITypeCreatorCtxGetError(EtsLong ctxPtr)
234 {
235 auto ctx = PtrFromLong<TypeCreatorCtx>(ctxPtr);
236 return ErrorFromCtx(ctx);
237 }
238
TypeAPITypeCreatorCtxGetObjectsArrayForCCtor(EtsLong ctxPtr)239 EtsObject *TypeAPITypeCreatorCtxGetObjectsArrayForCCtor(EtsLong ctxPtr)
240 {
241 auto ctx = PtrFromLong<TypeCreatorCtx>(ctxPtr);
242 auto coro = EtsCoroutine::GetCurrent();
243 return ctx->GetObjects(coro)->AsObject();
244 }
245
TypeAPITypeCreatorCtxClassSetBase(EtsLong classPtr,EtsString * baseTd)246 EtsString *TypeAPITypeCreatorCtxClassSetBase(EtsLong classPtr, EtsString *baseTd)
247 {
248 auto creator = PtrFromLong<ClassCreator>(classPtr);
249 auto par = GetPandasmTypeFromDescriptor(creator->GetCtx(), baseTd->GetMutf8());
250 if (par.GetRank() != 0) {
251 return EtsString::CreateFromMUtf8("can't have array base");
252 }
253 creator->GetRec()->metadata->SetAttributeValue(typeapi_create_consts::ATTR_EXTENDS, par.GetName());
254 return nullptr;
255 }
256
TypeAPITypeCreatorCtxInterfaceAddBase(EtsLong ifacePtr,EtsString * baseTd)257 EtsString *TypeAPITypeCreatorCtxInterfaceAddBase(EtsLong ifacePtr, EtsString *baseTd)
258 {
259 auto creator = PtrFromLong<InterfaceCreator>(ifacePtr);
260 auto par = GetPandasmTypeFromDescriptor(creator->GetCtx(), baseTd->GetMutf8());
261 if (par.GetRank() != 0) {
262 return EtsString::CreateFromMUtf8("can't have array base");
263 }
264 creator->GetRec()->metadata->SetAttributeValue(typeapi_create_consts::ATTR_IMPLEMENTS, par.GetName());
265 return nullptr;
266 }
267
TypeAPITypeCreatorCtxGetTypeDescFromPointer(EtsLong nptr)268 EtsString *TypeAPITypeCreatorCtxGetTypeDescFromPointer(EtsLong nptr)
269 {
270 auto creator = PtrFromLong<TypeCreator>(nptr);
271 auto type = creator->GetType();
272 return EtsString::CreateFromMUtf8(type.GetDescriptor(!type.IsPrimitive()).c_str());
273 }
274
TypeAPITypeCreatorCtxMethodAddParam(EtsLong methodPtr,EtsString * paramTd,EtsString * name,EtsInt attrs)275 EtsString *TypeAPITypeCreatorCtxMethodAddParam(EtsLong methodPtr, EtsString *paramTd, [[maybe_unused]] EtsString *name,
276 [[maybe_unused]] EtsInt attrs)
277 {
278 // NOTE(kprokopenko): dump meta info
279 auto m = PtrFromLong<PandasmMethodCreator>(methodPtr);
280 auto type = GetPandasmTypeFromDescriptor(m->Ctx(), paramTd->GetMutf8());
281 m->AddParameter(std::move(type));
282 return nullptr;
283 }
284
TypeAPITypeCreatorCtxMethodCreate(EtsLong containingTypePtr,EtsString * name,EtsInt attrs)285 EtsLong TypeAPITypeCreatorCtxMethodCreate(EtsLong containingTypePtr, EtsString *name, EtsInt attrs)
286 {
287 auto klass = PtrFromLong<ClassCreator>(containingTypePtr);
288 auto nameStr = klass->GetRec()->name;
289 nameStr += ".";
290 if (HasFeatureAttribute(attrs, EtsTypeAPIAttributes::CONSTRUCTOR)) {
291 nameStr += panda_file::GetCtorName(SourceLanguage::ETS);
292 } else {
293 if (HasFeatureAttribute(attrs, EtsTypeAPIAttributes::GETTER)) {
294 nameStr += GETTER_BEGIN;
295 } else if (HasFeatureAttribute(attrs, EtsTypeAPIAttributes::SETTER)) {
296 nameStr += SETTER_BEGIN;
297 }
298 nameStr += name->GetMutf8();
299 }
300 auto ret = klass->GetCtx()->Alloc<PandasmMethodCreator>(std::move(nameStr), klass->GetCtx());
301 if (HasFeatureAttribute(attrs, EtsTypeAPIAttributes::STATIC)) {
302 ret->GetFn().metadata->SetAttribute(typeapi_create_consts::ATTR_STATIC);
303 } else {
304 ret->GetFn().params.emplace_back(pandasm::Type {klass->GetRec()->name, 0}, SourceLanguage::ETS);
305 }
306 if (HasFeatureAttribute(attrs, EtsTypeAPIAttributes::ABSTRACT)) {
307 ret->GetFn().metadata->SetAttribute(typeapi_create_consts::ATTR_NOIMPL);
308 }
309 if (HasFeatureAttribute(attrs, EtsTypeAPIAttributes::CONSTRUCTOR)) {
310 ret->GetFn().metadata->SetAttribute(typeapi_create_consts::ATTR_CTOR);
311 }
312 return PtrToLong(ret);
313 }
314
TypeAPITypeCreatorCtxMethodAddAccessMod(EtsLong methodPtr,EtsInt access)315 EtsString *TypeAPITypeCreatorCtxMethodAddAccessMod(EtsLong methodPtr, EtsInt access)
316 {
317 auto m = PtrFromLong<PandasmMethodCreator>(methodPtr);
318 auto accessMod = static_cast<EtsTypeAPIAccessModifier>(access);
319 SetAccessFlags(m->GetFn().metadata.get(), typeapi_create_consts::ATTR_ACCESS_FUNCTION, accessMod);
320 return ErrorFromCtx(m->Ctx());
321 }
322
TypeAPITypeCreatorCtxMethodAdd(EtsLong methodPtr)323 EtsString *TypeAPITypeCreatorCtxMethodAdd(EtsLong methodPtr)
324 {
325 auto m = PtrFromLong<PandasmMethodCreator>(methodPtr);
326 m->Create();
327 return ErrorFromCtx(m->Ctx());
328 }
329
TypeAPITypeCreatorCtxMethodAddBodyFromMethod(EtsLong methodPtr,EtsString * methodDesc)330 EtsString *TypeAPITypeCreatorCtxMethodAddBodyFromMethod(EtsLong methodPtr, EtsString *methodDesc)
331 {
332 auto m = PtrFromLong<PandasmMethodCreator>(methodPtr);
333 auto meth = EtsMethod::FromTypeDescriptor(methodDesc->GetMutf8());
334 auto ctx = m->Ctx();
335
336 auto parentMethodClassName = GetPandasmTypeFromDescriptor(m->Ctx(), meth->GetClass()->GetDescriptor());
337
338 // NOTE(kprokopenko): implement type checking
339
340 auto parentMethod = CreateCopiedMethod(ctx, parentMethodClassName.GetName() + ".", meth);
341 parentMethod.GetFn().metadata->SetAttribute(typeapi_create_consts::ATTR_EXTERNAL);
342 parentMethod.Create();
343
344 m->GetFn().AddInstruction(pandasm::Create_CALL_RANGE(0, parentMethod.GetFunctionName()));
345 m->GetFn().AddInstruction(GetReturnStatement(meth->GetReturnValueType()));
346
347 return ErrorFromCtx(m->Ctx());
348 }
349
TypeAPITypeCreatorCtxMethodAddBodyFromLambda(EtsLong methodPtr,EtsInt lambdaObjectId,EtsString * lambdaTd)350 EtsString *TypeAPITypeCreatorCtxMethodAddBodyFromLambda(EtsLong methodPtr, EtsInt lambdaObjectId, EtsString *lambdaTd)
351 {
352 auto m = PtrFromLong<PandasmMethodCreator>(methodPtr);
353 auto ctx = m->Ctx();
354
355 auto coro = EtsCoroutine::GetCurrent();
356 auto klassTd = lambdaTd->GetMutf8();
357 auto klassName = GetPandasmTypeFromDescriptor(m->Ctx(), klassTd);
358 auto klass = coro->GetPandaVM()->GetClassLinker()->GetClass(klassTd.c_str());
359 ASSERT(klass->IsInitialized());
360 auto meth = klass->GetMethod("invoke");
361 if (meth == nullptr) {
362 return EtsString::CreateFromMUtf8("method is absent");
363 }
364
365 auto fld = m->Ctx()->AddInitField(lambdaObjectId, pandasm::Type {klassName, 0});
366
367 auto externalFn = CreateCopiedMethod(ctx, klassName.GetName() + ".", meth);
368 externalFn.GetFn().metadata->SetAttribute(typeapi_create_consts::ATTR_EXTERNAL);
369 externalFn.Create();
370
371 m->GetFn().regsNum = 1;
372 m->GetFn().AddInstruction(pandasm::Create_LDSTATIC_OBJ(fld));
373 m->GetFn().AddInstruction(pandasm::Create_STA_OBJ(0));
374 if (EtsMethod::ToRuntimeMethod(meth)->IsFinal()) {
375 m->GetFn().AddInstruction(pandasm::Create_CALL_RANGE(0, externalFn.GetFunctionName()));
376 } else {
377 m->GetFn().AddInstruction(pandasm::Create_CALL_VIRT_RANGE(0, externalFn.GetFunctionName()));
378 }
379
380 m->GetFn().AddInstruction(GetReturnStatement(meth->GetReturnValueType()));
381
382 return ErrorFromCtx(m->Ctx());
383 }
384
PrepareLambdaTypeCreator(TypeCreatorCtx * ctx)385 static LambdaTypeCreator PrepareLambdaTypeCreator(TypeCreatorCtx *ctx)
386 {
387 LambdaTypeCreator lambda {ctx};
388 lambda.AddParameter(pandasm::Type {typeapi_create_consts::TYPE_OBJECT, 0});
389 lambda.AddParameter(pandasm::Type {typeapi_create_consts::TYPE_OBJECT, 0});
390 lambda.AddResult(pandasm::Type {typeapi_create_consts::TYPE_OBJECT, 0});
391 lambda.Create();
392 return lambda;
393 }
394
395 static constexpr int TMP_REG = 0;
396 static constexpr int LMB_REG = 0;
397 static constexpr int RECV_REG = LMB_REG + 1;
398 static constexpr int ARR_REG = RECV_REG + 1;
399 static constexpr int ARGS_REG_START = ARR_REG + 1;
400
AddLambdaParamInst(pandasm::Function & fn,TypeCreatorCtx * ctx)401 static void AddLambdaParamInst(pandasm::Function &fn, TypeCreatorCtx *ctx)
402 {
403 const auto isStatic = fn.metadata->GetAttribute(std::string {typeapi_create_consts::ATTR_STATIC});
404 for (size_t i = 0; i < fn.params.size(); i++) {
405 // adjust array store index
406 const auto &par = fn.params[i];
407 if (i != 0 && (i != 1 || isStatic)) {
408 fn.AddInstruction(pandasm::Create_INCI(TMP_REG, 1));
409 }
410 if (par.type.IsObject()) {
411 fn.AddInstruction(pandasm::Create_LDA_OBJ(ARGS_REG_START + i));
412 } else {
413 auto ctor = ctx->DeclarePrimitive(par.type.GetComponentName()).first;
414 fn.AddInstruction(pandasm::Create_INITOBJ_SHORT(ARGS_REG_START + i, 0, ctor));
415 }
416 if (i == 0 && !isStatic) {
417 // set recv
418 fn.AddInstruction(pandasm::Create_STA_OBJ(RECV_REG));
419 } else {
420 // set arg
421 fn.AddInstruction(pandasm::Create_STARR_OBJ(ARR_REG, TMP_REG));
422 }
423 }
424 }
425
TypeAPITypeCreatorCtxMethodAddBodyFromErasedLambda(EtsLong methodPtr,EtsInt lambdaId)426 EtsString *TypeAPITypeCreatorCtxMethodAddBodyFromErasedLambda(EtsLong methodPtr, EtsInt lambdaId)
427 {
428 auto m = PtrFromLong<PandasmMethodCreator>(methodPtr);
429
430 m->Ctx()->AddRefTypeAsExternal(std::string {typeapi_create_consts::TYPE_OBJECT});
431
432 auto lambda = PrepareLambdaTypeCreator(m->Ctx());
433
434 auto savedLambdaField = m->Ctx()->AddInitField(lambdaId, lambda.GetType());
435
436 auto &fn = m->GetFn();
437 auto isStatic = fn.metadata->GetAttribute(std::string {typeapi_create_consts::ATTR_STATIC});
438 fn.regsNum = ARGS_REG_START;
439 const auto &ret = fn.returnType;
440 auto pars = fn.params.size();
441 auto arrLen = pars - (isStatic ? 0 : 1);
442 fn.AddInstruction(pandasm::Create_MOVI(TMP_REG, arrLen));
443 fn.AddInstruction(
444 pandasm::Create_NEWARR(ARR_REG, TMP_REG, pandasm::Type {typeapi_create_consts::TYPE_OBJECT, 1}.GetName()));
445
446 fn.AddInstruction(pandasm::Create_MOVI(TMP_REG, 0));
447
448 if (isStatic) {
449 fn.AddInstruction(pandasm::Create_LDA_NULL());
450 fn.AddInstruction(pandasm::Create_STA_OBJ(RECV_REG));
451 }
452
453 AddLambdaParamInst(fn, m->Ctx());
454
455 fn.AddInstruction(pandasm::Create_LDSTATIC_OBJ(savedLambdaField));
456 fn.AddInstruction(pandasm::Create_STA_OBJ(LMB_REG));
457
458 fn.AddInstruction(pandasm::Create_CALL_VIRT(LMB_REG, RECV_REG, ARR_REG, 0, lambda.GetFunctionName()));
459
460 fn.AddInstruction(pandasm::Create_STA_OBJ(0));
461 if (!fn.returnType.IsObject()) {
462 auto destr = m->Ctx()->DeclarePrimitive(fn.returnType.GetComponentName()).second;
463 fn.AddInstruction(pandasm::Create_CALL_SHORT(0, 0, destr));
464 }
465
466 if (fn.returnType.IsObject()) {
467 fn.AddInstruction(pandasm::Create_CHECKCAST(ret.GetName()));
468 }
469 auto returnId = fn.returnType.GetId();
470 fn.AddInstruction(GetReturnStatement(ConvertPandaTypeToEtsType(panda_file::Type {returnId})));
471
472 return ErrorFromCtx(m->Ctx());
473 }
474
TypeAPITypeCreatorCtxMethodAddBodyDefault(EtsLong methodPtr)475 EtsString *TypeAPITypeCreatorCtxMethodAddBodyDefault(EtsLong methodPtr)
476 {
477 auto m = PtrFromLong<PandasmMethodCreator>(methodPtr);
478 auto &fn = m->GetFn();
479
480 // call default constructor in case of constructor
481 if (fn.metadata->IsCtor()) {
482 auto selfName = m->GetFn().params.front().type.GetName();
483 auto &recordTable = m->Ctx()->Program().recordTable;
484 // clang-format off
485 auto superName = recordTable.find(selfName)
486 ->second.metadata->GetAttributeValue(std::string {typeapi_create_consts::ATTR_EXTENDS})
487 .value();
488 // clang-format on
489 m->Ctx()->AddRefTypeAsExternal(superName);
490 PandasmMethodCreator superCtor {superName + "." + panda_file::GetCtorName(panda_file::SourceLang::ETS),
491 m->Ctx()};
492 superCtor.AddParameter(pandasm::Type {superName, 0, true});
493 superCtor.GetFn().metadata->SetAttribute(typeapi_create_consts::ATTR_EXTERNAL);
494 superCtor.Create();
495
496 fn.AddInstruction(pandasm::Create_CALL_SHORT(0, 0, superCtor.GetFunctionName()));
497 }
498
499 const auto &ret = fn.returnType;
500 if (ret.IsVoid()) {
501 fn.AddInstruction(pandasm::Create_RETURN_VOID());
502 } else if (ret.IsObject()) {
503 fn.AddInstruction(pandasm::Create_LDA_NULL());
504 fn.AddInstruction(pandasm::Create_RETURN_OBJ());
505 // return EtsString::CreateFromMUtf8("can't make default return for object type");
506 } else if (ret.IsFloat32()) {
507 fn.AddInstruction(pandasm::Create_FLDAI(0));
508 fn.AddInstruction(pandasm::Create_RETURN());
509 } else if (ret.IsFloat64()) {
510 fn.AddInstruction(pandasm::Create_FLDAI_64(0));
511 fn.AddInstruction(pandasm::Create_RETURN_64());
512 } else if (ret.IsPrim64()) {
513 fn.AddInstruction(pandasm::Create_LDAI_64(0));
514 fn.AddInstruction(pandasm::Create_RETURN_64());
515 } else {
516 fn.AddInstruction(pandasm::Create_LDAI(0));
517 fn.AddInstruction(pandasm::Create_RETURN());
518 }
519
520 return ErrorFromCtx(m->Ctx());
521 }
522
TypeAPITypeCreatorCtxMethodAddResult(EtsLong methodPtr,EtsString * descriptor)523 EtsString *TypeAPITypeCreatorCtxMethodAddResult(EtsLong methodPtr, EtsString *descriptor)
524 {
525 auto m = PtrFromLong<PandasmMethodCreator>(methodPtr);
526 m->AddResult(GetPandasmTypeFromDescriptor(m->Ctx(), descriptor->GetMutf8().c_str()));
527 return ErrorFromCtx(m->Ctx());
528 }
529
TypeAPITypeCreatorCtxLambdaTypeCreate(EtsLong ctxPtr,EtsInt attrs)530 EtsLong TypeAPITypeCreatorCtxLambdaTypeCreate(EtsLong ctxPtr, [[maybe_unused]] EtsInt attrs)
531 {
532 auto ctx = PtrFromLong<TypeCreatorCtx>(ctxPtr);
533 // NOTE(kprokopenko): add attributes
534 auto fn = ctx->Alloc<LambdaTypeCreator>(ctx);
535 return PtrToLong(fn);
536 }
537
TypeAPITypeCreatorCtxLambdaTypeAddParam(EtsLong ftPtr,EtsString * td,EtsInt attrs)538 EtsString *TypeAPITypeCreatorCtxLambdaTypeAddParam(EtsLong ftPtr, EtsString *td, [[maybe_unused]] EtsInt attrs)
539 {
540 // NOTE(kprokopenko): dump meta info
541 auto creator = PtrFromLong<LambdaTypeCreator>(ftPtr);
542 creator->AddParameter(GetPandasmTypeFromDescriptor(creator->GetCtx(), td->GetMutf8()));
543 return ErrorFromCtx(creator->GetCtx());
544 }
545
TypeAPITypeCreatorCtxLambdaTypeAddResult(EtsLong ftPtr,EtsString * td)546 EtsString *TypeAPITypeCreatorCtxLambdaTypeAddResult(EtsLong ftPtr, EtsString *td)
547 {
548 auto creator = PtrFromLong<LambdaTypeCreator>(ftPtr);
549 creator->AddResult(GetPandasmTypeFromDescriptor(creator->GetCtx(), td->GetMutf8()));
550 return ErrorFromCtx(creator->GetCtx());
551 }
552
TypeAPITypeCreatorCtxLambdaTypeAdd(EtsLong ftPtr)553 EtsString *TypeAPITypeCreatorCtxLambdaTypeAdd(EtsLong ftPtr)
554 {
555 auto creator = PtrFromLong<LambdaTypeCreator>(ftPtr);
556 creator->Create();
557 return ErrorFromCtx(creator->GetCtx());
558 }
559
TypeAPITypeCreatorCtxClassAddIface(EtsLong classPtr,EtsString * descr)560 EtsString *TypeAPITypeCreatorCtxClassAddIface(EtsLong classPtr, EtsString *descr)
561 {
562 auto creator = PtrFromLong<ClassCreator>(classPtr);
563 auto iface = GetPandasmTypeFromDescriptor(creator->GetCtx(), descr->GetMutf8());
564 creator->GetRec()->metadata->SetAttributeValue(typeapi_create_consts::ATTR_IMPLEMENTS, iface.GetName());
565 return ErrorFromCtx(creator->GetCtx());
566 }
567
TypeAPITypeCreatorCtxClassAddField(EtsLong classPtr,EtsString * name,EtsString * descr,EtsInt attrs,EtsInt access)568 EtsString *TypeAPITypeCreatorCtxClassAddField(EtsLong classPtr, EtsString *name, EtsString *descr, EtsInt attrs,
569 EtsInt access)
570 {
571 auto klass = PtrFromLong<ClassCreator>(classPtr);
572 auto type = GetPandasmTypeFromDescriptor(klass->GetCtx(), descr->GetMutf8());
573 pandasm::Field fld {SourceLanguage::ETS};
574 if (HasFeatureAttribute(attrs, EtsTypeAPIAttributes::STATIC)) {
575 fld.metadata->SetAttribute(typeapi_create_consts::ATTR_STATIC);
576 }
577 if (HasFeatureAttribute(attrs, EtsTypeAPIAttributes::READONLY)) {
578 fld.metadata->SetAttribute(typeapi_create_consts::ATTR_FINAL);
579 }
580 fld.name = name->GetMutf8();
581 fld.type = pandasm::Type(type, 0);
582 auto accessMod = static_cast<EtsTypeAPIAccessModifier>(access);
583 SetAccessFlags(fld.metadata.get(), typeapi_create_consts::ATTR_ACCESS_FIELD, accessMod);
584 klass->GetRec()->fieldList.emplace_back(std::move(fld));
585 return ErrorFromCtx(klass->GetCtx());
586 }
587 }
588
589 } // namespace ark::ets::intrinsics
590