• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 - 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 "ETSemitter.h"
17 
18 #include "compiler/core/ETSGen.h"
19 #include "varbinder/varbinder.h"
20 #include "varbinder/variableFlags.h"
21 #include "varbinder/ETSBinder.h"
22 #include "ir/astNode.h"
23 #include "ir/expressions/identifier.h"
24 #include "ir/base/decorator.h"
25 #include "ir/base/methodDefinition.h"
26 #include "ir/base/classDefinition.h"
27 #include "ir/base/scriptFunction.h"
28 #include "ir/base/classProperty.h"
29 #include "ir/ts/tsEnumDeclaration.h"
30 #include "ir/ts/tsEnumMember.h"
31 #include "ir/ts/tsInterfaceDeclaration.h"
32 #include "ir/ts/tsInterfaceBody.h"
33 #include "ir/ts/tsTypeParameterDeclaration.h"
34 #include "ir/ts/tsTypeParameter.h"
35 #include "ir/typeNode.h"
36 #include "parser/program/program.h"
37 #include "compiler/core/compilerContext.h"
38 #include "checker/checker.h"
39 #include "checker/types/signature.h"
40 #include "checker/ETSchecker.h"
41 #include "checker/types/type.h"
42 #include "checker/types/ets/types.h"
43 
44 #include "assembly-program.h"
45 
46 namespace panda::es2panda::compiler {
47 
48 #ifdef PANDA_WITH_ETS
49 static constexpr auto EXTENSION = panda_file::SourceLang::ETS;
50 #else
51 // NOTE: temporary dummy gn buildfix until ETS plugin has gn build support
52 static constexpr auto EXTENSION = panda_file::SourceLang::PANDA_ASSEMBLY;
53 #endif
54 
TranslateModifierFlags(ir::ModifierFlags modifierFlags)55 static uint32_t TranslateModifierFlags(ir::ModifierFlags modifierFlags)
56 {
57     uint32_t accessFlags = 0;
58 
59     if ((modifierFlags & ir::ModifierFlags::PRIVATE) != 0) {
60         accessFlags = ACC_PRIVATE;
61     } else if ((modifierFlags & ir::ModifierFlags::INTERNAL) != 0) {
62         if ((modifierFlags & ir::ModifierFlags::PROTECTED) != 0) {
63             accessFlags = ACC_PROTECTED;
64         }
65         // NOTE: torokg. Add ACC_INTERNAL access flag to libpandabase
66     } else if ((modifierFlags & ir::ModifierFlags::PROTECTED) != 0) {
67         accessFlags = ACC_PROTECTED;
68     } else {
69         accessFlags = ACC_PUBLIC;
70     }
71 
72     if ((modifierFlags & ir::ModifierFlags::STATIC) != 0) {
73         accessFlags |= ACC_STATIC;
74     }
75 
76     if ((modifierFlags & ir::ModifierFlags::CONST) != 0) {
77         accessFlags |= ACC_FINAL;
78     }
79 
80     if ((modifierFlags & ir::ModifierFlags::ABSTRACT) != 0) {
81         accessFlags |= ACC_ABSTRACT;
82     }
83 
84     if ((modifierFlags & ir::ModifierFlags::NATIVE) != 0) {
85         accessFlags |= ACC_NATIVE;
86     }
87 
88     return accessFlags;
89 }
90 
GenScriptFunction(CompilerContext const * context,const ir::ScriptFunction * scriptFunc)91 static pandasm::Function GenScriptFunction(CompilerContext const *context, const ir::ScriptFunction *scriptFunc)
92 {
93     auto *funcScope = scriptFunc->Scope();
94     auto *paramScope = funcScope->ParamScope();
95 
96     auto func = pandasm::Function(funcScope->InternalName().Mutf8(), EXTENSION);
97 
98     func.params.reserve(paramScope->Params().size());
99 
100     for (const auto *var : paramScope->Params()) {
101         std::stringstream ss;
102         context->Checker()->AsETSChecker()->MaybeBoxedType(var)->ToAssemblerType(ss);
103         func.params.emplace_back(pandasm::Type(ss.str(), var->TsType()->Rank()), EXTENSION);
104     }
105 
106     std::stringstream ss;
107 
108     if (scriptFunc->IsConstructor() || scriptFunc->IsStaticBlock()) {
109         func.returnType = pandasm::Type(Signatures::PRIMITIVE_VOID, 0);
110     } else {
111         const auto *returnType = scriptFunc->Signature()->ReturnType();
112 
113         returnType->ToAssemblerType(ss);
114         ASSERT(!ss.str().empty());
115         func.returnType = pandasm::Type(ss.str(), returnType->Rank());
116     }
117 
118     if (!scriptFunc->IsStaticBlock()) {
119         const auto *methodDef = util::Helpers::GetContainingClassMethodDefinition(scriptFunc);
120         func.metadata->SetAccessFlags(TranslateModifierFlags(methodDef->Modifiers()));
121     }
122 
123     return func;
124 }
125 
GenFunctionSignature()126 pandasm::Function *ETSFunctionEmitter::GenFunctionSignature()
127 {
128     auto func = GenScriptFunction(Cg()->Context(), Cg()->RootNode()->AsScriptFunction());
129     auto *funcElement = new pandasm::Function(func.name, func.language);
130     *funcElement = std::move(func);
131     GetProgramElement()->SetFunction(funcElement);
132     funcElement->regsNum = VReg::REG_START - Cg()->TotalRegsNum();
133 
134     return funcElement;
135 }
136 
GenVariableSignature(pandasm::debuginfo::LocalVariable & variableDebug,varbinder::LocalVariable * variable) const137 void ETSFunctionEmitter::GenVariableSignature(pandasm::debuginfo::LocalVariable &variableDebug,
138                                               [[maybe_unused]] varbinder::LocalVariable *variable) const
139 {
140     variableDebug.signature = Signatures::ANY;
141     variableDebug.signatureType = Signatures::ANY;
142 }
143 
GenFunctionAnnotations(pandasm::Function * func)144 void ETSFunctionEmitter::GenFunctionAnnotations([[maybe_unused]] pandasm::Function *func) {}
145 
146 template <typename T>
GenExternalFunction(T signature,bool isCtor)147 static pandasm::Function GenExternalFunction(T signature, bool isCtor)
148 {
149     auto iter = signature.begin();
150     std::string name(*iter++);
151 
152     auto func = pandasm::Function(name, EXTENSION);
153 
154     while (iter != signature.end()) {
155         auto paramName = *iter++;
156         func.params.emplace_back(pandasm::Type(paramName, 0), EXTENSION);
157     }
158 
159     func.returnType = pandasm::Type(Signatures::PRIMITIVE_VOID, 0);
160     if (isCtor) {
161         func.metadata->SetAttribute(Signatures::CONSTRUCTOR);
162     }
163     func.metadata->SetAttribute(Signatures::EXTERNAL);
164 
165     return func;
166 }
167 
GenExternalFunction(checker::Signature * signature,bool isCtor)168 static pandasm::Function GenExternalFunction(checker::Signature *signature, bool isCtor)
169 {
170     auto func = pandasm::Function(signature->InternalName().Mutf8(), EXTENSION);
171 
172     for (auto param : signature->Params()) {
173         auto *paramType = param->TsType();
174 
175         std::stringstream ss;
176         paramType->ToAssemblerType(ss);
177         func.params.emplace_back(pandasm::Type(ss.str(), paramType->Rank()), EXTENSION);
178     }
179 
180     std::stringstream ss;
181     signature->ReturnType()->ToAssemblerType(ss);
182     func.returnType = pandasm::Type(ss.str(), signature->ReturnType()->Rank());
183 
184     if (isCtor) {
185         func.metadata->SetAttribute(Signatures::CONSTRUCTOR);
186     }
187     func.metadata->SetAttribute(Signatures::EXTERNAL);
188 
189     return func;
190 }
191 
GenAnnotation()192 void ETSEmitter::GenAnnotation()
193 {
194     Program()->lang = EXTENSION;
195     const auto *varbinder = static_cast<varbinder::ETSBinder *>(Context()->VarBinder());
196 
197     auto *globalRecordTable = varbinder->GetGlobalRecordTable();
198 
199     for (auto *classDecl : globalRecordTable->ClassDefinitions()) {
200         GenClassRecord(classDecl, false);
201     }
202 
203     for (auto *interfaceDecl : globalRecordTable->InterfaceDeclarations()) {
204         GenInterfaceRecord(interfaceDecl, false);
205     }
206 
207     for (auto *signature : globalRecordTable->Signatures()) {
208         auto *scriptFunc = signature->Node()->AsScriptFunction();
209         auto func = GenScriptFunction(Context(), scriptFunc);
210         if (scriptFunc->IsAsyncFunc()) {
211             std::vector<pandasm::AnnotationData> annotations;
212             annotations.push_back(GenAnnotationAsync(scriptFunc));
213             func.metadata->SetAnnotations(std::move(annotations));
214         }
215         Program()->functionTable.emplace(func.name, std::move(func));
216     }
217 
218     for (auto [extProg, recordTable] : varbinder->GetExternalRecordTable()) {
219         (void)extProg;
220         GenExternalRecord(recordTable);
221     }
222 
223     const auto *checker = static_cast<checker::ETSChecker *>(Context()->Checker());
224 
225     for (auto [arrType, signature] : checker->GlobalArrayTypes()) {
226         GenGlobalArrayRecord(arrType, signature);
227     }
228 }
229 
GenExternalRecord(varbinder::RecordTable * recordTable)230 void ETSEmitter::GenExternalRecord(varbinder::RecordTable *recordTable)
231 {
232     bool isGenStdLib = recordTable->Program()->VarBinder()->IsGenStdLib();
233     for (auto *classDecl : recordTable->ClassDefinitions()) {
234         GenClassRecord(classDecl, !isGenStdLib);
235     }
236 
237     for (auto *interfaceDecl : recordTable->InterfaceDeclarations()) {
238         GenInterfaceRecord(interfaceDecl, !isGenStdLib);
239     }
240 
241     for (auto *signature : recordTable->Signatures()) {
242         auto func = GenScriptFunction(Context(), signature->Node()->AsScriptFunction());
243 
244         if (!isGenStdLib) {
245             func.metadata->SetAttribute(Signatures::EXTERNAL);
246         }
247 
248         Program()->functionTable.emplace(func.name, std::move(func));
249     }
250 }
251 
EmitDefaultFieldValue(pandasm::Field & classField,const ir::Expression * init)252 void ETSEmitter::EmitDefaultFieldValue(pandasm::Field &classField, const ir::Expression *init)
253 {
254     if (init == nullptr) {
255         return;
256     }
257 
258     const auto *type = init->TsType();
259 
260     if (!type->HasTypeFlag(checker::TypeFlag::CONSTANT)) {
261         return;
262     }
263 
264     auto typeKind = checker::ETSChecker::TypeKind(type);
265 
266     classField.metadata->SetFieldType(classField.type);
267     switch (typeKind) {
268         case checker::TypeFlag::ETS_BOOLEAN: {
269             classField.metadata->SetValue(pandasm::ScalarValue::Create<pandasm::Value::Type::U1>(
270                 static_cast<uint8_t>(type->AsETSBooleanType()->GetValue())));
271             break;
272         }
273         case checker::TypeFlag::BYTE: {
274             classField.metadata->SetValue(
275                 pandasm::ScalarValue::Create<pandasm::Value::Type::I8>(type->AsByteType()->GetValue()));
276             break;
277         }
278         case checker::TypeFlag::SHORT: {
279             classField.metadata->SetValue(
280                 pandasm::ScalarValue::Create<pandasm::Value::Type::I16>(type->AsShortType()->GetValue()));
281             break;
282         }
283         case checker::TypeFlag::INT: {
284             classField.metadata->SetValue(
285                 pandasm::ScalarValue::Create<pandasm::Value::Type::I32>(type->AsIntType()->GetValue()));
286             break;
287         }
288         case checker::TypeFlag::LONG: {
289             classField.metadata->SetValue(
290                 pandasm::ScalarValue::Create<pandasm::Value::Type::I64>(type->AsLongType()->GetValue()));
291             break;
292         }
293         case checker::TypeFlag::FLOAT: {
294             classField.metadata->SetValue(
295                 pandasm::ScalarValue::Create<pandasm::Value::Type::F32>(type->AsFloatType()->GetValue()));
296             break;
297         }
298         case checker::TypeFlag::DOUBLE: {
299             classField.metadata->SetValue(
300                 pandasm::ScalarValue::Create<pandasm::Value::Type::F64>(type->AsDoubleType()->GetValue()));
301             break;
302         }
303         case checker::TypeFlag::CHAR: {
304             classField.metadata->SetValue(
305                 pandasm::ScalarValue::Create<pandasm::Value::Type::U16>(type->AsCharType()->GetValue()));
306             break;
307         }
308         case checker::TypeFlag::ETS_OBJECT: {
309             classField.metadata->SetValue(pandasm::ScalarValue::Create<pandasm::Value::Type::STRING>(
310                 type->AsETSObjectType()->AsETSStringType()->GetValue().Mutf8()));
311             break;
312         }
313         default: {
314             UNREACHABLE();
315         }
316     }
317 }
318 
GenInterfaceMethodDefinition(const ir::MethodDefinition * methodDef,bool external)319 void ETSEmitter::GenInterfaceMethodDefinition(const ir::MethodDefinition *methodDef, bool external)
320 {
321     auto *scriptFunc = methodDef->Function();
322     auto func = GenScriptFunction(Context(), scriptFunc);
323 
324     if (external) {
325         func.metadata->SetAttribute(Signatures::EXTERNAL);
326     }
327 
328     if (scriptFunc->Body() != nullptr) {
329         return;
330     }
331 
332     func.metadata->SetAccessFlags(func.metadata->GetAccessFlags() | ACC_ABSTRACT);
333     Program()->functionTable.emplace(func.name, std::move(func));
334 }
335 
GenClassField(const ir::ClassProperty * field,pandasm::Record & classRecord,bool external)336 void ETSEmitter::GenClassField(const ir::ClassProperty *field, pandasm::Record &classRecord, bool external)
337 {
338     GenField(field->TsType(), field->Id()->Name(), field->Value(), TranslateModifierFlags(field->Modifiers()),
339              classRecord, external);
340 }
341 
GenField(const checker::Type * tsType,const util::StringView & name,const ir::Expression * value,uint32_t accesFlags,pandasm::Record & record,bool external)342 void ETSEmitter::GenField(const checker::Type *tsType, const util::StringView &name, const ir::Expression *value,
343                           uint32_t accesFlags, pandasm::Record &record, bool external)
344 {
345     auto field = pandasm::Field(Program()->lang);
346     std::stringstream ss;
347     tsType->ToAssemblerType(ss);
348 
349     field.name = name.Mutf8();
350     field.type = pandasm::Type(ss.str(), tsType->Rank());
351 
352     field.metadata->SetAccessFlags(accesFlags);
353 
354     if (external) {
355         field.metadata->SetAttribute(Signatures::EXTERNAL);
356     } else if (tsType->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE) || tsType->IsETSStringType()) {
357         EmitDefaultFieldValue(field, value);
358     }
359 
360     record.fieldList.emplace_back(std::move(field));
361 }
362 
GenClassInheritedFields(const checker::ETSObjectType * baseType,pandasm::Record & classRecord)363 void ETSEmitter::GenClassInheritedFields(const checker::ETSObjectType *baseType, pandasm::Record &classRecord)
364 {
365     std::vector<const varbinder::LocalVariable *> foreignProps = baseType->ForeignProperties();
366 
367     for (const auto *foreignProp : foreignProps) {
368         auto *declNode = foreignProp->Declaration()->Node();
369         if (!declNode->IsClassProperty()) {
370             continue;
371         }
372 
373         GenClassField(declNode->AsClassProperty(), classRecord, true);
374     }
375 }
376 
GenGlobalArrayRecord(checker::ETSArrayType * arrayType,checker::Signature * signature)377 void ETSEmitter::GenGlobalArrayRecord(checker::ETSArrayType *arrayType, checker::Signature *signature)
378 {
379     std::stringstream ss;
380     arrayType->ToAssemblerTypeWithRank(ss);
381 
382     auto arrayRecord = pandasm::Record(ss.str(), Program()->lang);
383 
384     auto func = GenExternalFunction(signature, true);
385     func.params.emplace(func.params.begin(), pandasm::Type(ss.str(), 0), EXTENSION);
386 
387     Program()->functionTable.emplace(func.name, std::move(func));
388 
389     arrayRecord.metadata->SetAttribute(Signatures::EXTERNAL);
390     Program()->recordTable.emplace(arrayRecord.name, std::move(arrayRecord));
391 
392     std::stringstream ss2;
393     arrayType->ElementType()->ToAssemblerType(ss2);
394     panda::pandasm::Type atypePa(ss2.str(), arrayType->Rank());
395     Program()->arrayTypes.emplace(std::move(atypePa));
396 }
397 
GenInterfaceRecord(const ir::TSInterfaceDeclaration * interfaceDecl,bool external)398 void ETSEmitter::GenInterfaceRecord(const ir::TSInterfaceDeclaration *interfaceDecl, bool external)
399 {
400     auto *baseType = interfaceDecl->TsType()->AsETSObjectType();
401 
402     auto interfaceRecord = pandasm::Record(interfaceDecl->InternalName().Mutf8(), Program()->lang);
403 
404     if (external) {
405         interfaceRecord.metadata->SetAttribute(Signatures::EXTERNAL);
406     }
407 
408     uint32_t accessFlags = ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE;
409 
410     if (interfaceDecl->IsStatic()) {
411         accessFlags |= ACC_STATIC;
412     }
413 
414     interfaceRecord.metadata->SetAccessFlags(accessFlags);
415     interfaceRecord.sourceFile = Context()->VarBinder()->Program()->AbsoluteName().Mutf8();
416     interfaceRecord.metadata->SetAttributeValue(Signatures::EXTENDS_ATTRIBUTE, Signatures::BUILTIN_OBJECT);
417 
418     for (auto *it : baseType->Interfaces()) {
419         auto *declNode = it->GetDeclNode();
420         ASSERT(declNode->IsTSInterfaceDeclaration());
421         std::string name = declNode->AsTSInterfaceDeclaration()->InternalName().Mutf8();
422         interfaceRecord.metadata->SetAttributeValue(Signatures::IMPLEMENTS_ATTRIBUTE, name);
423     }
424 
425     GenClassInheritedFields(baseType, interfaceRecord);
426 
427     for (const auto *prop : interfaceDecl->Body()->Body()) {
428         if (prop->IsClassProperty()) {
429             GenClassField(prop->AsClassProperty(), interfaceRecord, external);
430         } else if (prop->IsMethodDefinition()) {
431             GenInterfaceMethodDefinition(prop->AsMethodDefinition(), external);
432         }
433     }
434 
435     Program()->recordTable.emplace(interfaceRecord.name, std::move(interfaceRecord));
436 }
437 
GenClassRecord(const ir::ClassDefinition * classDef,bool external)438 void ETSEmitter::GenClassRecord(const ir::ClassDefinition *classDef, bool external)
439 {
440     auto classRecord = pandasm::Record(classDef->InternalName().Mutf8(), Program()->lang);
441 
442     if (external) {
443         classRecord.metadata->SetAttribute(Signatures::EXTERNAL);
444     }
445 
446     uint32_t accessFlags = ACC_PUBLIC;
447 
448     if (classDef->IsAbstract()) {
449         accessFlags |= ACC_ABSTRACT;
450     } else if (classDef->IsFinal()) {
451         accessFlags |= ACC_FINAL;
452     }
453 
454     if (classDef->IsStatic()) {
455         accessFlags |= ACC_STATIC;
456     }
457 
458     classRecord.metadata->SetAccessFlags(accessFlags);
459     classRecord.sourceFile = Context()->VarBinder()->Program()->AbsoluteName().Mutf8();
460 
461     auto *baseType = classDef->TsType()->AsETSObjectType();
462     if (baseType->SuperType() != nullptr) {
463         classRecord.metadata->SetAttributeValue(Signatures::EXTENDS_ATTRIBUTE,
464                                                 baseType->SuperType()->AssemblerName().Mutf8());
465     } else {
466         // NOTE: rtakacs. Replace the whole if block (below) with assert when lambda objects have super class.
467         if (baseType->AssemblerName().Mutf8() != Signatures::BUILTIN_OBJECT) {
468             classRecord.metadata->SetAttributeValue(Signatures::EXTENDS_ATTRIBUTE, Signatures::BUILTIN_OBJECT);
469         }
470     }
471 
472     for (auto *it : baseType->Interfaces()) {
473         // We do not need to add dynamic interfaces
474         if (it->IsETSDynamicType()) {
475             continue;
476         }
477 
478         auto *declNode = it->GetDeclNode();
479         // NOTE: itrubachev. replace it with ASSERT(decl_node->IsTSInterfaceDeclaration())
480         // after adding proper creation of lambda object in ETSFunctionType::AssignmentSource
481         if (!declNode->IsTSInterfaceDeclaration()) {
482             continue;
483         }
484         std::string name = declNode->AsTSInterfaceDeclaration()->InternalName().Mutf8();
485         classRecord.metadata->SetAttributeValue(Signatures::IMPLEMENTS_ATTRIBUTE, name);
486     }
487 
488     GenClassInheritedFields(baseType, classRecord);
489 
490     for (const auto *prop : classDef->Body()) {
491         if (!prop->IsClassProperty()) {
492             continue;
493         }
494 
495         GenClassField(prop->AsClassProperty(), classRecord, external);
496     }
497 
498     std::vector<pandasm::AnnotationData> annotations;
499 
500     const ir::AstNode *parent = classDef->Parent();
501     while (parent != nullptr) {
502         if (parent->IsMethodDefinition()) {
503             annotations.emplace_back(GenAnnotationEnclosingMethod(parent->AsMethodDefinition()));
504             annotations.emplace_back(GenAnnotationInnerClass(classDef, parent));
505             break;
506         }
507         if (parent->IsClassDefinition()) {
508             annotations.emplace_back(GenAnnotationEnclosingClass(
509                 parent->AsClassDefinition()->TsType()->AsETSObjectType()->AssemblerName().Utf8()));
510             annotations.emplace_back(GenAnnotationInnerClass(classDef, parent));
511             break;
512         }
513         parent = parent->Parent();
514     }
515 
516     if (!annotations.empty()) {
517         classRecord.metadata->SetAnnotations(std::move(annotations));
518     }
519 
520     Program()->recordTable.emplace(classRecord.name, std::move(classRecord));
521 }
522 
GenAnnotationSignature(const ir::ClassDefinition * classDef)523 pandasm::AnnotationData ETSEmitter::GenAnnotationSignature(const ir::ClassDefinition *classDef)
524 {
525     static constexpr std::string_view OBJECT = "Lstd/core/Object";
526     std::vector<pandasm::ScalarValue> parts {};
527     std::stringstream ss {};
528     const auto &params = classDef->TypeParams()->Params();
529 
530     bool firstIteration = true;
531     for (const auto *param : params) {
532         if (firstIteration) {
533             ss << Signatures::GENERIC_BEGIN;
534             firstIteration = false;
535         }
536         ss << param->Name()->Name() << Signatures::MANGLE_BEGIN;
537         parts.emplace_back(pandasm::ScalarValue::Create<pandasm::Value::Type::STRING>(ss.str()));
538 
539         std::stringstream {}.swap(ss);
540         if (param->Constraint() == nullptr) {
541             ss << OBJECT;
542         } else {
543             param->Constraint()->TsType()->ToAssemblerTypeWithRank(ss);
544             auto str = ss.str();
545             std::replace(str.begin(), str.end(), *Signatures::METHOD_SEPARATOR.begin(),
546                          *Signatures::NAMESPACE_SEPARATOR.begin());
547             std::stringstream {}.swap(ss);
548             ss << Signatures::CLASS_REF_BEGIN << str << Signatures::MANGLE_SEPARATOR;
549         }
550 
551         parts.emplace_back(pandasm::ScalarValue::Create<pandasm::Value::Type::STRING>(ss.str()));
552         std::stringstream {}.swap(ss);  // cleanup
553     }
554 
555     ss << Signatures::GENERIC_END;
556     parts.emplace_back(pandasm::ScalarValue::Create<pandasm::Value::Type::STRING>(ss.str()));
557 
558     std::stringstream {}.swap(ss);
559     if (classDef->TsType()->AsETSObjectType()->SuperType() == nullptr) {
560         ss << OBJECT;
561     } else {
562         ss << Signatures::CLASS_REF_BEGIN;
563         auto superType = classDef->TsType()->AsETSObjectType()->SuperType()->AssemblerName().Mutf8();
564         std::replace(superType.begin(), superType.end(), *Signatures::METHOD_SEPARATOR.begin(),
565                      *Signatures::NAMESPACE_SEPARATOR.begin());
566         ss << superType << Signatures::MANGLE_SEPARATOR;
567     }
568     parts.emplace_back(pandasm::ScalarValue::Create<pandasm::Value::Type::STRING>(ss.str()));
569 
570     GenAnnotationRecord(Signatures::ETS_ANNOTATION_SIGNATURE);
571     pandasm::AnnotationData signature(Signatures::ETS_ANNOTATION_SIGNATURE);
572     pandasm::AnnotationElement value(
573         Signatures::ANNOTATION_KEY_VALUE,
574         std::make_unique<pandasm::ArrayValue>(pandasm::Value::Type::STRING, std::move(parts)));
575     signature.AddElement(std::move(value));
576     return signature;
577 }
578 
GenAnnotationEnclosingMethod(const ir::MethodDefinition * methodDef)579 pandasm::AnnotationData ETSEmitter::GenAnnotationEnclosingMethod(const ir::MethodDefinition *methodDef)
580 {
581     GenAnnotationRecord(Signatures::ETS_ANNOTATION_ENCLOSING_METHOD);
582     pandasm::AnnotationData enclosingMethod(Signatures::ETS_ANNOTATION_ENCLOSING_METHOD);
583     pandasm::AnnotationElement value(
584         Signatures::ANNOTATION_KEY_VALUE,
585         std::make_unique<pandasm::ScalarValue>(pandasm::ScalarValue::Create<pandasm::Value::Type::METHOD>(
586             methodDef->Function()->Scope()->InternalName().Mutf8())));
587     enclosingMethod.AddElement(std::move(value));
588     return enclosingMethod;
589 }
590 
GenAnnotationEnclosingClass(std::string_view className)591 pandasm::AnnotationData ETSEmitter::GenAnnotationEnclosingClass(std::string_view className)
592 {
593     GenAnnotationRecord(Signatures::ETS_ANNOTATION_ENCLOSING_CLASS);
594     pandasm::AnnotationData enclosingClass(Signatures::ETS_ANNOTATION_ENCLOSING_CLASS);
595     pandasm::AnnotationElement value(
596         Signatures::ANNOTATION_KEY_VALUE,
597         std::make_unique<pandasm::ScalarValue>(
598             pandasm::ScalarValue::Create<pandasm::Value::Type::RECORD>(pandasm::Type::FromName(className, true))));
599     enclosingClass.AddElement(std::move(value));
600     return enclosingClass;
601 }
602 
GenAnnotationInnerClass(const ir::ClassDefinition * classDef,const ir::AstNode * parent)603 pandasm::AnnotationData ETSEmitter::GenAnnotationInnerClass(const ir::ClassDefinition *classDef,
604                                                             const ir::AstNode *parent)
605 {
606     GenAnnotationRecord(Signatures::ETS_ANNOTATION_INNER_CLASS);
607     pandasm::AnnotationData innerClass(Signatures::ETS_ANNOTATION_INNER_CLASS);
608     const bool isAnonymous = (classDef->Modifiers() & ir::ClassDefinitionModifiers::ANONYMOUS) != 0;
609     pandasm::AnnotationElement name(Signatures::ANNOTATION_KEY_NAME,
610                                     std::make_unique<pandasm::ScalarValue>(
611                                         isAnonymous
612                                             ? pandasm::ScalarValue::Create<pandasm::Value::Type::STRING_NULLPTR>(0)
613                                             : pandasm::ScalarValue::Create<pandasm::Value::Type::STRING>(
614                                                   classDef->TsType()->AsETSObjectType()->AssemblerName().Mutf8())));
615     innerClass.AddElement(std::move(name));
616 
617     pandasm::AnnotationElement accessFlags(
618         Signatures::ANNOTATION_KEY_ACCESS_FLAGS,
619         std::make_unique<pandasm::ScalarValue>(
620             pandasm::ScalarValue::Create<pandasm::Value::Type::I32>(TranslateModifierFlags(parent->Modifiers()))));
621     innerClass.AddElement(std::move(accessFlags));
622     return innerClass;
623 }
624 
FindAsyncImpl(ir::ScriptFunction * asyncFunc)625 ir::MethodDefinition *ETSEmitter::FindAsyncImpl(ir::ScriptFunction *asyncFunc)
626 {
627     std::string implName = checker::ETSChecker::GetAsyncImplName(asyncFunc->Id()->Name());
628     ir::AstNode *ownerNode = asyncFunc->Signature()->Owner()->GetDeclNode();
629     ASSERT(ownerNode != nullptr && ownerNode->IsClassDefinition());
630     const ir::ClassDefinition *classDef = ownerNode->AsClassDefinition();
631     ASSERT(classDef != nullptr);
632 
633     auto it = std::find_if(classDef->Body().rbegin(), classDef->Body().rend(), [&implName](ir::AstNode *node) {
634         return node->IsMethodDefinition() && node->AsMethodDefinition()->Id()->Name().Utf8() == implName;
635     });
636     if (it == classDef->Body().rend()) {
637         return nullptr;
638     }
639 
640     ir::MethodDefinition *method = (*it)->AsMethodDefinition();
641     auto *checker = static_cast<checker::ETSChecker *>(Context()->Checker());
642     checker::TypeRelation *typeRel = checker->Relation();
643     checker::SavedTypeRelationFlagsContext savedFlagsCtx(typeRel, checker::TypeRelationFlag::NO_RETURN_TYPE_CHECK);
644     method->Function()->Signature()->Identical(typeRel, asyncFunc->Signature());
645     auto overloadIt = method->Overloads().begin();
646     while (overloadIt != method->Overloads().end() && !typeRel->IsTrue()) {
647         method = *overloadIt;
648         method->Function()->Signature()->Identical(typeRel, asyncFunc->Signature());
649         ++overloadIt;
650     }
651     return typeRel->IsTrue() ? method : nullptr;
652 }
653 
GenAnnotationAsync(ir::ScriptFunction * scriptFunc)654 pandasm::AnnotationData ETSEmitter::GenAnnotationAsync(ir::ScriptFunction *scriptFunc)
655 {
656     GenAnnotationRecord(Signatures::ETS_COROUTINE_ASYNC);
657     const ir::MethodDefinition *impl = FindAsyncImpl(scriptFunc);
658     ASSERT(impl != nullptr);
659     pandasm::AnnotationData ann(Signatures::ETS_COROUTINE_ASYNC);
660     pandasm::AnnotationElement value(
661         Signatures::ANNOTATION_KEY_VALUE,
662         std::make_unique<pandasm::ScalarValue>(pandasm::ScalarValue::Create<pandasm::Value::Type::METHOD>(
663             impl->Function()->Scope()->InternalName().Mutf8())));
664     ann.AddElement(std::move(value));
665     return ann;
666 }
667 
GenAnnotationRecord(std::string_view recordNameView,bool isRuntime,bool isType)668 void ETSEmitter::GenAnnotationRecord(std::string_view recordNameView, bool isRuntime, bool isType)
669 {
670     const std::string recordName(recordNameView);
671     const auto recordIt = Program()->recordTable.find(recordName);
672     if (recordIt == Program()->recordTable.end()) {
673         pandasm::Record record(recordName, EXTENSION);
674         record.metadata->SetAttribute(Signatures::EXTERNAL);
675         record.metadata->SetAttribute(Signatures::ANNOTATION_ATTRIBUTE);
676         if (isRuntime && isType) {
677             record.metadata->SetAttributeValue(Signatures::ANNOTATION_ATTRIBUTE_TYPE,
678                                                Signatures::RUNTIME_TYPE_ANNOTATION);
679         } else if (isRuntime && !isType) {
680             record.metadata->SetAttributeValue(Signatures::ANNOTATION_ATTRIBUTE_TYPE, Signatures::RUNTIME_ANNOTATION);
681         } else if (!isRuntime && isType) {
682             record.metadata->SetAttributeValue(Signatures::ANNOTATION_ATTRIBUTE_TYPE, Signatures::TYPE_ANNOTATION);
683         }
684         Program()->recordTable.emplace(record.name, std::move(record));
685     }
686 }
687 }  // namespace panda::es2panda::compiler
688