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 ¶ms = 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