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 "ETSemitter.h"
17
18 #include "compiler/core/ETSGen.h"
19 #include "varbinder/varbinder.h"
20 #include "varbinder/ETSBinder.h"
21 #include "ir/astNode.h"
22 #include "ir/expressions/identifier.h"
23 #include "ir/base/decorator.h"
24 #include "ir/base/methodDefinition.h"
25 #include "ir/base/classDefinition.h"
26 #include "ir/base/scriptFunction.h"
27 #include "ir/base/classProperty.h"
28 #include "ir/ts/tsEnumDeclaration.h"
29 #include "ir/ts/tsEnumMember.h"
30 #include "ir/ts/tsInterfaceDeclaration.h"
31 #include "ir/ts/tsInterfaceBody.h"
32 #include "ir/ts/tsTypeParameterDeclaration.h"
33 #include "ir/ts/tsTypeParameter.h"
34 #include "ir/typeNode.h"
35 #include "parser/program/program.h"
36 #include "checker/checker.h"
37 #include "checker/types/signature.h"
38 #include "checker/ETSchecker.h"
39 #include "checker/types/type.h"
40 #include "checker/types/ets/types.h"
41 #include "checker/types/ets/etsPartialTypeParameter.h"
42 #include "public/public.h"
43
44 #include "assembly-program.h"
45
46 namespace {
47 uint32_t g_litArrayValueCount = 0;
48 } // namespace
49
50 namespace ark::es2panda::compiler {
51
52 #ifdef PANDA_WITH_ETS
53 static constexpr auto EXTENSION = panda_file::SourceLang::ETS;
54 #else
55 // NOTE: temporary dummy gn buildfix until ETS plugin has gn build support
56 static constexpr auto EXTENSION = panda_file::SourceLang::PANDA_ASSEMBLY;
57 #endif
58
TranslateModifierFlags(ir::ModifierFlags modifierFlags)59 static uint32_t TranslateModifierFlags(ir::ModifierFlags modifierFlags)
60 {
61 uint32_t accessFlags = 0;
62
63 if ((modifierFlags & ir::ModifierFlags::PRIVATE) != 0) {
64 accessFlags = ACC_PRIVATE;
65 } else if ((modifierFlags & ir::ModifierFlags::INTERNAL) != 0) {
66 if ((modifierFlags & ir::ModifierFlags::PROTECTED) != 0) {
67 accessFlags = ACC_PROTECTED;
68 }
69 // NOTE: torokg. Add ACC_INTERNAL access flag to libpandabase
70 } else if ((modifierFlags & ir::ModifierFlags::PROTECTED) != 0) {
71 accessFlags = ACC_PROTECTED;
72 } else {
73 accessFlags = ACC_PUBLIC;
74 }
75
76 if ((modifierFlags & ir::ModifierFlags::STATIC) != 0) {
77 accessFlags |= ACC_STATIC;
78 }
79 if ((modifierFlags & ir::ModifierFlags::FINAL) != 0) {
80 accessFlags |= ACC_FINAL;
81 }
82 // NOTE: should be ModifierFlags::READONLY
83 if ((modifierFlags & ir::ModifierFlags::READONLY) != 0) {
84 accessFlags |= ACC_READONLY;
85 }
86 if ((modifierFlags & ir::ModifierFlags::ABSTRACT) != 0) {
87 accessFlags |= ACC_ABSTRACT;
88 }
89 if ((modifierFlags & ir::ModifierFlags::NATIVE) != 0) {
90 accessFlags |= ACC_NATIVE;
91 }
92
93 return accessFlags;
94 }
95
PandasmTypeWithRank(checker::Type const * type,uint32_t rank=0)96 static pandasm::Type PandasmTypeWithRank(checker::Type const *type, uint32_t rank = 0)
97 {
98 if (type->IsETSTypeParameter()) {
99 return PandasmTypeWithRank(type->AsETSTypeParameter()->GetConstraintType());
100 }
101 if (type->IsETSNonNullishType()) {
102 return PandasmTypeWithRank(type->AsETSNonNullishType()->GetUnderlying());
103 }
104 if (type->IsETSPartialTypeParameter()) {
105 return PandasmTypeWithRank(type->AsETSPartialTypeParameter()->GetUnderlying());
106 }
107 if (type->IsETSUnionType()) {
108 return PandasmTypeWithRank(type->AsETSUnionType()->GetAssemblerLUB());
109 }
110
111 std::stringstream ss;
112 type->ToAssemblerType(ss);
113 return pandasm::Type(ss.str(), rank == 0 ? type->Rank() : rank);
114 }
115
GenScriptFunction(const ir::ScriptFunction * scriptFunc,ETSEmitter * emitter)116 static pandasm::Function GenScriptFunction(const ir::ScriptFunction *scriptFunc, ETSEmitter *emitter)
117 {
118 auto *funcScope = scriptFunc->Scope();
119 auto *paramScope = funcScope->ParamScope();
120
121 auto func = pandasm::Function(funcScope->InternalName().Mutf8(), EXTENSION);
122 func.params.reserve(paramScope->Params().size());
123
124 for (const auto *var : paramScope->Params()) {
125 func.params.emplace_back(PandasmTypeWithRank(var->TsType()), EXTENSION);
126 }
127
128 if (scriptFunc->IsConstructor() || scriptFunc->IsStaticBlock()) {
129 func.returnType = pandasm::Type(Signatures::PRIMITIVE_VOID, 0);
130 } else {
131 func.returnType = PandasmTypeWithRank(scriptFunc->Signature()->ReturnType());
132 }
133
134 uint32_t accessFlags = 0;
135 if (!scriptFunc->IsStaticBlock()) {
136 const auto *methodDef = util::Helpers::GetContainingClassMethodDefinition(scriptFunc);
137 accessFlags |= TranslateModifierFlags(methodDef->Modifiers());
138 }
139 if (scriptFunc->HasRestParameter()) {
140 accessFlags |= ACC_VARARGS;
141 }
142 func.metadata->SetAccessFlags(accessFlags);
143
144 if (!scriptFunc->Annotations().empty()) {
145 auto baseName = scriptFunc->Id()->Name().Mutf8();
146 func.metadata->SetAnnotations(emitter->GenCustomAnnotations(scriptFunc->Annotations(), baseName));
147 }
148 return func;
149 }
150
GenFunctionSignature()151 pandasm::Function *ETSFunctionEmitter::GenFunctionSignature()
152 {
153 auto *scriptFunc = Cg()->RootNode()->AsScriptFunction();
154 auto *emitter = static_cast<ETSEmitter *>(Cg()->Context()->emitter);
155 auto func = GenScriptFunction(scriptFunc, emitter);
156
157 if (Cg()->RootNode()->AsScriptFunction()->IsExternal()) {
158 func.metadata->SetAttribute(Signatures::EXTERNAL);
159 }
160
161 auto *funcElement = new pandasm::Function(func.name, func.language);
162 *funcElement = std::move(func);
163 GetProgramElement()->SetFunction(funcElement);
164 funcElement->regsNum = VReg::REG_START - Cg()->TotalRegsNum();
165
166 return funcElement;
167 }
168
GenVariableSignature(pandasm::debuginfo::LocalVariable & variableDebug,varbinder::LocalVariable * variable) const169 void ETSFunctionEmitter::GenVariableSignature(pandasm::debuginfo::LocalVariable &variableDebug,
170 [[maybe_unused]] varbinder::LocalVariable *variable) const
171 {
172 variableDebug.signature = Signatures::ANY;
173 variableDebug.signatureType = Signatures::ANY;
174 }
175
GenFunctionAnnotations(pandasm::Function * func)176 void ETSFunctionEmitter::GenFunctionAnnotations([[maybe_unused]] pandasm::Function *func) {}
177
GenExternalFunction(checker::Signature * signature,bool isCtor)178 static pandasm::Function GenExternalFunction(checker::Signature *signature, bool isCtor)
179 {
180 auto func = pandasm::Function(signature->InternalName().Mutf8(), EXTENSION);
181
182 for (auto param : signature->Params()) {
183 func.params.emplace_back(PandasmTypeWithRank(param->TsType()), EXTENSION);
184 }
185 func.returnType = PandasmTypeWithRank(signature->ReturnType());
186
187 if (isCtor) {
188 func.metadata->SetAttribute(Signatures::CONSTRUCTOR);
189 }
190 func.metadata->SetAttribute(Signatures::EXTERNAL);
191
192 return func;
193 }
194
GenerateMangledName(const std::string & baseName,const std::string & propName)195 static std::string GenerateMangledName(const std::string &baseName, const std::string &propName)
196 {
197 return baseName + "$" + propName;
198 }
199
GenAnnotation()200 void ETSEmitter::GenAnnotation()
201 {
202 Program()->lang = EXTENSION;
203 const auto *varbinder = static_cast<varbinder::ETSBinder *>(Context()->parserProgram->VarBinder());
204
205 auto *globalRecordTable = varbinder->GetGlobalRecordTable();
206 auto baseName = varbinder->GetRecordTable()->RecordName().Mutf8();
207 for (auto *annoDecl : globalRecordTable->AnnotationDeclarations()) {
208 auto newBaseName = GenerateMangledName(baseName, annoDecl->GetBaseName()->Name().Mutf8());
209 GenCustomAnnotationRecord(annoDecl, newBaseName, annoDecl->IsDeclare());
210 }
211
212 for (auto *classDecl : globalRecordTable->ClassDefinitions()) {
213 GenClassRecord(classDecl, classDecl->IsDeclare());
214 }
215
216 for (auto *interfaceDecl : globalRecordTable->InterfaceDeclarations()) {
217 GenInterfaceRecord(interfaceDecl, interfaceDecl->IsDeclare());
218 }
219
220 for (auto *signature : globalRecordTable->Signatures()) {
221 auto *scriptFunc = signature->Node()->AsScriptFunction();
222 auto func = GenScriptFunction(scriptFunc, this);
223 if (scriptFunc->IsDeclare()) {
224 func.metadata->SetAttribute(Signatures::EXTERNAL);
225 }
226 if (scriptFunc->IsAsyncFunc()) {
227 std::vector<pandasm::AnnotationData> annotations;
228 annotations.push_back(GenAnnotationAsync(scriptFunc));
229 func.metadata->SetAnnotations(std::move(annotations));
230 }
231 Program()->functionTable.emplace(func.name, std::move(func));
232 }
233
234 for (auto [extProg, recordTable] : varbinder->GetExternalRecordTable()) {
235 (void)extProg;
236 if (recordTable == varbinder->GetRecordTable()) {
237 continue;
238 }
239 GenExternalRecord(recordTable);
240 }
241
242 const auto *checker = static_cast<checker::ETSChecker *>(Context()->checker);
243
244 for (auto [arrType, signature] : checker->GlobalArrayTypes()) {
245 GenGlobalArrayRecord(arrType, signature);
246 }
247 }
248
GenExternalRecord(varbinder::RecordTable * recordTable)249 void ETSEmitter::GenExternalRecord(varbinder::RecordTable *recordTable)
250 {
251 bool isGenStdLib = recordTable->Program()->VarBinder()->IsGenStdLib();
252 const auto *varbinder = static_cast<const varbinder::ETSBinder *>(Context()->parserProgram->VarBinder());
253 auto baseName = varbinder->GetRecordTable()->RecordName().Mutf8();
254 for (auto *annoDecl : recordTable->AnnotationDeclarations()) {
255 auto newBaseName = GenerateMangledName(baseName, annoDecl->GetBaseName()->Name().Mutf8());
256 GenCustomAnnotationRecord(annoDecl, newBaseName, !isGenStdLib);
257 }
258
259 for (auto *classDecl : recordTable->ClassDefinitions()) {
260 GenClassRecord(classDecl, !isGenStdLib);
261 }
262
263 for (auto *interfaceDecl : recordTable->InterfaceDeclarations()) {
264 GenInterfaceRecord(interfaceDecl, !isGenStdLib);
265 }
266
267 for (auto *signature : recordTable->Signatures()) {
268 auto func = GenScriptFunction(signature->Node()->AsScriptFunction(), this);
269
270 if (!isGenStdLib) {
271 func.metadata->SetAttribute(Signatures::EXTERNAL);
272 }
273
274 Program()->functionTable.emplace(func.name, std::move(func));
275 }
276 }
277
278 // Helper function to reduce EmitDefaultFieldValue size and pass code check
CreateScalarValue(const checker::Type * type,checker::TypeFlag typeKind)279 static pandasm::ScalarValue CreateScalarValue(const checker::Type *type, checker::TypeFlag typeKind)
280 {
281 switch (typeKind) {
282 case checker::TypeFlag::ETS_BOOLEAN: {
283 return pandasm::ScalarValue::Create<pandasm::Value::Type::U1>(
284 static_cast<uint8_t>(type->AsETSBooleanType()->GetValue()));
285 }
286 case checker::TypeFlag::BYTE: {
287 return pandasm::ScalarValue::Create<pandasm::Value::Type::I8>(type->AsByteType()->GetValue());
288 }
289 case checker::TypeFlag::SHORT: {
290 return pandasm::ScalarValue::Create<pandasm::Value::Type::I16>(type->AsShortType()->GetValue());
291 }
292 case checker::TypeFlag::INT: {
293 return pandasm::ScalarValue::Create<pandasm::Value::Type::I32>(type->AsIntType()->GetValue());
294 }
295 case checker::TypeFlag::LONG: {
296 return pandasm::ScalarValue::Create<pandasm::Value::Type::I64>(type->AsLongType()->GetValue());
297 }
298 case checker::TypeFlag::FLOAT: {
299 return pandasm::ScalarValue::Create<pandasm::Value::Type::F32>(type->AsFloatType()->GetValue());
300 }
301 case checker::TypeFlag::DOUBLE: {
302 return pandasm::ScalarValue::Create<pandasm::Value::Type::F64>(type->AsDoubleType()->GetValue());
303 }
304 case checker::TypeFlag::CHAR: {
305 return pandasm::ScalarValue::Create<pandasm::Value::Type::U16>(type->AsCharType()->GetValue());
306 }
307 case checker::TypeFlag::ETS_OBJECT: {
308 return pandasm::ScalarValue::Create<pandasm::Value::Type::STRING>(
309 type->AsETSObjectType()->AsETSStringType()->GetValue().Mutf8());
310 }
311 default: {
312 UNREACHABLE();
313 }
314 }
315 }
316
EmitDefaultFieldValue(pandasm::Field & classField,const ir::Expression * init)317 void ETSEmitter::EmitDefaultFieldValue(pandasm::Field &classField, const ir::Expression *init)
318 {
319 if (init == nullptr) {
320 return;
321 }
322
323 const auto *type = init->TsType();
324
325 if (!type->HasTypeFlag(checker::TypeFlag::CONSTANT)) {
326 return;
327 }
328
329 auto typeKind = checker::ETSChecker::TypeKind(type);
330 classField.metadata->SetFieldType(classField.type);
331 classField.metadata->SetValue(CreateScalarValue(type, typeKind));
332 }
333
GenInterfaceMethodDefinition(const ir::MethodDefinition * methodDef,bool external)334 void ETSEmitter::GenInterfaceMethodDefinition(const ir::MethodDefinition *methodDef, bool external)
335 {
336 auto *scriptFunc = methodDef->Function();
337 auto func = GenScriptFunction(scriptFunc, this);
338
339 if (external) {
340 func.metadata->SetAttribute(Signatures::EXTERNAL);
341 }
342
343 if (scriptFunc->Body() != nullptr) {
344 return;
345 }
346
347 func.metadata->SetAccessFlags(func.metadata->GetAccessFlags() | ACC_ABSTRACT);
348 Program()->functionTable.emplace(func.name, std::move(func));
349 }
350
GenClassField(const ir::ClassProperty * prop,pandasm::Record & classRecord,bool external)351 void ETSEmitter::GenClassField(const ir::ClassProperty *prop, pandasm::Record &classRecord, bool external)
352 {
353 auto field = pandasm::Field(Program()->lang);
354 field.name = prop->Id()->Name().Mutf8();
355 field.type = PandasmTypeWithRank(prop->TsType());
356 field.metadata->SetAccessFlags(TranslateModifierFlags(prop->Modifiers()));
357
358 if (external || prop->IsDeclare()) {
359 field.metadata->SetAttribute(Signatures::EXTERNAL);
360 } else if (prop->TsType()->IsETSPrimitiveType() || prop->TsType()->IsETSStringType()) {
361 EmitDefaultFieldValue(field, prop->Value());
362 } else if (prop->TsType()->IsETSEnumType()) {
363 CreateEnumProp(prop, field);
364 }
365
366 classRecord.fieldList.emplace_back(std::move(field));
367 }
368
GenClassInheritedFields(const checker::ETSObjectType * baseType,pandasm::Record & classRecord)369 void ETSEmitter::GenClassInheritedFields(const checker::ETSObjectType *baseType, pandasm::Record &classRecord)
370 {
371 std::vector<const varbinder::LocalVariable *> foreignProps = baseType->ForeignProperties();
372
373 for (const auto *foreignProp : foreignProps) {
374 auto *declNode = foreignProp->Declaration()->Node();
375 if (!declNode->IsClassProperty()) {
376 continue;
377 }
378
379 GenClassField(declNode->AsClassProperty(), classRecord, true);
380 }
381 }
382
GenGlobalArrayRecord(checker::ETSArrayType * arrayType,checker::Signature * signature)383 void ETSEmitter::GenGlobalArrayRecord(checker::ETSArrayType *arrayType, checker::Signature *signature)
384 {
385 std::stringstream ss;
386 arrayType->ToAssemblerTypeWithRank(ss);
387
388 auto arrayRecord = pandasm::Record(ss.str(), Program()->lang);
389
390 auto func = GenExternalFunction(signature, true);
391 func.params.emplace(func.params.begin(), pandasm::Type(ss.str(), 0), EXTENSION);
392
393 Program()->functionTable.emplace(func.name, std::move(func));
394
395 arrayRecord.metadata->SetAttribute(Signatures::EXTERNAL);
396 Program()->recordTable.emplace(arrayRecord.name, std::move(arrayRecord));
397 Program()->arrayTypes.emplace(PandasmTypeWithRank(arrayType));
398 }
399
GenInterfaceRecord(const ir::TSInterfaceDeclaration * interfaceDecl,bool external)400 void ETSEmitter::GenInterfaceRecord(const ir::TSInterfaceDeclaration *interfaceDecl, bool external)
401 {
402 auto *baseType = interfaceDecl->TsType()->AsETSObjectType();
403
404 auto interfaceRecord = pandasm::Record(interfaceDecl->InternalName().Mutf8(), Program()->lang);
405 if (external) {
406 interfaceRecord.metadata->SetAttribute(Signatures::EXTERNAL);
407 }
408
409 uint32_t accessFlags = ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE;
410
411 if (interfaceDecl->IsStatic()) {
412 accessFlags |= ACC_STATIC;
413 }
414
415 interfaceRecord.metadata->SetAccessFlags(accessFlags);
416 interfaceRecord.sourceFile =
417 Context()->parserProgram->VarBinder()->Program()->SourceFile().GetAbsolutePath().Mutf8();
418 interfaceRecord.metadata->SetAttributeValue(Signatures::EXTENDS_ATTRIBUTE, Signatures::BUILTIN_OBJECT);
419
420 for (auto *it : baseType->Interfaces()) {
421 auto *declNode = it->GetDeclNode();
422 ASSERT(declNode->IsTSInterfaceDeclaration());
423 std::string name = declNode->AsTSInterfaceDeclaration()->InternalName().Mutf8();
424 interfaceRecord.metadata->SetAttributeValue(Signatures::IMPLEMENTS_ATTRIBUTE, name);
425 }
426
427 GenClassInheritedFields(baseType, interfaceRecord);
428
429 for (const auto *prop : interfaceDecl->Body()->Body()) {
430 if (prop->IsClassProperty()) {
431 GenClassField(prop->AsClassProperty(), interfaceRecord, external);
432 } else if (prop->IsMethodDefinition()) {
433 GenInterfaceMethodDefinition(prop->AsMethodDefinition(), external);
434 }
435 }
436
437 Program()->recordTable.emplace(interfaceRecord.name, std::move(interfaceRecord));
438 }
439
GenAnnotations(const ir::ClassDefinition * classDef)440 std::vector<pandasm::AnnotationData> ETSEmitter::GenAnnotations(const ir::ClassDefinition *classDef)
441 {
442 std::vector<pandasm::AnnotationData> annotations;
443 const ir::AstNode *parent = classDef->Parent();
444 while (parent != nullptr) {
445 if (parent->IsMethodDefinition()) {
446 annotations.emplace_back(GenAnnotationEnclosingMethod(parent->AsMethodDefinition()));
447 annotations.emplace_back(GenAnnotationInnerClass(classDef, parent));
448 break;
449 }
450 if (parent->IsClassDefinition()) {
451 annotations.emplace_back(GenAnnotationEnclosingClass(
452 parent->AsClassDefinition()->TsType()->AsETSObjectType()->AssemblerName().Utf8()));
453 annotations.emplace_back(GenAnnotationInnerClass(classDef, parent));
454 break;
455 }
456 parent = parent->Parent();
457 }
458
459 auto classIdent = classDef->Ident()->Name().Mutf8();
460 bool isConstruct = classIdent == Signatures::JSNEW_CLASS;
461 if (isConstruct || classIdent == Signatures::JSCALL_CLASS) {
462 auto *callNames = Context()->checker->AsETSChecker()->DynamicCallNames(isConstruct);
463 annotations.push_back(GenAnnotationDynamicCall(*callNames));
464 }
465
466 return annotations;
467 }
468
GetAccessFlags(const ir::ClassDefinition * classDef)469 static uint32_t GetAccessFlags(const ir::ClassDefinition *classDef)
470 {
471 uint32_t accessFlags = ACC_PUBLIC;
472 if (classDef->IsAbstract()) {
473 accessFlags |= ACC_ABSTRACT;
474 } else if (classDef->IsFinal()) {
475 accessFlags |= ACC_FINAL;
476 }
477
478 if (classDef->IsStatic()) {
479 accessFlags |= ACC_STATIC;
480 }
481
482 return accessFlags;
483 }
484
GenClassRecord(const ir::ClassDefinition * classDef,bool external)485 void ETSEmitter::GenClassRecord(const ir::ClassDefinition *classDef, bool external)
486 {
487 auto classRecord = pandasm::Record(classDef->InternalName().Mutf8(), Program()->lang);
488 auto baseName = classDef->Ident()->Name().Mutf8();
489 if (external) {
490 classRecord.metadata->SetAttribute(Signatures::EXTERNAL);
491 }
492
493 if (!classDef->Annotations().empty()) {
494 classRecord.metadata->SetAnnotations(GenCustomAnnotations(classDef->Annotations(), baseName));
495 }
496
497 uint32_t accessFlags = GetAccessFlags(classDef);
498 classRecord.metadata->SetAccessFlags(accessFlags);
499 classRecord.sourceFile = Context()->parserProgram->VarBinder()->Program()->SourceFile().GetAbsolutePath().Mutf8();
500
501 auto *baseType = classDef->TsType()->AsETSObjectType();
502 if (baseType->SuperType() != nullptr) {
503 classRecord.metadata->SetAttributeValue(Signatures::EXTENDS_ATTRIBUTE,
504 baseType->SuperType()->AssemblerName().Mutf8());
505 } else {
506 // NOTE: rtakacs. Replace the whole if block (below) with assert when lambda objects have super class.
507 if (baseType->AssemblerName().Mutf8() != Signatures::BUILTIN_OBJECT) {
508 classRecord.metadata->SetAttributeValue(Signatures::EXTENDS_ATTRIBUTE, Signatures::BUILTIN_OBJECT);
509 }
510 }
511
512 for (auto *it : baseType->Interfaces()) {
513 // We do not need to add dynamic interfaces
514 if (it->IsETSDynamicType()) {
515 continue;
516 }
517
518 auto *declNode = it->GetDeclNode();
519 // NOTE: itrubachev. replace it with ASSERT(decl_node->IsTSInterfaceDeclaration())
520 // after adding proper creation of lambda object in ETSFunctionType::AssignmentSource
521 if (!declNode->IsTSInterfaceDeclaration()) {
522 continue;
523 }
524 std::string name = declNode->AsTSInterfaceDeclaration()->InternalName().Mutf8();
525 classRecord.metadata->SetAttributeValue(Signatures::IMPLEMENTS_ATTRIBUTE, name);
526 }
527
528 GenClassInheritedFields(baseType, classRecord);
529 for (const auto *prop : classDef->Body()) {
530 if (!prop->IsClassProperty()) {
531 continue;
532 }
533
534 GenClassField(prop->AsClassProperty(), classRecord, external);
535 }
536
537 std::vector<pandasm::AnnotationData> annotations = GenAnnotations(classDef);
538 if (!annotations.empty()) {
539 classRecord.metadata->SetAnnotations(std::move(annotations));
540 }
541
542 Program()->recordTable.emplace(classRecord.name, std::move(classRecord));
543 }
544
545 // Helper function to check if the unary expression is a numeric literal with negation.
546 // This expression should be handled during lowering with the associated issue number.
IsNegativeLiteralNode(const ir::UnaryExpression * expr)547 static bool IsNegativeLiteralNode(const ir::UnaryExpression *expr)
548 {
549 return expr->OperatorType() == lexer::TokenType::PUNCTUATOR_MINUS && expr->Argument()->IsNumberLiteral();
550 }
551
CreateEnumProp(const ir::ClassProperty * prop,pandasm::Field & field)552 void ETSEmitter::CreateEnumProp(const ir::ClassProperty *prop, pandasm::Field &field)
553 {
554 if (prop->Value() == nullptr) {
555 return;
556 }
557 auto *init = prop->Value()->AsMemberExpression()->PropVar()->Declaration()->Node()->AsTSEnumMember()->Init();
558 field.metadata->SetFieldType(field.type);
559 if (init->IsNumberLiteral()) {
560 auto value = init->AsNumberLiteral()->Number().GetInt();
561 field.metadata->SetValue(pandasm::ScalarValue::Create<pandasm::Value::Type::I32>(value));
562 } else if (init->IsStringLiteral()) {
563 auto value = init->AsStringLiteral()->Str().Mutf8();
564 field.metadata->SetValue(pandasm::ScalarValue::Create<pandasm::Value::Type::STRING>(value));
565 } else if (init->IsUnaryExpression() && IsNegativeLiteralNode(init->AsUnaryExpression())) {
566 double doubleValue = (-1) * init->AsUnaryExpression()->Argument()->AsNumberLiteral()->Number().GetDouble();
567 field.metadata->SetValue(pandasm::ScalarValue::Create<pandasm::Value::Type::F64>(doubleValue));
568 } else {
569 UNREACHABLE();
570 }
571 }
572
ProcessArrayExpression(std::string & baseName,std::vector<std::pair<std::string,std::vector<pandasm::LiteralArray::Literal>>> & result,std::vector<pandasm::LiteralArray::Literal> & literals,const ir::Expression * elem)573 void ETSEmitter::ProcessArrayExpression(
574 std::string &baseName, std::vector<std::pair<std::string, std::vector<pandasm::LiteralArray::Literal>>> &result,
575 std::vector<pandasm::LiteralArray::Literal> &literals, const ir::Expression *elem)
576 {
577 auto litArrays = CreateLiteralArray(baseName, elem);
578 auto emplaceLiteral = [&literals](panda_file::LiteralTag tag, const auto &value) {
579 literals.emplace_back(pandasm::LiteralArray::Literal {tag, value});
580 };
581
582 emplaceLiteral(panda_file::LiteralTag::TAGVALUE, static_cast<uint8_t>(panda_file::LiteralTag::LITERALARRAY));
583 emplaceLiteral(panda_file::LiteralTag::LITERALARRAY, litArrays.back().first);
584 for (const auto &item : litArrays) {
585 result.push_back(item);
586 }
587 }
588
ProcessEnumExpression(std::vector<pandasm::LiteralArray::Literal> & literals,const ir::Expression * elem)589 static void ProcessEnumExpression(std::vector<pandasm::LiteralArray::Literal> &literals, const ir::Expression *elem)
590 {
591 auto *memberExpr = elem->IsCallExpression() ? elem->AsCallExpression()->Arguments()[0]->AsMemberExpression()
592 : elem->AsMemberExpression();
593 auto *init = memberExpr->PropVar()->Declaration()->Node()->AsTSEnumMember()->Init();
594 if (init->IsNumberLiteral()) {
595 auto enumValue = static_cast<uint32_t>(init->AsNumberLiteral()->Number().GetInt());
596 literals.emplace_back(pandasm::LiteralArray::Literal {panda_file::LiteralTag::TAGVALUE,
597 static_cast<uint8_t>(panda_file::LiteralTag::INTEGER)});
598 literals.emplace_back(pandasm::LiteralArray::Literal {panda_file::LiteralTag::INTEGER, enumValue});
599 } else {
600 auto enumValue = init->AsStringLiteral()->Str().Mutf8();
601 literals.emplace_back(pandasm::LiteralArray::Literal {panda_file::LiteralTag::TAGVALUE,
602 static_cast<uint8_t>(panda_file::LiteralTag::STRING)});
603 literals.emplace_back(pandasm::LiteralArray::Literal {panda_file::LiteralTag::STRING, enumValue});
604 }
605 }
606
ProcessArrayElement(const ir::Expression * elem,std::vector<pandasm::LiteralArray::Literal> & literals,std::string & baseName,LiteralArrayVector & result)607 void ETSEmitter::ProcessArrayElement(const ir::Expression *elem, std::vector<pandasm::LiteralArray::Literal> &literals,
608 std::string &baseName, LiteralArrayVector &result)
609 {
610 switch (elem->Type()) {
611 case ir::AstNodeType::NUMBER_LITERAL: {
612 auto doubleValue = elem->AsNumberLiteral()->Number().GetDouble();
613 literals.emplace_back(pandasm::LiteralArray::Literal {
614 panda_file::LiteralTag::TAGVALUE, static_cast<uint8_t>(panda_file::LiteralTag::DOUBLE)});
615 literals.emplace_back(pandasm::LiteralArray::Literal {panda_file::LiteralTag::DOUBLE, doubleValue});
616 break;
617 }
618 case ir::AstNodeType::BOOLEAN_LITERAL: {
619 bool boolValue = elem->AsBooleanLiteral()->Value();
620 literals.emplace_back(pandasm::LiteralArray::Literal {panda_file::LiteralTag::TAGVALUE,
621 static_cast<uint8_t>(panda_file::LiteralTag::BOOL)});
622 literals.emplace_back(pandasm::LiteralArray::Literal {panda_file::LiteralTag::BOOL, boolValue});
623 break;
624 }
625 case ir::AstNodeType::STRING_LITERAL: {
626 std::string stringValue {elem->AsStringLiteral()->Str().Utf8()};
627 literals.emplace_back(pandasm::LiteralArray::Literal {
628 panda_file::LiteralTag::TAGVALUE, static_cast<uint8_t>(panda_file::LiteralTag::STRING)});
629 literals.emplace_back(pandasm::LiteralArray::Literal {panda_file::LiteralTag::STRING, stringValue});
630 break;
631 }
632 case ir::AstNodeType::ARRAY_EXPRESSION: {
633 ProcessArrayExpression(baseName, result, literals, elem);
634 break;
635 }
636 case ir::AstNodeType::MEMBER_EXPRESSION:
637 case ir::AstNodeType::CALL_EXPRESSION: {
638 ProcessEnumExpression(literals, elem);
639 break;
640 }
641 case ir::AstNodeType::UNARY_EXPRESSION: {
642 double doubleValue = (-1) * elem->AsUnaryExpression()->Argument()->AsNumberLiteral()->Number().GetDouble();
643 literals.emplace_back(pandasm::LiteralArray::Literal {
644 panda_file::LiteralTag::TAGVALUE, static_cast<uint8_t>(panda_file::LiteralTag::DOUBLE)});
645 literals.emplace_back(pandasm::LiteralArray::Literal {panda_file::LiteralTag::DOUBLE, doubleValue});
646 break;
647 }
648 default:
649 UNREACHABLE();
650 break;
651 }
652 }
653
CreateLiteralArray(std::string & baseName,const ir::Expression * array)654 LiteralArrayVector ETSEmitter::CreateLiteralArray(std::string &baseName, const ir::Expression *array)
655 {
656 LiteralArrayVector result;
657 std::vector<pandasm::LiteralArray::Literal> literals;
658 ArenaVector<ir::Expression *> elements {array->AsArrayExpression()->Elements()};
659
660 for (const auto *elem : elements) {
661 ProcessArrayElement(elem, literals, baseName, result);
662 }
663
664 std::string litArrayName = GenerateMangledName(baseName, std::to_string(g_litArrayValueCount));
665 ++g_litArrayValueCount;
666 result.emplace_back(litArrayName, literals);
667 return result;
668 }
669
CreateLiteralArrayProp(const ir::ClassProperty * prop,std::string & baseName,pandasm::Field & field)670 void ETSEmitter::CreateLiteralArrayProp(const ir::ClassProperty *prop, std::string &baseName, pandasm::Field &field)
671 {
672 uint8_t rank = 1;
673 auto *elemType = prop->TsType()->AsETSArrayType()->ElementType();
674 while (elemType->IsETSArrayType()) {
675 ++rank;
676 elemType = elemType->AsETSArrayType()->ElementType();
677 }
678 if (elemType->IsETSEnumType()) {
679 field.type = PandasmTypeWithRank(elemType, rank);
680 } else {
681 std::stringstream ss;
682 elemType->ToAssemblerType(ss);
683 field.type = pandasm::Type(ss.str(), rank);
684 }
685
686 auto value = prop->Value();
687 if (value != nullptr) {
688 std::string newBaseName = GenerateMangledName(baseName, field.name);
689 auto litArray = CreateLiteralArray(newBaseName, value);
690 for (const auto &item : litArray) {
691 Program()->literalarrayTable.emplace(item.first, item.second);
692 }
693 field.metadata->SetValue(
694 pandasm::ScalarValue::Create<pandasm::Value::Type::LITERALARRAY>(std::string_view {litArray.back().first}));
695 }
696 }
697
GenCustomAnnotationProp(const ir::ClassProperty * prop,std::string & baseName,pandasm::Record & record,bool external)698 void ETSEmitter::GenCustomAnnotationProp(const ir::ClassProperty *prop, std::string &baseName, pandasm::Record &record,
699 bool external)
700 {
701 auto field = pandasm::Field(Program()->lang);
702 auto *type = prop->TsType();
703 field.name = prop->Id()->Name().Mutf8();
704 field.type = PandasmTypeWithRank(type);
705 field.metadata->SetAccessFlags(TranslateModifierFlags(prop->Modifiers()));
706
707 if (external) {
708 field.metadata->SetAttribute(Signatures::EXTERNAL);
709 } else if (type->IsETSEnumType()) {
710 CreateEnumProp(prop, field);
711 } else if (type->IsETSPrimitiveType() || type->IsETSStringType()) {
712 EmitDefaultFieldValue(field, prop->Value());
713 } else if (type->IsETSArrayType()) {
714 CreateLiteralArrayProp(prop, baseName, field);
715 } else {
716 UNREACHABLE();
717 }
718 record.fieldList.emplace_back(std::move(field));
719 }
720
GenCustomAnnotationRecord(const ir::AnnotationDeclaration * annoDecl,std::string & baseName,bool external)721 void ETSEmitter::GenCustomAnnotationRecord(const ir::AnnotationDeclaration *annoDecl, std::string &baseName,
722 bool external)
723 {
724 auto annoRecord = pandasm::Record(annoDecl->InternalName().Mutf8(), Program()->lang);
725 if (Program()->recordTable.find(annoRecord.name) != Program()->recordTable.end()) {
726 return;
727 }
728
729 if (external) {
730 annoRecord.metadata->SetAttribute(Signatures::EXTERNAL);
731 }
732
733 uint32_t accessFlags = ACC_PUBLIC | ACC_ABSTRACT | ACC_ANNOTATION;
734 annoRecord.metadata->SetAccessFlags(accessFlags);
735 annoRecord.sourceFile = Context()->parserProgram->VarBinder()->Program()->SourceFile().GetAbsolutePath().Mutf8();
736 for (auto *it : annoDecl->Properties()) {
737 GenCustomAnnotationProp(it->AsClassProperty(), baseName, annoRecord, external);
738 }
739
740 Program()->recordTable.emplace(annoRecord.name, std::move(annoRecord));
741 }
742
CreateAnnotationScalarValue(checker::TypeFlag typeKind,const ir::Literal * init)743 static pandasm::ScalarValue CreateAnnotationScalarValue(checker::TypeFlag typeKind, const ir::Literal *init)
744 {
745 switch (typeKind) {
746 case checker::TypeFlag::ETS_BOOLEAN: {
747 return pandasm::ScalarValue::Create<pandasm::Value::Type::U1>(
748 static_cast<uint8_t>(init->AsBooleanLiteral()->Value()));
749 }
750 case checker::TypeFlag::BYTE: {
751 return pandasm::ScalarValue::Create<pandasm::Value::Type::I8>(init->AsNumberLiteral()->Number().GetInt());
752 }
753 case checker::TypeFlag::SHORT: {
754 return pandasm::ScalarValue::Create<pandasm::Value::Type::I16>(init->AsNumberLiteral()->Number().GetInt());
755 }
756 case checker::TypeFlag::INT: {
757 return pandasm::ScalarValue::Create<pandasm::Value::Type::I32>(init->AsNumberLiteral()->Number().GetInt());
758 }
759 case checker::TypeFlag::LONG: {
760 return pandasm::ScalarValue::Create<pandasm::Value::Type::I64>(init->AsNumberLiteral()->Number().GetLong());
761 }
762 case checker::TypeFlag::FLOAT: {
763 return pandasm::ScalarValue::Create<pandasm::Value::Type::F32>(
764 init->AsNumberLiteral()->Number().GetFloat());
765 }
766 case checker::TypeFlag::DOUBLE: {
767 return pandasm::ScalarValue::Create<pandasm::Value::Type::F64>(
768 init->AsNumberLiteral()->Number().GetDouble());
769 }
770 case checker::TypeFlag::ETS_OBJECT: {
771 return pandasm::ScalarValue::Create<pandasm::Value::Type::STRING>(init->AsStringLiteral()->Str().Mutf8());
772 }
773 default: {
774 UNREACHABLE();
775 }
776 }
777 }
778
ProcessArrayType(const ir::ClassProperty * prop,std::string & baseName,const ir::Expression * init)779 pandasm::AnnotationElement ETSEmitter::ProcessArrayType(const ir::ClassProperty *prop, std::string &baseName,
780 const ir::Expression *init)
781 {
782 auto propName = prop->Id()->Name().Mutf8();
783 std::string newBaseName = GenerateMangledName(baseName, propName);
784 auto litArrays = CreateLiteralArray(newBaseName, init);
785
786 for (const auto &item : litArrays) {
787 Program()->literalarrayTable.emplace(item.first, item.second);
788 }
789
790 return pandasm::AnnotationElement {
791 propName, std::make_unique<pandasm::ScalarValue>(pandasm::ScalarValue::Create<pandasm::Value::Type::STRING>(
792 std::string_view {litArrays.back().first}))};
793 }
794
GenCustomAnnotationElement(const ir::ClassProperty * prop,std::string & baseName)795 pandasm::AnnotationElement ETSEmitter::GenCustomAnnotationElement(const ir::ClassProperty *prop, std::string &baseName)
796 {
797 const auto *init = prop->Value();
798 const auto *type = init->TsType();
799 auto typeKind = checker::ETSChecker::TypeKind(type);
800 auto propName = prop->Id()->Name().Mutf8();
801 if (type->IsETSArrayType()) {
802 return ProcessArrayType(prop, baseName, init);
803 }
804 switch (checker::ETSChecker::TypeKind(
805 Context()->checker->AsETSChecker()->MaybeUnboxType(const_cast<checker::Type *>(type)))) {
806 case checker::TypeFlag::BYTE:
807 case checker::TypeFlag::SHORT:
808 case checker::TypeFlag::INT:
809 case checker::TypeFlag::LONG:
810 case checker::TypeFlag::FLOAT:
811 case checker::TypeFlag::DOUBLE:
812 case checker::TypeFlag::ETS_BOOLEAN:
813 case checker::TypeFlag::ETS_OBJECT: {
814 if (init->IsUnaryExpression() && IsNegativeLiteralNode(init->AsUnaryExpression())) {
815 double negNumberValue =
816 (-1) * init->AsUnaryExpression()->Argument()->AsNumberLiteral()->Number().GetDouble();
817 return pandasm::AnnotationElement {
818 propName, std::make_unique<pandasm::ScalarValue>(
819 pandasm::ScalarValue::Create<pandasm::Value::Type::F64>(negNumberValue))};
820 }
821 return pandasm::AnnotationElement {propName, std::make_unique<pandasm::ScalarValue>(
822 CreateAnnotationScalarValue(typeKind, init->AsLiteral()))};
823 }
824 case checker::TypeFlag::ETS_INT_ENUM: {
825 auto *initValue = init->AsMemberExpression()->PropVar()->Declaration()->Node()->AsTSEnumMember()->Init();
826 auto enumValue = static_cast<uint32_t>(initValue->AsNumberLiteral()->Number().GetInt());
827 auto intEnumValue = pandasm::ScalarValue::Create<pandasm::Value::Type::I32>(enumValue);
828 return pandasm::AnnotationElement {propName, std::make_unique<pandasm::ScalarValue>(intEnumValue)};
829 }
830 case checker::TypeFlag::ETS_STRING_ENUM: {
831 auto *initValue = init->AsMemberExpression()->PropVar()->Declaration()->Node()->AsTSEnumMember()->Init();
832 auto enumValue = initValue->AsStringLiteral()->Str().Mutf8();
833 auto stringValue = pandasm::ScalarValue::Create<pandasm::Value::Type::STRING>(enumValue);
834 return pandasm::AnnotationElement {propName, std::make_unique<pandasm::ScalarValue>(stringValue)};
835 }
836 default:
837 UNREACHABLE();
838 }
839 }
840
GenCustomAnnotation(ir::AnnotationUsage * anno,std::string & baseName)841 pandasm::AnnotationData ETSEmitter::GenCustomAnnotation(ir::AnnotationUsage *anno, std::string &baseName)
842 {
843 auto *annoDecl = anno->GetBaseName()->Variable()->Declaration()->Node()->AsAnnotationDeclaration();
844 pandasm::AnnotationData annotation(annoDecl->InternalName().Mutf8());
845 if (annoDecl->IsImportDeclaration()) {
846 auto annoRecord = pandasm::Record(annoDecl->InternalName().Mutf8(), Program()->lang);
847 annoRecord.metadata->SetAttribute(Signatures::EXTERNAL);
848 uint32_t accessFlags = ACC_PUBLIC | ACC_ABSTRACT | ACC_ANNOTATION;
849 annoRecord.metadata->SetAccessFlags(accessFlags);
850 Program()->recordTable.emplace(annoRecord.name, std::move(annoRecord));
851 }
852
853 for (auto *prop : anno->Properties()) {
854 annotation.AddElement(GenCustomAnnotationElement(prop->AsClassProperty(), baseName));
855 }
856 return annotation;
857 }
858
GenCustomAnnotations(const ArenaVector<ir::AnnotationUsage * > & annotationUsages,std::string & baseName)859 std::vector<pandasm::AnnotationData> ETSEmitter::GenCustomAnnotations(
860 const ArenaVector<ir::AnnotationUsage *> &annotationUsages, std::string &baseName)
861 {
862 std::vector<pandasm::AnnotationData> annotations;
863 for (auto *anno : annotationUsages) {
864 auto newBaseName = GenerateMangledName(baseName, anno->GetBaseName()->Name().Mutf8());
865 annotations.emplace_back(GenCustomAnnotation(anno, newBaseName));
866 }
867 return annotations;
868 }
869
GenAnnotationSignature(const ir::ClassDefinition * classDef)870 pandasm::AnnotationData ETSEmitter::GenAnnotationSignature(const ir::ClassDefinition *classDef)
871 {
872 static constexpr std::string_view OBJECT = "Lstd/core/Object";
873 std::vector<pandasm::ScalarValue> parts {};
874 std::stringstream ss {};
875 const auto ¶ms = classDef->TypeParams()->Params();
876
877 bool firstIteration = true;
878 for (const auto *param : params) {
879 if (firstIteration) {
880 ss << Signatures::GENERIC_BEGIN;
881 firstIteration = false;
882 }
883 ss << param->Name()->Name() << Signatures::MANGLE_BEGIN;
884 parts.emplace_back(pandasm::ScalarValue::Create<pandasm::Value::Type::STRING>(ss.str()));
885
886 std::stringstream {}.swap(ss);
887 if (param->Constraint() == nullptr) {
888 ss << OBJECT;
889 } else {
890 param->Constraint()->TsType()->ToAssemblerTypeWithRank(ss);
891 auto str = ss.str();
892 std::replace(str.begin(), str.end(), *Signatures::METHOD_SEPARATOR.begin(),
893 *Signatures::NAMESPACE_SEPARATOR.begin());
894 std::stringstream {}.swap(ss);
895 ss << Signatures::CLASS_REF_BEGIN << str << Signatures::MANGLE_SEPARATOR;
896 }
897
898 parts.emplace_back(pandasm::ScalarValue::Create<pandasm::Value::Type::STRING>(ss.str()));
899 std::stringstream {}.swap(ss); // cleanup
900 }
901
902 ss << Signatures::GENERIC_END;
903 parts.emplace_back(pandasm::ScalarValue::Create<pandasm::Value::Type::STRING>(ss.str()));
904
905 std::stringstream {}.swap(ss);
906 if (classDef->TsType()->AsETSObjectType()->SuperType() == nullptr) {
907 ss << OBJECT;
908 } else {
909 ss << Signatures::CLASS_REF_BEGIN;
910 auto superType = classDef->TsType()->AsETSObjectType()->SuperType()->AssemblerName().Mutf8();
911 std::replace(superType.begin(), superType.end(), *Signatures::METHOD_SEPARATOR.begin(),
912 *Signatures::NAMESPACE_SEPARATOR.begin());
913 ss << superType << Signatures::MANGLE_SEPARATOR;
914 }
915 parts.emplace_back(pandasm::ScalarValue::Create<pandasm::Value::Type::STRING>(ss.str()));
916
917 GenAnnotationRecord(Signatures::ETS_ANNOTATION_SIGNATURE);
918 pandasm::AnnotationData signature(Signatures::ETS_ANNOTATION_SIGNATURE);
919 pandasm::AnnotationElement value(
920 Signatures::ANNOTATION_KEY_VALUE,
921 std::make_unique<pandasm::ArrayValue>(pandasm::Value::Type::STRING, std::move(parts)));
922 signature.AddElement(std::move(value));
923 return signature;
924 }
925
GenAnnotationEnclosingMethod(const ir::MethodDefinition * methodDef)926 pandasm::AnnotationData ETSEmitter::GenAnnotationEnclosingMethod(const ir::MethodDefinition *methodDef)
927 {
928 GenAnnotationRecord(Signatures::ETS_ANNOTATION_ENCLOSING_METHOD);
929 pandasm::AnnotationData enclosingMethod(Signatures::ETS_ANNOTATION_ENCLOSING_METHOD);
930 pandasm::AnnotationElement value(
931 Signatures::ANNOTATION_KEY_VALUE,
932 std::make_unique<pandasm::ScalarValue>(pandasm::ScalarValue::Create<pandasm::Value::Type::METHOD>(
933 methodDef->Function()->Scope()->InternalName().Mutf8())));
934 enclosingMethod.AddElement(std::move(value));
935 return enclosingMethod;
936 }
937
GenAnnotationEnclosingClass(std::string_view className)938 pandasm::AnnotationData ETSEmitter::GenAnnotationEnclosingClass(std::string_view className)
939 {
940 GenAnnotationRecord(Signatures::ETS_ANNOTATION_ENCLOSING_CLASS);
941 pandasm::AnnotationData enclosingClass(Signatures::ETS_ANNOTATION_ENCLOSING_CLASS);
942 pandasm::AnnotationElement value(
943 Signatures::ANNOTATION_KEY_VALUE,
944 std::make_unique<pandasm::ScalarValue>(
945 pandasm::ScalarValue::Create<pandasm::Value::Type::RECORD>(pandasm::Type::FromName(className, true))));
946 enclosingClass.AddElement(std::move(value));
947 return enclosingClass;
948 }
949
GenAnnotationInnerClass(const ir::ClassDefinition * classDef,const ir::AstNode * parent)950 pandasm::AnnotationData ETSEmitter::GenAnnotationInnerClass(const ir::ClassDefinition *classDef,
951 const ir::AstNode *parent)
952 {
953 GenAnnotationRecord(Signatures::ETS_ANNOTATION_INNER_CLASS);
954 pandasm::AnnotationData innerClass(Signatures::ETS_ANNOTATION_INNER_CLASS);
955 const bool isAnonymous = (classDef->Modifiers() & ir::ClassDefinitionModifiers::ANONYMOUS) != 0;
956 pandasm::AnnotationElement name(Signatures::ANNOTATION_KEY_NAME,
957 std::make_unique<pandasm::ScalarValue>(
958 isAnonymous
959 ? pandasm::ScalarValue::Create<pandasm::Value::Type::STRING_NULLPTR>(0)
960 : pandasm::ScalarValue::Create<pandasm::Value::Type::STRING>(
961 classDef->TsType()->AsETSObjectType()->AssemblerName().Mutf8())));
962 innerClass.AddElement(std::move(name));
963
964 pandasm::AnnotationElement accessFlags(
965 Signatures::ANNOTATION_KEY_ACCESS_FLAGS,
966 std::make_unique<pandasm::ScalarValue>(
967 pandasm::ScalarValue::Create<pandasm::Value::Type::I32>(TranslateModifierFlags(parent->Modifiers()))));
968 innerClass.AddElement(std::move(accessFlags));
969 return innerClass;
970 }
971
FindAsyncImpl(ir::ScriptFunction * asyncFunc)972 ir::MethodDefinition *ETSEmitter::FindAsyncImpl(ir::ScriptFunction *asyncFunc)
973 {
974 std::string implName = checker::ETSChecker::GetAsyncImplName(asyncFunc->Id()->Name());
975 ir::AstNode *ownerNode = asyncFunc->Signature()->Owner()->GetDeclNode();
976 ASSERT(ownerNode != nullptr && ownerNode->IsClassDefinition());
977 const ir::ClassDefinition *classDef = ownerNode->AsClassDefinition();
978 ASSERT(classDef != nullptr);
979
980 auto it = std::find_if(classDef->Body().rbegin(), classDef->Body().rend(), [&implName](ir::AstNode *node) {
981 return node->IsMethodDefinition() && node->AsMethodDefinition()->Id()->Name().Utf8() == implName;
982 });
983 if (it == classDef->Body().rend()) {
984 return nullptr;
985 }
986
987 ir::MethodDefinition *method = (*it)->AsMethodDefinition();
988 auto *checker = static_cast<checker::ETSChecker *>(Context()->checker);
989 checker::TypeRelation *typeRel = checker->Relation();
990 checker::SavedTypeRelationFlagsContext savedFlagsCtx(typeRel, checker::TypeRelationFlag::NO_RETURN_TYPE_CHECK);
991 method->Function()->Signature()->Compatible(typeRel, asyncFunc->Signature());
992 auto overloadIt = method->Overloads().begin();
993 while (overloadIt != method->Overloads().end() && !typeRel->IsTrue()) {
994 method = *overloadIt;
995 method->Function()->Signature()->Compatible(typeRel, asyncFunc->Signature());
996 ++overloadIt;
997 }
998 return typeRel->IsTrue() ? method : nullptr;
999 }
1000
GenAnnotationAsync(ir::ScriptFunction * scriptFunc)1001 pandasm::AnnotationData ETSEmitter::GenAnnotationAsync(ir::ScriptFunction *scriptFunc)
1002 {
1003 GenAnnotationRecord(Signatures::ETS_COROUTINE_ASYNC);
1004 const ir::MethodDefinition *impl = FindAsyncImpl(scriptFunc);
1005 ASSERT(impl != nullptr);
1006 pandasm::AnnotationData ann(Signatures::ETS_COROUTINE_ASYNC);
1007 pandasm::AnnotationElement value(
1008 Signatures::ANNOTATION_KEY_VALUE,
1009 std::make_unique<pandasm::ScalarValue>(pandasm::ScalarValue::Create<pandasm::Value::Type::METHOD>(
1010 impl->Function()->Scope()->InternalName().Mutf8())));
1011 ann.AddElement(std::move(value));
1012 return ann;
1013 }
1014
GenAnnotationDynamicCall(DynamicCallNamesMap & callNames)1015 pandasm::AnnotationData ETSEmitter::GenAnnotationDynamicCall(DynamicCallNamesMap &callNames)
1016 {
1017 GenAnnotationRecord(Signatures::ETS_ANNOTATION_DYNAMIC_CALL);
1018 pandasm::AnnotationData dynamicCallSig(Signatures::ETS_ANNOTATION_DYNAMIC_CALL);
1019 std::vector<pandasm::ScalarValue> allParts {};
1020 for (auto &[parts, startIdx] : callNames) {
1021 startIdx = allParts.size();
1022 for (const auto &str : parts) {
1023 allParts.emplace_back(pandasm::ScalarValue::Create<pandasm::Value::Type::STRING>(str.Utf8()));
1024 }
1025 }
1026 pandasm::AnnotationElement value(
1027 Signatures::ANNOTATION_KEY_VALUE,
1028 std::make_unique<pandasm::ArrayValue>(pandasm::Value::Type::STRING, std::move(allParts)));
1029 dynamicCallSig.AddElement(std::move(value));
1030 return dynamicCallSig;
1031 }
1032
GenAnnotationRecord(std::string_view recordNameView,bool isRuntime,bool isType)1033 void ETSEmitter::GenAnnotationRecord(std::string_view recordNameView, bool isRuntime, bool isType)
1034 {
1035 const std::string recordName(recordNameView);
1036 const auto recordIt = Program()->recordTable.find(recordName);
1037 if (recordIt == Program()->recordTable.end()) {
1038 pandasm::Record record(recordName, EXTENSION);
1039 record.metadata->SetAttribute(Signatures::EXTERNAL);
1040 record.metadata->SetAttribute(Signatures::ANNOTATION_ATTRIBUTE);
1041 if (isRuntime && isType) {
1042 record.metadata->SetAttributeValue(Signatures::ANNOTATION_ATTRIBUTE_TYPE,
1043 Signatures::RUNTIME_TYPE_ANNOTATION);
1044 } else if (isRuntime && !isType) {
1045 record.metadata->SetAttributeValue(Signatures::ANNOTATION_ATTRIBUTE_TYPE, Signatures::RUNTIME_ANNOTATION);
1046 } else if (!isRuntime && isType) {
1047 record.metadata->SetAttributeValue(Signatures::ANNOTATION_ATTRIBUTE_TYPE, Signatures::TYPE_ANNOTATION);
1048 }
1049 Program()->recordTable.emplace(record.name, std::move(record));
1050 }
1051 }
1052 } // namespace ark::es2panda::compiler
1053