• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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