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