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 "ETSCompiler.h" 17 18#include "compiler/base/catchTable.h" 19#include "checker/ets/dynamic/dynamicCall.h" 20#include "compiler/base/condition.h" 21#include "compiler/base/lreference.h" 22#include "compiler/core/switchBuilder.h" 23#include "compiler/function/functionBuilder.h" 24#include "checker/ETSchecker.h" 25#include "checker/types/ets/etsDynamicFunctionType.h" 26#include "parser/ETSparser.h" 27 28namespace ark::es2panda::compiler { 29 30ETSGen *ETSCompiler::GetETSGen() const 31{ 32 return static_cast<ETSGen *>(GetCodeGen()); 33} 34 35void ETSCompiler::Compile(const ir::CatchClause *st) const 36{ 37 ETSGen *etsg = GetETSGen(); 38 compiler::LocalRegScope lrs(etsg, st->Scope()->ParamScope()); 39 etsg->SetAccumulatorType(st->TsType()); 40 auto lref = compiler::ETSLReference::Create(etsg, st->Param(), true); 41 lref.SetValue(); 42 st->Body()->Compile(etsg); 43} 44 45void ETSCompiler::Compile(const ir::ClassProperty *st) const 46{ 47 ETSGen *etsg = GetETSGen(); 48 if (st->Value() == nullptr && st->TsType()->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)) { 49 return; 50 } 51 52 auto ttctx = compiler::TargetTypeContext(etsg, st->TsType()); 53 compiler::RegScope rs(etsg); 54 55 if (st->Value() == nullptr) { 56 etsg->LoadDefaultValue(st, st->TsType()); 57 } else if (!etsg->TryLoadConstantExpression(st->Value())) { 58 st->Value()->Compile(etsg); 59 etsg->ApplyConversion(st->Value(), st->TsType()); 60 } 61 62 if (st->IsStatic()) { 63 etsg->StoreStaticOwnProperty(st, st->TsType(), st->Key()->AsIdentifier()->Name()); 64 } else { 65 etsg->StoreProperty(st, st->TsType(), etsg->GetThisReg(), st->Key()->AsIdentifier()->Name()); 66 } 67} 68 69void ETSCompiler::Compile(const ir::TemplateElement *expr) const 70{ 71 ETSGen *etsg = GetETSGen(); 72 etsg->LoadAccumulatorString(expr, expr->Cooked()); 73 etsg->SetAccumulatorType(expr->TsType()); 74 ASSERT(etsg->Checker()->Relation()->IsIdenticalTo(etsg->GetAccumulatorType(), expr->TsType())); 75} 76 77void ETSCompiler::Compile(const ir::ETSClassLiteral *expr) const 78{ 79 ETSGen *etsg = GetETSGen(); 80 81 auto *literal = expr->Expr(); 82 auto *literalType = literal->TsType(); 83 84 bool const isPrimitive = !literalType->IsETSReferenceType(); 85 if (!isPrimitive) { 86 literal->Compile(etsg); 87 } else { 88 ASSERT(literalType->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)); 89 etsg->SetAccumulatorType(literalType); 90 } 91 92 etsg->GetType(expr, isPrimitive); 93 ASSERT(etsg->Checker()->Relation()->IsIdenticalTo(etsg->GetAccumulatorType(), expr->TsType())); 94} 95 96void ETSCompiler::Compile(const ir::ETSFunctionType *node) const 97{ 98 ETSGen *etsg = GetETSGen(); 99 etsg->LoadAccumulatorNull(node, node->TsType()); 100 ASSERT(etsg->Checker()->Relation()->IsIdenticalTo(etsg->GetAccumulatorType(), node->TsType())); 101} 102 103void ETSCompiler::Compile([[maybe_unused]] const ir::ETSLaunchExpression *expr) const 104{ 105#ifdef PANDA_WITH_ETS 106 ETSGen *etsg = GetETSGen(); 107 compiler::RegScope rs(etsg); 108 compiler::VReg calleeReg = etsg->AllocReg(); 109 checker::Signature *signature = expr->expr_->Signature(); 110 bool isStatic = signature->HasSignatureFlag(checker::SignatureFlags::STATIC); 111 if (expr->expr_->Callee()->IsIdentifier()) { 112 if (!isStatic) { 113 etsg->LoadThis(expr->expr_); 114 etsg->StoreAccumulator(expr, calleeReg); 115 } 116 } else if (expr->expr_->Callee()->IsMemberExpression()) { 117 if (!isStatic) { 118 expr->expr_->Callee()->AsMemberExpression()->Object()->Compile(etsg); 119 etsg->StoreAccumulator(expr, calleeReg); 120 } 121 } else { 122 expr->expr_->Callee()->Compile(etsg); 123 etsg->StoreAccumulator(expr, calleeReg); 124 } 125 126 if (isStatic) { 127 etsg->LaunchExact(expr, signature, expr->expr_->Arguments()); 128 } else { 129 etsg->LaunchVirtual(expr, signature, calleeReg, expr->expr_->Arguments()); 130 } 131 132 etsg->SetAccumulatorType(expr->TsType()); 133#endif // PANDA_WITH_ETS 134} 135 136void ETSCompiler::Compile(const ir::ETSNewArrayInstanceExpression *expr) const 137{ 138 ETSGen *etsg = GetETSGen(); 139 compiler::RegScope rs(etsg); 140 compiler::TargetTypeContext ttctx(etsg, etsg->Checker()->GlobalIntType()); 141 142 expr->Dimension()->Compile(etsg); 143 144 compiler::VReg arr = etsg->AllocReg(); 145 compiler::VReg dim = etsg->AllocReg(); 146 etsg->ApplyConversionAndStoreAccumulator(expr, dim, expr->Dimension()->TsType()); 147 etsg->NewArray(expr, arr, dim, expr->TsType()); 148 149 const auto *exprType = expr->TypeReference()->TsType(); 150 151 const bool isUnionTypeContainsUndefined = 152 expr->TypeReference()->IsETSTypeReference() && exprType->IsETSUnionType() && 153 exprType->AsETSUnionType()->HasType(etsg->Checker()->GlobalETSUndefinedType()); 154 if (expr->Signature() != nullptr || isUnionTypeContainsUndefined) { 155 compiler::VReg countReg = etsg->AllocReg(); 156 auto *startLabel = etsg->AllocLabel(); 157 auto *endLabel = etsg->AllocLabel(); 158 etsg->MoveImmediateToRegister(expr, countReg, checker::TypeFlag::INT, static_cast<std::int32_t>(0)); 159 const auto indexReg = etsg->AllocReg(); 160 161 etsg->SetLabel(expr, startLabel); 162 etsg->LoadAccumulator(expr, dim); 163 etsg->JumpCompareRegister<compiler::Jle>(expr, countReg, endLabel); 164 165 etsg->LoadAccumulator(expr, countReg); 166 etsg->StoreAccumulator(expr, indexReg); 167 168 const compiler::TargetTypeContext ttctx2(etsg, exprType); 169 ArenaVector<ir::Expression *> arguments(GetCodeGen()->Allocator()->Adapter()); 170 if (isUnionTypeContainsUndefined) { 171 exprType = etsg->LoadDefaultValue(expr, exprType); 172 } else { 173 etsg->InitObject(expr, expr->Signature(), arguments); 174 } 175 etsg->StoreArrayElement(expr, arr, indexReg, exprType); 176 177 etsg->IncrementImmediateRegister(expr, countReg, checker::TypeFlag::INT, static_cast<std::int32_t>(1)); 178 etsg->JumpTo(expr, startLabel); 179 etsg->SetLabel(expr, endLabel); 180 } 181 182 etsg->SetVRegType(arr, expr->TsType()); 183 etsg->LoadAccumulator(expr, arr); 184 185 ASSERT(etsg->Checker()->Relation()->IsIdenticalTo(etsg->GetAccumulatorType(), expr->TsType())); 186} 187 188static std::pair<VReg, VReg> LoadDynamicName(compiler::ETSGen *etsg, const ir::AstNode *node, 189 const ArenaVector<util::StringView> &dynName, bool isConstructor) 190{ 191 auto *checker = const_cast<checker::ETSChecker *>(etsg->Checker()->AsETSChecker()); 192 auto *callNames = checker->DynamicCallNames(isConstructor); 193 194 auto qnameStart = etsg->AllocReg(); 195 auto qnameLen = etsg->AllocReg(); 196 197 TargetTypeContext ttctx(etsg, nullptr); // without this ints will be cast to JSValue 198 etsg->LoadAccumulatorInt(node, callNames->at(dynName)); 199 etsg->StoreAccumulator(node, qnameStart); 200 etsg->LoadAccumulatorInt(node, dynName.size()); 201 etsg->StoreAccumulator(node, qnameLen); 202 return {qnameStart, qnameLen}; 203} 204 205static void CreateDynamicObject(const ir::AstNode *node, compiler::ETSGen *etsg, const ir::Expression *typeRef, 206 checker::Signature *signature, const ArenaVector<ir::Expression *> &arguments) 207{ 208 auto objReg = etsg->AllocReg(); 209 210 auto callInfo = checker::DynamicCall::ResolveCall(etsg->VarBinder(), typeRef); 211 if (callInfo.obj->IsETSImportDeclaration()) { 212 etsg->LoadAccumulatorDynamicModule(node, callInfo.obj->AsETSImportDeclaration()); 213 } else { 214 callInfo.obj->Compile(etsg); 215 } 216 217 etsg->StoreAccumulator(node, objReg); 218 219 auto [qnameStart, qnameLen] = LoadDynamicName(etsg, node, callInfo.name, true); 220 etsg->CallDynamic(ETSGen::CallDynamicData {node, objReg, qnameStart}, qnameLen, signature, arguments); 221} 222 223static void ConvertRestArguments(checker::ETSChecker *const checker, const ir::ETSNewClassInstanceExpression *expr) 224{ 225 if (expr->GetSignature()->RestVar() != nullptr) { 226 std::size_t const argumentCount = expr->GetArguments().size(); 227 std::size_t const parameterCount = expr->GetSignature()->MinArgCount(); 228 ASSERT(argumentCount >= parameterCount); 229 230 auto &arguments = const_cast<ArenaVector<ir::Expression *> &>(expr->GetArguments()); 231 std::size_t i = parameterCount; 232 233 if (i < argumentCount && expr->GetArguments()[i]->IsSpreadElement()) { 234 arguments[i] = expr->GetArguments()[i]->AsSpreadElement()->Argument(); 235 } else { 236 ArenaVector<ir::Expression *> elements(checker->Allocator()->Adapter()); 237 for (; i < argumentCount; ++i) { 238 elements.emplace_back(expr->GetArguments()[i]); 239 } 240 auto *arrayExpression = checker->AllocNode<ir::ArrayExpression>(std::move(elements), checker->Allocator()); 241 arrayExpression->SetParent(const_cast<ir::ETSNewClassInstanceExpression *>(expr)); 242 auto restType = expr->GetSignature()->RestVar()->TsType()->AsETSArrayType(); 243 arrayExpression->SetTsType(restType); 244 arrayExpression->SetPreferredType(restType->ElementType()); 245 arguments.erase(expr->GetArguments().begin() + parameterCount, expr->GetArguments().end()); 246 arguments.emplace_back(arrayExpression); 247 } 248 } 249} 250 251static void HandleUnionTypeInForOf(compiler::ETSGen *etsg, checker::Type const *const exprType, 252 const ir::ForOfStatement *st, VReg objReg, VReg *countReg) 253{ 254 ArenaVector<Label *> labels(etsg->Allocator()->Adapter()); 255 256 for (auto it : exprType->AsETSUnionType()->ConstituentTypes()) { 257 labels.push_back(etsg->AllocLabel()); 258 etsg->LoadAccumulator(st->Right(), objReg); 259 etsg->IsInstance(st->Right(), objReg, it); 260 etsg->BranchIfTrue(st, labels.back()); 261 } 262 263 labels.push_back(etsg->AllocLabel()); 264 265 for (size_t i = 0; i < exprType->AsETSUnionType()->ConstituentTypes().size(); i++) { 266 compiler::VReg unionReg = etsg->AllocReg(); 267 auto currentType = exprType->AsETSUnionType()->ConstituentTypes()[i]; 268 etsg->SetLabel(st->Right(), labels[i]); 269 etsg->LoadAccumulator(st, objReg); 270 etsg->CastToReftype(st->Right(), currentType, false); 271 etsg->StoreAccumulator(st, unionReg); 272 etsg->LoadAccumulator(st, unionReg); 273 if (countReg == nullptr) { 274 if (currentType->IsETSArrayType()) { 275 etsg->LoadArrayLength(st, unionReg); 276 } else { 277 etsg->LoadStringLength(st); 278 } 279 } else { 280 if (currentType->IsETSArrayType()) { 281 etsg->LoadAccumulator(st, *countReg); 282 etsg->LoadArrayElement(st, unionReg); 283 } else { 284 etsg->LoadStringChar(st, unionReg, *countReg); 285 etsg->ApplyCastToBoxingFlags(st, ir::BoxingUnboxingFlags::BOX_TO_CHAR); 286 etsg->SetAccumulatorType(etsg->EmitBoxedType(ir::BoxingUnboxingFlags::BOX_TO_CHAR, st)); 287 etsg->CastToChar(st); 288 } 289 } 290 291 if (i + 1 != exprType->AsETSUnionType()->ConstituentTypes().size()) { 292 etsg->Branch(st, labels.back()); 293 } 294 } 295 296 etsg->SetLabel(st->Right(), labels.back()); 297} 298 299static void GetSizeInForOf(compiler::ETSGen *etsg, checker::Type const *const exprType, const ir::ForOfStatement *st, 300 VReg objReg) 301{ 302 if (exprType->IsETSArrayType()) { 303 etsg->LoadArrayLength(st, objReg); 304 } else if (exprType->IsETSUnionType()) { 305 HandleUnionTypeInForOf(etsg, exprType, st, objReg, nullptr); 306 } else { 307 etsg->LoadStringLength(st); 308 } 309} 310static void MaybeCastUnionTypeToFunctionType(compiler::ETSGen *etsg, const ir::CallExpression *expr, 311 checker::Signature *signature) 312{ 313 expr->Callee()->AsMemberExpression()->Object()->Compile(etsg); 314 auto objType = expr->Callee()->AsMemberExpression()->Object()->TsType(); 315 if (auto propType = expr->Callee()->AsMemberExpression()->Property()->TsType(); 316 propType != nullptr && propType->IsETSFunctionType() && objType->IsETSUnionType()) { 317 etsg->CastUnionToFunctionType(expr, objType->AsETSUnionType(), signature); 318 } 319} 320 321void ETSCompiler::Compile(const ir::ETSNewClassInstanceExpression *expr) const 322{ 323 ETSGen *etsg = GetETSGen(); 324 if (expr->TsType()->IsETSDynamicType()) { 325 compiler::RegScope rs(etsg); 326 auto *name = expr->GetTypeRef(); 327 CreateDynamicObject(expr, etsg, name, expr->signature_, expr->GetArguments()); 328 } else { 329 ConvertRestArguments(const_cast<checker::ETSChecker *>(etsg->Checker()->AsETSChecker()), expr); 330 etsg->InitObject(expr, expr->signature_, expr->GetArguments()); 331 } 332 333 etsg->SetAccumulatorType(expr->TsType()); 334} 335 336void ETSCompiler::Compile(const ir::ETSNewMultiDimArrayInstanceExpression *expr) const 337{ 338 ETSGen *etsg = GetETSGen(); 339 etsg->InitObject(expr, expr->Signature(), expr->Dimensions()); 340 etsg->SetAccumulatorType(expr->TsType()); 341} 342 343void ETSCompiler::Compile(const ir::ETSParameterExpression *expr) const 344{ 345 ETSGen *etsg = GetETSGen(); 346 expr->Ident()->Compile(etsg); 347 348 if (auto *const paramType = expr->TsType(); 349 !etsg->Checker()->AsETSChecker()->Relation()->IsIdenticalTo(paramType, etsg->GetAccumulatorType())) { 350 etsg->SetAccumulatorType(paramType); 351 } 352 353 ASSERT(etsg->Checker()->Relation()->IsIdenticalTo(etsg->GetAccumulatorType(), expr->TsType())); 354} 355 356void ETSCompiler::Compile(const ir::ETSTypeReference *node) const 357{ 358 ETSGen *etsg = GetETSGen(); 359 node->Part()->Compile(etsg); 360 ASSERT(etsg->Checker()->Relation()->IsIdenticalTo(etsg->GetAccumulatorType(), node->TsType())); 361} 362 363void ETSCompiler::Compile(const ir::ETSTypeReferencePart *node) const 364{ 365 ETSGen *etsg = GetETSGen(); 366 node->Name()->Compile(etsg); 367 ASSERT(etsg->Checker()->Relation()->IsIdenticalTo(etsg->GetAccumulatorType(), node->TsType())); 368} 369 370void ETSCompiler::Compile([[maybe_unused]] const ir::ETSWildcardType *node) const 371{ 372 ETSGen *etsg = GetETSGen(); 373 etsg->Unimplemented(); 374} 375 376void ETSCompiler::Compile(const ir::ArrayExpression *expr) const 377{ 378 ETSGen *etsg = GetETSGen(); 379 const compiler::RegScope rs(etsg); 380 381 const auto arr = etsg->AllocReg(); 382 const auto dim = etsg->AllocReg(); 383 384 const compiler::TargetTypeContext ttctx(etsg, etsg->Checker()->GlobalIntType()); 385 etsg->LoadAccumulatorInt(expr, static_cast<std::int32_t>(expr->Elements().size())); 386 etsg->StoreAccumulator(expr, dim); 387 etsg->NewArray(expr, arr, dim, expr->TsType()); 388 389 const auto indexReg = etsg->AllocReg(); 390 for (std::uint32_t i = 0; i < expr->Elements().size(); ++i) { 391 const auto *const expression = expr->Elements()[i]; 392 etsg->LoadAccumulatorInt(expr, i); 393 etsg->StoreAccumulator(expr, indexReg); 394 395 const compiler::TargetTypeContext ttctx2(etsg, expr->TsType()->AsETSArrayType()->ElementType()); 396 if (!etsg->TryLoadConstantExpression(expression)) { 397 expression->Compile(etsg); 398 } 399 400 etsg->ApplyConversion(expression, nullptr); 401 etsg->ApplyConversion(expression); 402 403 if (expression->TsType()->IsETSArrayType()) { 404 etsg->StoreArrayElement(expr, arr, indexReg, expression->TsType()); 405 } else { 406 etsg->StoreArrayElement(expr, arr, indexReg, expr->TsType()->AsETSArrayType()->ElementType()); 407 } 408 } 409 410 etsg->LoadAccumulator(expr, arr); 411 ASSERT(etsg->Checker()->Relation()->IsIdenticalTo(etsg->GetAccumulatorType(), expr->TsType())); 412} 413 414void ETSCompiler::Compile(const ir::AssignmentExpression *expr) const 415{ 416 ETSGen *etsg = GetETSGen(); 417 // All other operations are handled in OpAssignmentLowering 418 ASSERT(expr->OperatorType() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION); 419 auto *const exprType = expr->TsType(); 420 421 compiler::RegScope rs(etsg); 422 auto lref = compiler::ETSLReference::Create(etsg, expr->Left(), false); 423 auto ttctx = compiler::TargetTypeContext(etsg, exprType); 424 425 if (expr->Right()->IsNullLiteral()) { 426 etsg->LoadAccumulatorNull(expr, exprType); 427 } else { 428 expr->Right()->Compile(etsg); 429 etsg->ApplyConversion(expr->Right(), exprType); 430 etsg->SetAccumulatorType(exprType); 431 } 432 433 if (expr->Right()->TsType()->IsETSBigIntType()) { 434 // For bigints we have to copy the bigint object when performing an assignment operation 435 const VReg value = etsg->AllocReg(); 436 etsg->StoreAccumulator(expr, value); 437 etsg->CreateBigIntObject(expr, value, Signatures::BUILTIN_BIGINT_CTOR_BIGINT); 438 } 439 440 ASSERT(etsg->Checker()->Relation()->IsIdenticalTo(etsg->GetAccumulatorType(), exprType) || 441 etsg->Checker()->Relation()->IsIdenticalTo(etsg->GetAccumulatorType(), 442 etsg->Checker()->GlobalBuiltinJSValueType())); 443 lref.SetValue(); 444} 445 446void ETSCompiler::Compile(const ir::AwaitExpression *expr) const 447{ 448 ETSGen *etsg = GetETSGen(); 449 static constexpr bool IS_UNCHECKED_CAST = false; 450 compiler::RegScope rs(etsg); 451 compiler::VReg argumentReg = etsg->AllocReg(); 452 expr->Argument()->Compile(etsg); 453 etsg->StoreAccumulator(expr, argumentReg); 454 etsg->CallVirtual(expr->Argument(), compiler::Signatures::BUILTIN_PROMISE_AWAIT_RESOLUTION, argumentReg); 455 etsg->CastToReftype(expr->Argument(), expr->TsType(), IS_UNCHECKED_CAST); 456 etsg->SetAccumulatorType(expr->TsType()); 457} 458 459static void CompileNullishCoalescing(compiler::ETSGen *etsg, ir::BinaryExpression const *const node) 460{ 461 auto const compileOperand = [etsg, optype = node->OperationType()](ir::Expression const *expr) { 462 etsg->CompileAndCheck(expr); 463 etsg->ApplyConversion(expr, nullptr); 464 }; 465 466 compileOperand(node->Left()); 467 468 if (node->Left()->TsType()->DefinitelyNotETSNullish()) { 469 // fallthrough 470 } else if (node->Left()->TsType()->DefinitelyETSNullish()) { 471 compileOperand(node->Right()); 472 } else { 473 auto *ifLeftNullish = etsg->AllocLabel(); 474 auto *endLabel = etsg->AllocLabel(); 475 476 etsg->BranchIfNullish(node, ifLeftNullish); 477 478 etsg->AssumeNonNullish(node, node->OperationType()); 479 etsg->ApplyConversion(node->Left(), node->OperationType()); 480 etsg->JumpTo(node, endLabel); 481 482 etsg->SetLabel(node, ifLeftNullish); 483 compileOperand(node->Right()); 484 485 etsg->SetLabel(node, endLabel); 486 } 487 etsg->SetAccumulatorType(node->TsType()); 488} 489 490static void CompileLogical(compiler::ETSGen *etsg, const ir::BinaryExpression *expr) 491{ 492 if (expr->OperatorType() == lexer::TokenType::PUNCTUATOR_NULLISH_COALESCING) { 493 CompileNullishCoalescing(etsg, expr); 494 return; 495 } 496 497 ASSERT(expr->IsLogicalExtended()); 498 auto ttctx = compiler::TargetTypeContext(etsg, expr->OperationType()); 499 compiler::RegScope rs(etsg); 500 auto lhs = etsg->AllocReg(); 501 502 expr->Left()->Compile(etsg); 503 etsg->ApplyConversionAndStoreAccumulator(expr->Left(), lhs, expr->OperationType()); 504 505 auto *endLabel = etsg->AllocLabel(); 506 507 auto returnLeftLabel = etsg->AllocLabel(); 508 if (expr->OperatorType() == lexer::TokenType::PUNCTUATOR_LOGICAL_AND) { 509 etsg->ResolveConditionalResultIfFalse(expr->Left(), returnLeftLabel); 510 etsg->BranchIfFalse(expr, returnLeftLabel); 511 512 expr->Right()->Compile(etsg); 513 etsg->ApplyConversion(expr->Right(), expr->OperationType()); 514 etsg->Branch(expr, endLabel); 515 516 etsg->SetLabel(expr, returnLeftLabel); 517 etsg->LoadAccumulator(expr, lhs); 518 } else { 519 etsg->ResolveConditionalResultIfTrue(expr->Left(), returnLeftLabel); 520 etsg->BranchIfTrue(expr, returnLeftLabel); 521 522 expr->Right()->Compile(etsg); 523 etsg->ApplyConversion(expr->Right(), expr->OperationType()); 524 etsg->Branch(expr, endLabel); 525 526 etsg->SetLabel(expr, returnLeftLabel); 527 etsg->LoadAccumulator(expr, lhs); 528 } 529 530 etsg->SetLabel(expr, endLabel); 531 etsg->SetAccumulatorType(expr->TsType()); 532 etsg->ApplyConversion(expr, expr->OperationType()); 533 534 ASSERT(etsg->Checker()->Relation()->IsIdenticalTo(etsg->GetAccumulatorType(), expr->TsType())); 535} 536 537static void CompileInstanceof(compiler::ETSGen *etsg, const ir::BinaryExpression *expr) 538{ 539 ASSERT(expr->OperatorType() == lexer::TokenType::KEYW_INSTANCEOF); 540 auto ttctx = compiler::TargetTypeContext(etsg, expr->OperationType()); 541 compiler::RegScope rs(etsg); 542 auto lhs = etsg->AllocReg(); 543 544 expr->Left()->Compile(etsg); 545 etsg->ApplyConversionAndStoreAccumulator(expr->Left(), lhs, expr->OperationType()); 546 547 if (expr->Left()->TsType()->IsETSDynamicType() || expr->Right()->TsType()->IsETSDynamicType()) { 548 auto rhs = etsg->AllocReg(); 549 expr->Right()->Compile(etsg); 550 etsg->StoreAccumulator(expr, rhs); 551 etsg->IsInstanceDynamic(expr, lhs, rhs); 552 } else { 553 etsg->IsInstance(expr, lhs, expr->Right()->TsType()); 554 } 555 ASSERT(etsg->Checker()->Relation()->IsIdenticalTo(etsg->GetAccumulatorType(), expr->TsType())); 556} 557 558std::map<lexer::TokenType, std::string_view> &GetBigintSignatures() 559{ 560 static std::map<lexer::TokenType, std::string_view> bigintSignatures = { 561 {lexer::TokenType::PUNCTUATOR_PLUS, compiler::Signatures::BUILTIN_BIGINT_OPERATOR_ADD}, 562 {lexer::TokenType::PUNCTUATOR_MINUS, compiler::Signatures::BUILTIN_BIGINT_OPERATOR_SUBTRACT}, 563 {lexer::TokenType::PUNCTUATOR_MULTIPLY, compiler::Signatures::BUILTIN_BIGINT_OPERATOR_MULTIPLY}, 564 {lexer::TokenType::PUNCTUATOR_DIVIDE, compiler::Signatures::BUILTIN_BIGINT_OPERATOR_DIVIDE}, 565 {lexer::TokenType::PUNCTUATOR_MOD, compiler::Signatures::BUILTIN_BIGINT_OPERATOR_MODULE}, 566 {lexer::TokenType::PUNCTUATOR_BITWISE_OR, compiler::Signatures::BUILTIN_BIGINT_OPERATOR_BITWISE_OR}, 567 {lexer::TokenType::PUNCTUATOR_BITWISE_AND, compiler::Signatures::BUILTIN_BIGINT_OPERATOR_BITWISE_AND}, 568 {lexer::TokenType::PUNCTUATOR_BITWISE_XOR, compiler::Signatures::BUILTIN_BIGINT_OPERATOR_BITWISE_XOR}, 569 {lexer::TokenType::PUNCTUATOR_LEFT_SHIFT, compiler::Signatures::BUILTIN_BIGINT_OPERATOR_LEFT_SHIFT}, 570 {lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT, compiler::Signatures::BUILTIN_BIGINT_OPERATOR_RIGHT_SHIFT}, 571 {lexer::TokenType::PUNCTUATOR_GREATER_THAN, compiler::Signatures::BUILTIN_BIGINT_OPERATOR_GREATER_THAN}, 572 {lexer::TokenType::PUNCTUATOR_LESS_THAN, compiler::Signatures::BUILTIN_BIGINT_OPERATOR_LESS_THAN}, 573 {lexer::TokenType::PUNCTUATOR_GREATER_THAN_EQUAL, 574 compiler::Signatures::BUILTIN_BIGINT_OPERATOR_GREATER_THAN_EQUAL}, 575 {lexer::TokenType::PUNCTUATOR_LESS_THAN_EQUAL, compiler::Signatures::BUILTIN_BIGINT_OPERATOR_LESS_THAN_EQUAL}, 576 }; 577 578 return bigintSignatures; 579} 580 581static bool CompileBigInt(compiler::ETSGen *etsg, const ir::BinaryExpression *expr) 582{ 583 if ((expr->Left()->TsType() == nullptr) || (expr->Right()->TsType() == nullptr)) { 584 return false; 585 } 586 587 if (!expr->Left()->TsType()->IsETSBigIntType()) { 588 return false; 589 } 590 591 if (!expr->Right()->TsType()->IsETSBigIntType()) { 592 return false; 593 } 594 595 auto map = GetBigintSignatures(); 596 if (map.find(expr->OperatorType()) == map.end()) { 597 return false; 598 } 599 600 const checker::Type *operationType = expr->OperationType(); 601 auto ttctx = compiler::TargetTypeContext(etsg, operationType); 602 compiler::RegScope rs(etsg); 603 compiler::VReg lhs = etsg->AllocReg(); 604 expr->Left()->Compile(etsg); 605 etsg->ApplyConversionAndStoreAccumulator(expr->Left(), lhs, operationType); 606 expr->Right()->Compile(etsg); 607 etsg->ApplyConversion(expr->Right(), operationType); 608 compiler::VReg rhs = etsg->AllocReg(); 609 etsg->StoreAccumulator(expr, rhs); 610 611 std::string_view signature = map.at(expr->OperatorType()); 612 switch (expr->OperatorType()) { 613 case lexer::TokenType::PUNCTUATOR_GREATER_THAN: 614 case lexer::TokenType::PUNCTUATOR_LESS_THAN: 615 case lexer::TokenType::PUNCTUATOR_GREATER_THAN_EQUAL: 616 case lexer::TokenType::PUNCTUATOR_LESS_THAN_EQUAL: 617 etsg->CallBigIntBinaryComparison(expr, lhs, rhs, signature); 618 break; 619 default: 620 etsg->CallBigIntBinaryOperator(expr, lhs, rhs, signature); 621 break; 622 } 623 624 ASSERT(etsg->Checker()->Relation()->IsIdenticalTo(etsg->GetAccumulatorType(), expr->TsType())); 625 return true; 626} 627 628void ETSCompiler::Compile(const ir::BinaryExpression *expr) const 629{ 630 ETSGen *etsg = GetETSGen(); 631 632 if (CompileBigInt(etsg, expr)) { 633 return; 634 } 635 636 if (etsg->TryLoadConstantExpression(expr)) { 637 return; 638 } 639 640 if (expr->IsLogical()) { 641 CompileLogical(etsg, expr); 642 return; 643 } 644 if (expr->OperatorType() == lexer::TokenType::KEYW_INSTANCEOF) { 645 CompileInstanceof(etsg, expr); 646 return; 647 } 648 649 auto ttctx = compiler::TargetTypeContext(etsg, expr->OperationType()); 650 compiler::RegScope rs(etsg); 651 compiler::VReg lhs = etsg->AllocReg(); 652 653 if (expr->OperatorType() == lexer::TokenType::PUNCTUATOR_PLUS && expr->OperationType()->IsETSStringType()) { 654 etsg->BuildString(expr); 655 return; 656 } 657 658 expr->CompileOperands(etsg, lhs); 659 if (expr->OperationType()->IsIntType()) { 660 etsg->ApplyCast(expr->Right(), expr->OperationType()); 661 } 662 663 etsg->Binary(expr, expr->OperatorType(), lhs); 664 ASSERT(etsg->Checker()->Relation()->IsIdenticalTo(etsg->GetAccumulatorType(), expr->TsType())); 665} 666 667static void ConvertRestArguments(checker::ETSChecker *const checker, const ir::CallExpression *expr, 668 checker::Signature *signature) 669{ 670 if (signature->RestVar() != nullptr) { 671 std::size_t const argumentCount = expr->Arguments().size(); 672 std::size_t const parameterCount = signature->MinArgCount(); 673 ASSERT(argumentCount >= parameterCount); 674 675 auto &arguments = const_cast<ArenaVector<ir::Expression *> &>(expr->Arguments()); 676 std::size_t i = parameterCount; 677 678 if (i < argumentCount && expr->Arguments()[i]->IsSpreadElement()) { 679 arguments[i] = expr->Arguments()[i]->AsSpreadElement()->Argument(); 680 } else if (i < argumentCount && expr->Arguments()[i]->IsTSAsExpression() && 681 expr->Arguments()[i]->AsTSAsExpression()->Expr()->Type() == ir::AstNodeType::SPREAD_ELEMENT) { 682 arguments[i] = expr->Arguments()[i]->AsTSAsExpression()->Expr()->AsSpreadElement()->Argument(); 683 } else { 684 ArenaVector<ir::Expression *> elements(checker->Allocator()->Adapter()); 685 for (; i < argumentCount; ++i) { 686 elements.emplace_back(expr->Arguments()[i]); 687 } 688 auto *arrayExpression = checker->AllocNode<ir::ArrayExpression>(std::move(elements), checker->Allocator()); 689 arrayExpression->SetParent(const_cast<ir::CallExpression *>(expr)); 690 auto restType = signature->RestVar()->TsType()->AsETSArrayType(); 691 arrayExpression->SetTsType(restType); 692 arrayExpression->SetPreferredType(restType->ElementType()); 693 arguments.erase(expr->Arguments().begin() + parameterCount, expr->Arguments().end()); 694 arguments.emplace_back(arrayExpression); 695 } 696 } 697} 698 699void ConvertArgumentsForFunctionalCall(checker::ETSChecker *const checker, const ir::CallExpression *expr) 700{ 701 std::size_t const argumentCount = expr->Arguments().size(); 702 auto &arguments = const_cast<ArenaVector<ir::Expression *> &>(expr->Arguments()); 703 auto *signature = expr->Signature(); 704 705 for (size_t i = 0; i < argumentCount; i++) { 706 checker::Type *paramType; 707 if (i < signature->Params().size()) { 708 paramType = signature->Params()[i]->TsType(); 709 } else { 710 ASSERT(signature->RestVar() != nullptr); 711 auto *restType = signature->RestVar()->TsType(); 712 ASSERT(restType->IsETSArrayType()); 713 paramType = restType->AsETSArrayType()->ElementType(); 714 } 715 716 auto *arg = arguments[i]; 717 auto *cast = checker->Allocator()->New<ir::TSAsExpression>(arg, nullptr, false); 718 arguments[i]->SetParent(cast); 719 cast->SetParent(const_cast<ir::CallExpression *>(expr)); 720 cast->SetTsType(paramType); 721 722 if (paramType->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)) { 723 cast->AddBoxingUnboxingFlags(checker->GetBoxingFlag(paramType)); 724 } 725 726 arguments[i] = cast; 727 } 728} 729 730void ETSCompiler::Compile(const ir::BlockExpression *expr) const 731{ 732 ETSGen *etsg = GetETSGen(); 733 734 // Nasty hack: current sccope may not be expr's parent scope. 735 // For example. when expr is a field initializer, the current scope will 736 // be a constructor's scope, not the class scope where the field definition resides. 737 auto *oldParent = expr->Scope()->Parent(); 738 expr->Scope()->SetParent(const_cast<varbinder::Scope *>(etsg->Scope())); 739 740 compiler::LocalRegScope lrs(etsg, expr->Scope()); 741 742 etsg->CompileStatements(expr->Statements()); 743 744 expr->Scope()->SetParent(oldParent); 745} 746 747bool ETSCompiler::IsSucceedCompilationProxyMemberExpr(const ir::CallExpression *expr) const 748{ 749 ETSGen *etsg = GetETSGen(); 750 auto *const calleeObject = expr->callee_->AsMemberExpression()->Object(); 751 auto const *const enumInterface = [calleeType = calleeObject->TsType()]() -> checker::ETSEnumType const * { 752 if (calleeType == nullptr) { 753 return nullptr; 754 } 755 if (calleeType->IsETSIntEnumType()) { 756 return calleeType->AsETSIntEnumType(); 757 } 758 if (calleeType->IsETSStringEnumType()) { 759 return calleeType->AsETSStringEnumType(); 760 } 761 return nullptr; 762 }(); 763 764 if (enumInterface != nullptr) { 765 ArenaVector<ir::Expression *> arguments(etsg->Allocator()->Adapter()); 766 767 checker::Signature *const signature = [expr, calleeObject, enumInterface, &arguments]() { 768 const auto &memberProxyMethodName = expr->Signature()->InternalName(); 769 770 if (memberProxyMethodName == checker::ETSIntEnumType::TO_STRING_METHOD_NAME) { 771 arguments.push_back(calleeObject); 772 return enumInterface->ToStringMethod().globalSignature; 773 } 774 if (memberProxyMethodName == checker::ETSIntEnumType::VALUE_OF_METHOD_NAME) { 775 arguments.push_back(calleeObject); 776 return enumInterface->ValueOfMethod().globalSignature; 777 } 778 if (memberProxyMethodName == checker::ETSIntEnumType::GET_NAME_METHOD_NAME) { 779 arguments.push_back(calleeObject); 780 return enumInterface->GetNameMethod().globalSignature; 781 } 782 if (memberProxyMethodName == checker::ETSIntEnumType::VALUES_METHOD_NAME) { 783 return enumInterface->ValuesMethod().globalSignature; 784 } 785 if (memberProxyMethodName == checker::ETSIntEnumType::GET_VALUE_OF_METHOD_NAME) { 786 arguments.push_back(expr->Arguments().front()); 787 return enumInterface->GetValueOfMethod().globalSignature; 788 } 789 UNREACHABLE(); 790 }(); 791 792 ASSERT(signature->ReturnType() == expr->Signature()->ReturnType()); 793 etsg->CallExact(expr, signature, arguments); 794 etsg->SetAccumulatorType(expr->TsType()); 795 } 796 797 return enumInterface != nullptr; 798} 799 800void ETSCompiler::CompileDynamic(const ir::CallExpression *expr, compiler::VReg &calleeReg) const 801{ 802 ETSGen *etsg = GetETSGen(); 803 auto callInfo = checker::DynamicCall::ResolveCall(etsg->VarBinder(), expr->Callee()); 804 if (callInfo.obj->IsETSImportDeclaration()) { 805 etsg->LoadAccumulatorDynamicModule(expr, callInfo.obj->AsETSImportDeclaration()); 806 } else { 807 callInfo.obj->Compile(etsg); 808 } 809 etsg->StoreAccumulator(expr, calleeReg); 810 811 if (!callInfo.name.empty()) { 812 auto [qnameStart, qnameLen] = LoadDynamicName(etsg, expr, callInfo.name, false); 813 etsg->CallDynamic(ETSGen::CallDynamicData {expr, calleeReg, qnameStart}, qnameLen, expr->Signature(), 814 expr->Arguments()); 815 } else { 816 compiler::VReg dynParam2 = etsg->AllocReg(); 817 818 auto lang = expr->Callee()->TsType()->IsETSDynamicFunctionType() 819 ? expr->Callee()->TsType()->AsETSDynamicFunctionType()->Language() 820 : expr->Callee()->TsType()->AsETSDynamicType()->Language(); 821 etsg->LoadUndefinedDynamic(expr, lang); 822 etsg->StoreAccumulator(expr, dynParam2); 823 etsg->CallDynamic(ETSGen::CallDynamicData {expr, calleeReg, dynParam2}, expr->Signature(), expr->Arguments()); 824 } 825 etsg->SetAccumulatorType(expr->Signature()->ReturnType()); 826 827 if (etsg->GetAccumulatorType() != expr->TsType()) { 828 etsg->ApplyConversion(expr, expr->TsType()); 829 } 830} 831 832void ETSCompiler::EmitCall(const ir::CallExpression *expr, compiler::VReg &calleeReg, 833 checker::Signature *signature) const 834{ 835 ETSGen *etsg = GetETSGen(); 836 if (expr->Callee()->GetBoxingUnboxingFlags() != ir::BoxingUnboxingFlags::NONE) { 837 etsg->ApplyConversionAndStoreAccumulator(expr->Callee(), calleeReg, nullptr); 838 } 839 if (signature->HasSignatureFlag(checker::SignatureFlags::STATIC)) { 840 etsg->CallExact(expr, expr->Signature(), expr->Arguments()); 841 } else if ((expr->Callee()->IsMemberExpression() && 842 expr->Callee()->AsMemberExpression()->Object()->IsSuperExpression())) { 843 etsg->CallExact(expr, signature, calleeReg, expr->Arguments()); 844 } else { 845 etsg->CallVirtual(expr, signature, calleeReg, expr->Arguments()); 846 } 847 848 etsg->GuardUncheckedType(expr, expr->UncheckedType(), expr->TsType()); 849} 850 851static checker::Signature *ConvertArgumentsForFunctionReference(ETSGen *etsg, const ir::CallExpression *expr) 852{ 853 checker::Signature *origSignature = expr->Signature(); 854 855 auto *funcType = 856 origSignature->Owner() 857 ->GetOwnProperty<checker::PropertyType::INSTANCE_METHOD>(checker::FUNCTIONAL_INTERFACE_INVOKE_METHOD_NAME) 858 ->TsType() 859 ->AsETSFunctionType(); 860 ASSERT(funcType->CallSignatures().size() == 1); 861 checker::Signature *signature = funcType->CallSignatures()[0]; 862 863 if (signature->ReturnType()->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)) { 864 expr->AddBoxingUnboxingFlags(const_cast<checker::ETSChecker *>(etsg->Checker()->AsETSChecker()) 865 ->GetUnboxingFlag(signature->ReturnType())); 866 } 867 868 ConvertArgumentsForFunctionalCall(const_cast<checker::ETSChecker *>(etsg->Checker()->AsETSChecker()), expr); 869 870 return signature; 871} 872 873void ETSCompiler::Compile(const ir::CallExpression *expr) const 874{ 875 ETSGen *etsg = GetETSGen(); 876 compiler::RegScope rs(etsg); 877 compiler::VReg calleeReg = etsg->AllocReg(); 878 879 checker::Signature *signature = expr->Signature(); 880 881 if (signature->HasSignatureFlag(checker::SignatureFlags::PROXY) && expr->Callee()->IsMemberExpression()) { 882 if (IsSucceedCompilationProxyMemberExpr(expr)) { 883 return; 884 } 885 } 886 887 bool isStatic = signature->HasSignatureFlag(checker::SignatureFlags::STATIC); 888 bool isReference = false; // expr->Signature()->HasSignatureFlag(checker::SignatureFlags::TYPE); 889 bool isDynamic = expr->Callee()->TsType()->HasTypeFlag(checker::TypeFlag::ETS_DYNAMIC_FLAG); 890 891 if (isReference) { 892 signature = ConvertArgumentsForFunctionReference(etsg, expr); 893 } 894 895 ConvertRestArguments(const_cast<checker::ETSChecker *>(etsg->Checker()->AsETSChecker()), expr, signature); 896 897 if (isDynamic) { 898 CompileDynamic(expr, calleeReg); 899 } else if (!isReference && expr->Callee()->IsIdentifier()) { 900 if (!isStatic) { 901 etsg->LoadThis(expr); 902 etsg->StoreAccumulator(expr, calleeReg); 903 } 904 EmitCall(expr, calleeReg, signature); 905 } else if (!isReference && expr->Callee()->IsMemberExpression()) { 906 if (!isStatic) { 907 MaybeCastUnionTypeToFunctionType(etsg, expr, signature); 908 etsg->StoreAccumulator(expr, calleeReg); 909 } 910 EmitCall(expr, calleeReg, signature); 911 } else if (expr->Callee()->IsSuperExpression() || expr->Callee()->IsThisExpression()) { 912 ASSERT(!isReference && expr->IsETSConstructorCall()); 913 expr->Callee()->Compile(etsg); // ctor is not a value! 914 etsg->StoreAccumulator(expr, calleeReg); 915 EmitCall(expr, calleeReg, signature); 916 } else { 917 ASSERT(isReference); 918 etsg->CompileAndCheck(expr->Callee()); 919 etsg->StoreAccumulator(expr, calleeReg); 920 EmitCall(expr, calleeReg, signature); 921 } 922 923 if (expr->HasBoxingUnboxingFlags(ir::BoxingUnboxingFlags::UNBOXING_FLAG | ir::BoxingUnboxingFlags::BOXING_FLAG)) { 924 etsg->ApplyConversion(expr, expr->TsType()); 925 } else { 926 etsg->SetAccumulatorType(expr->TsType()); 927 } 928} 929 930void ETSCompiler::Compile(const ir::ConditionalExpression *expr) const 931{ 932 ETSGen *etsg = GetETSGen(); 933 934 auto *falseLabel = etsg->AllocLabel(); 935 auto *endLabel = etsg->AllocLabel(); 936 937 compiler::Condition::Compile(etsg, expr->Test(), falseLabel); 938 939 auto ttctx = compiler::TargetTypeContext(etsg, expr->TsType()); 940 941 expr->Consequent()->Compile(etsg); 942 etsg->ApplyConversion(expr->Consequent()); 943 etsg->Branch(expr, endLabel); 944 etsg->SetLabel(expr, falseLabel); 945 expr->Alternate()->Compile(etsg); 946 etsg->ApplyConversion(expr->Alternate()); 947 etsg->SetLabel(expr, endLabel); 948 etsg->SetAccumulatorType(expr->TsType()); 949} 950 951void ETSCompiler::Compile(const ir::Identifier *expr) const 952{ 953 ETSGen *etsg = GetETSGen(); 954 955 auto const *const smartType = expr->TsType(); 956 auto ttctx = compiler::TargetTypeContext(etsg, smartType); 957 958 ASSERT(expr->Variable() != nullptr); 959 if (!expr->Variable()->HasFlag(varbinder::VariableFlags::TYPE_ALIAS)) { 960 etsg->LoadVar(expr, expr->Variable()); 961 } 962 963 if (smartType->IsETSReferenceType()) { 964 // In case when smart cast type of identifier differs from initial variable type perform cast if required 965 if (!etsg->Checker()->AsETSChecker()->Relation()->IsSupertypeOf(smartType, etsg->GetAccumulatorType())) { 966 etsg->CastToReftype(expr, smartType, false); 967 } 968 } 969 970 etsg->SetAccumulatorType(smartType); 971} 972 973bool ETSCompiler::CompileComputed(compiler::ETSGen *etsg, const ir::MemberExpression *expr) 974{ 975 if (!expr->IsComputed()) { 976 return false; 977 } 978 auto *const objectType = expr->Object()->TsType(); 979 980 auto ottctx = compiler::TargetTypeContext(etsg, expr->Object()->TsType()); 981 etsg->CompileAndCheck(expr->Object()); 982 983 compiler::VReg objReg = etsg->AllocReg(); 984 etsg->StoreAccumulator(expr, objReg); 985 986 auto pttctx = compiler::TargetTypeContext(etsg, expr->Property()->TsType()); 987 988 etsg->CompileAndCheck(expr->Property()); 989 etsg->ApplyConversion(expr->Property(), expr->Property()->TsType()); 990 991 auto ttctx = compiler::TargetTypeContext(etsg, expr->TsType()); 992 993 if (objectType->IsETSDynamicType()) { 994 etsg->LoadElementDynamic(expr, objReg); 995 } else { 996 etsg->LoadArrayElement(expr, objReg); 997 } 998 999 etsg->GuardUncheckedType(expr, expr->UncheckedType(), expr->TsType()); 1000 etsg->ApplyConversion(expr); 1001 1002 ASSERT(etsg->Checker()->Relation()->IsIdenticalTo(etsg->GetAccumulatorType(), expr->TsType())); 1003 return true; 1004} 1005 1006void ETSCompiler::Compile(const ir::MemberExpression *expr) const 1007{ 1008 ETSGen *etsg = GetETSGen(); 1009 1010 compiler::RegScope rs(etsg); 1011 1012 if (CompileComputed(etsg, expr)) { 1013 return; 1014 } 1015 1016 if (HandleArrayTypeLengthProperty(expr, etsg)) { 1017 return; 1018 } 1019 1020 if (HandleEnumTypes(expr, etsg)) { 1021 return; 1022 } 1023 1024 if (HandleStaticProperties(expr, etsg)) { 1025 return; 1026 } 1027 1028 auto *const objectType = etsg->Checker()->GetApparentType(expr->Object()->TsType()); 1029 auto &propName = expr->Property()->AsIdentifier()->Name(); 1030 1031 auto ottctx = compiler::TargetTypeContext(etsg, expr->Object()->TsType()); 1032 etsg->CompileAndCheck(expr->Object()); 1033 1034 etsg->ApplyConversion(expr->Object()); 1035 compiler::VReg objReg = etsg->AllocReg(); 1036 etsg->StoreAccumulator(expr, objReg); 1037 1038 auto ttctx = compiler::TargetTypeContext(etsg, expr->TsType()); 1039 ASSERT(expr->PropVar()->TsType() != nullptr); 1040 const checker::Type *const variableType = expr->PropVar()->TsType(); 1041 if (variableType->HasTypeFlag(checker::TypeFlag::GETTER_SETTER)) { 1042 if (expr->Object()->IsSuperExpression()) { 1043 etsg->CallExact(expr, variableType->AsETSFunctionType()->FindGetter()->InternalName(), objReg); 1044 } else { 1045 etsg->CallVirtual(expr, variableType->AsETSFunctionType()->FindGetter(), objReg); 1046 } 1047 } else if (objectType->IsETSDynamicType()) { 1048 etsg->LoadPropertyDynamic(expr, expr->TsType(), objReg, propName); 1049 } else if (objectType->IsETSUnionType()) { 1050 etsg->LoadUnionProperty(expr, expr->TsType(), objReg, propName); 1051 } else { 1052 const auto fullName = etsg->FormClassPropReference(objectType->AsETSObjectType(), propName); 1053 etsg->LoadProperty(expr, variableType, objReg, fullName); 1054 } 1055 etsg->GuardUncheckedType(expr, expr->UncheckedType(), expr->TsType()); 1056 1057 ASSERT(etsg->Checker()->Relation()->IsIdenticalTo(etsg->GetAccumulatorType(), expr->TsType())); 1058} 1059 1060bool ETSCompiler::HandleArrayTypeLengthProperty(const ir::MemberExpression *expr, ETSGen *etsg) const 1061{ 1062 auto *const objectType = etsg->Checker()->GetApparentType(expr->Object()->TsType()); 1063 auto &propName = expr->Property()->AsIdentifier()->Name(); 1064 if (objectType->IsETSArrayType() && propName.Is("length")) { 1065 auto ottctx = compiler::TargetTypeContext(etsg, objectType); 1066 etsg->CompileAndCheck(expr->Object()); 1067 1068 compiler::VReg objReg = etsg->AllocReg(); 1069 etsg->StoreAccumulator(expr, objReg); 1070 1071 auto ttctx = compiler::TargetTypeContext(etsg, expr->TsType()); 1072 etsg->LoadArrayLength(expr, objReg); 1073 etsg->ApplyConversion(expr, expr->TsType()); 1074 return true; 1075 } 1076 return false; 1077} 1078 1079bool ETSCompiler::HandleEnumTypes(const ir::MemberExpression *expr, ETSGen *etsg) const 1080{ 1081 auto *const exprType = etsg->Checker()->GetApparentType(expr->TsType()); 1082 if (exprType->IsETSEnumType() && exprType->AsETSEnumType()->IsLiteralType()) { 1083 auto ttctx = compiler::TargetTypeContext(etsg, expr->TsType()); 1084 etsg->LoadAccumulatorInt(expr, exprType->AsETSEnumType()->GetOrdinal()); 1085 return true; 1086 } 1087 return false; 1088} 1089 1090bool ETSCompiler::HandleStaticProperties(const ir::MemberExpression *expr, ETSGen *etsg) const 1091{ 1092 auto &propName = expr->Property()->AsIdentifier()->Name(); 1093 auto const *const variable = expr->PropVar(); 1094 if (etsg->Checker()->IsVariableStatic(variable)) { 1095 auto ttctx = compiler::TargetTypeContext(etsg, expr->TsType()); 1096 1097 if (expr->PropVar()->TsType()->HasTypeFlag(checker::TypeFlag::GETTER_SETTER)) { 1098 checker::Signature *sig = variable->TsType()->AsETSFunctionType()->FindGetter(); 1099 etsg->CallExact(expr, sig->InternalName()); 1100 etsg->SetAccumulatorType(expr->TsType()); 1101 return true; 1102 } 1103 1104 if (expr->Object()->TsType()->IsETSEnumType() && expr->Property()->TsType()->IsETSEnumType() && 1105 expr->Property()->TsType()->AsETSEnumType()->IsLiteralType()) { 1106 etsg->LoadAccumulatorInt(expr, expr->Property()->TsType()->AsETSEnumType()->GetOrdinal()); 1107 expr->Object()->AddBoxingUnboxingFlags(ir::BoxingUnboxingFlags::BOX_TO_ENUM); 1108 etsg->ApplyBoxingConversion(expr->Object()); 1109 return true; 1110 } 1111 1112 util::StringView fullName = etsg->FormClassPropReference(expr->Object()->TsType()->AsETSObjectType(), propName); 1113 etsg->LoadStaticProperty(expr, expr->TsType(), fullName); 1114 1115 ASSERT(etsg->Checker()->Relation()->IsIdenticalTo(etsg->GetAccumulatorType(), expr->TsType())); 1116 return true; 1117 } 1118 return false; 1119} 1120 1121void ETSCompiler::Compile(const ir::ObjectExpression *expr) const 1122{ 1123 ETSGen *etsg = GetETSGen(); 1124 compiler::RegScope rs {etsg}; 1125 compiler::VReg objReg = etsg->AllocReg(); 1126 1127 // NOTE: object expressions of dynamic type are not handled in objectLiteralLowering phase 1128 ASSERT(expr->TsType()->IsETSDynamicType()); 1129 1130 auto *signatureInfo = etsg->Allocator()->New<checker::SignatureInfo>(etsg->Allocator()); 1131 auto *createObjSig = etsg->Allocator()->New<checker::Signature>( 1132 signatureInfo, nullptr, compiler::Signatures::BUILTIN_JSRUNTIME_CREATE_OBJECT); 1133 compiler::VReg dummyReg = compiler::VReg::RegStart(); 1134 etsg->CallDynamic(ETSGen::CallDynamicData {expr, dummyReg, dummyReg}, createObjSig, 1135 ArenaVector<ir::Expression *>(etsg->Allocator()->Adapter())); 1136 1137 etsg->SetAccumulatorType(expr->TsType()); 1138 etsg->StoreAccumulator(expr, objReg); 1139 1140 for (ir::Expression *propExpr : expr->Properties()) { 1141 ASSERT(propExpr->IsProperty()); 1142 ir::Property *prop = propExpr->AsProperty(); 1143 ir::Expression *key = prop->Key(); 1144 ir::Expression *value = prop->Value(); 1145 1146 util::StringView pname; 1147 if (key->IsStringLiteral()) { 1148 pname = key->AsStringLiteral()->Str(); 1149 } else if (key->IsIdentifier()) { 1150 pname = key->AsIdentifier()->Name(); 1151 } else { 1152 UNREACHABLE(); 1153 } 1154 1155 value->Compile(etsg); 1156 etsg->ApplyConversion(value, key->TsType()); 1157 if (expr->TsType()->IsETSDynamicType()) { 1158 etsg->StorePropertyDynamic(expr, value->TsType(), objReg, pname); 1159 } else { 1160 etsg->StoreProperty(expr, key->TsType(), objReg, pname); 1161 } 1162 } 1163 1164 etsg->LoadAccumulator(expr, objReg); 1165 ASSERT(etsg->Checker()->Relation()->IsIdenticalTo(etsg->GetAccumulatorType(), expr->TsType())); 1166} 1167 1168void ETSCompiler::Compile(const ir::SequenceExpression *expr) const 1169{ 1170 ETSGen *etsg = GetETSGen(); 1171 for (const auto *it : expr->Sequence()) { 1172 it->Compile(etsg); 1173 } 1174} 1175 1176void ETSCompiler::Compile(const ir::SuperExpression *expr) const 1177{ 1178 ETSGen *etsg = GetETSGen(); 1179 etsg->LoadThis(expr); 1180 etsg->SetAccumulatorType(etsg->GetAccumulatorType()->AsETSObjectType()->SuperType()); 1181 ASSERT(etsg->Checker()->Relation()->IsIdenticalTo(etsg->GetAccumulatorType(), expr->TsType())); 1182} 1183 1184void ETSCompiler::Compile(const ir::TemplateLiteral *expr) const 1185{ 1186 ETSGen *etsg = GetETSGen(); 1187 etsg->BuildTemplateString(expr); 1188 ASSERT(etsg->Checker()->Relation()->IsIdenticalTo(etsg->GetAccumulatorType(), expr->TsType())); 1189} 1190 1191void ETSCompiler::Compile(const ir::ThisExpression *expr) const 1192{ 1193 ETSGen *etsg = GetETSGen(); 1194 etsg->LoadThis(expr); 1195 ASSERT(etsg->Checker()->Relation()->IsIdenticalTo(etsg->GetAccumulatorType(), expr->TsType())); 1196} 1197 1198void ETSCompiler::Compile([[maybe_unused]] const ir::TypeofExpression *expr) const 1199{ 1200 ETSGen *etsg = GetETSGen(); 1201 ir::Expression *arg = expr->Argument(); 1202 arg->Compile(etsg); 1203 if (expr->TsType()->IsETSStringType() && expr->TsType()->HasTypeFlag(checker::TypeFlag::CONSTANT)) { 1204 etsg->LoadAccumulatorString(expr, expr->TsType()->AsETSStringType()->GetValue()); 1205 return; 1206 } 1207 auto argReg = etsg->AllocReg(); 1208 etsg->StoreAccumulator(expr, argReg); 1209 etsg->CallExact(expr, Signatures::BUILTIN_RUNTIME_TYPEOF, argReg); 1210 etsg->SetAccumulatorType(expr->TsType()); 1211} 1212 1213void ETSCompiler::Compile(const ir::UnaryExpression *expr) const 1214{ 1215 ETSGen *etsg = GetETSGen(); 1216 auto ttctx = compiler::TargetTypeContext(etsg, expr->TsType()); 1217 1218 if (!etsg->TryLoadConstantExpression(expr->Argument())) { 1219 expr->Argument()->Compile(etsg); 1220 } 1221 1222 etsg->ApplyConversion(expr->Argument(), nullptr); 1223 etsg->ApplyCast(expr->Argument(), expr->TsType()); 1224 1225 etsg->Unary(expr, expr->OperatorType()); 1226 1227 ASSERT(etsg->Checker()->Relation()->IsIdenticalTo(etsg->GetAccumulatorType(), expr->TsType())); 1228} 1229 1230void ETSCompiler::Compile([[maybe_unused]] const ir::BigIntLiteral *expr) const 1231{ 1232 ETSGen *etsg = GetETSGen(); 1233 compiler::TargetTypeContext ttctx = compiler::TargetTypeContext(etsg, expr->TsType()); 1234 compiler::RegScope rs {etsg}; 1235 etsg->LoadAccumulatorBigInt(expr, expr->Str()); 1236 const compiler::VReg value = etsg->AllocReg(); 1237 etsg->StoreAccumulator(expr, value); 1238 etsg->CreateBigIntObject(expr, value); 1239 ASSERT(etsg->Checker()->Relation()->IsIdenticalTo(etsg->GetAccumulatorType(), expr->TsType())); 1240} 1241 1242void ETSCompiler::Compile(const ir::BooleanLiteral *expr) const 1243{ 1244 ETSGen *etsg = GetETSGen(); 1245 etsg->LoadAccumulatorBoolean(expr, expr->Value()); 1246 ASSERT(etsg->Checker()->Relation()->IsIdenticalTo(etsg->GetAccumulatorType(), expr->TsType())); 1247} 1248 1249void ETSCompiler::Compile(const ir::CharLiteral *expr) const 1250{ 1251 ETSGen *etsg = GetETSGen(); 1252 etsg->LoadAccumulatorChar(expr, expr->Char()); 1253 ASSERT(etsg->Checker()->Relation()->IsIdenticalTo(etsg->GetAccumulatorType(), expr->TsType())); 1254} 1255 1256void ETSCompiler::Compile(const ir::NullLiteral *expr) const 1257{ 1258 ETSGen *etsg = GetETSGen(); 1259 etsg->LoadAccumulatorNull(expr, expr->TsType()); 1260 ASSERT(etsg->Checker()->Relation()->IsIdenticalTo(etsg->GetAccumulatorType(), expr->TsType())); 1261} 1262 1263void ETSCompiler::Compile(const ir::NumberLiteral *expr) const 1264{ 1265 ETSGen *etsg = GetETSGen(); 1266 auto ttctx = compiler::TargetTypeContext(etsg, expr->TsType()); 1267 1268 if (expr->Number().IsInt()) { 1269 if (util::Helpers::IsTargetFitInSourceRange<checker::ByteType::UType, checker::IntType::UType>( 1270 expr->Number().GetInt())) { 1271 etsg->LoadAccumulatorByte(expr, static_cast<int8_t>(expr->Number().GetInt())); 1272 } else if (util::Helpers::IsTargetFitInSourceRange<checker::ShortType::UType, checker::IntType::UType>( 1273 expr->Number().GetInt())) { 1274 etsg->LoadAccumulatorShort(expr, static_cast<int16_t>(expr->Number().GetInt())); 1275 } else { 1276 etsg->LoadAccumulatorInt(expr, static_cast<int32_t>(expr->Number().GetInt())); 1277 } 1278 } else if (expr->Number().IsLong()) { 1279 etsg->LoadAccumulatorWideInt(expr, expr->Number().GetLong()); 1280 } else if (expr->Number().IsFloat()) { 1281 etsg->LoadAccumulatorFloat(expr, expr->Number().GetFloat()); 1282 } else { 1283 etsg->LoadAccumulatorDouble(expr, expr->Number().GetDouble()); 1284 } 1285 1286 ASSERT(etsg->Checker()->Relation()->IsIdenticalTo(etsg->GetAccumulatorType(), expr->TsType())); 1287} 1288 1289void ETSCompiler::Compile(const ir::StringLiteral *expr) const 1290{ 1291 ETSGen *etsg = GetETSGen(); 1292 etsg->LoadAccumulatorString(expr, expr->Str()); 1293 etsg->SetAccumulatorType(expr->TsType()); 1294} 1295 1296static void ThrowError(compiler::ETSGen *const etsg, const ir::AssertStatement *st) 1297{ 1298 const compiler::RegScope rs(etsg); 1299 1300 if (st->Second() != nullptr) { 1301 st->Second()->Compile(etsg); 1302 } else { 1303 etsg->LoadAccumulatorString(st, "Assertion failed."); 1304 } 1305 1306 const auto message = etsg->AllocReg(); 1307 etsg->StoreAccumulator(st, message); 1308 1309 const auto assertionError = etsg->AllocReg(); 1310 etsg->NewObject(st, compiler::Signatures::BUILTIN_ASSERTION_ERROR, assertionError); 1311 etsg->CallExact(st, compiler::Signatures::BUILTIN_ASSERTION_ERROR_CTOR, assertionError, message); 1312 etsg->EmitThrow(st, assertionError); 1313} 1314 1315void ETSCompiler::Compile(const ir::AssertStatement *st) const 1316{ 1317 ETSGen *etsg = GetETSGen(); 1318 auto res = compiler::Condition::CheckConstantExpr(etsg, st->Test()); 1319 if (res == compiler::Condition::Result::CONST_TRUE) { 1320 return; 1321 } 1322 1323 if (res == compiler::Condition::Result::CONST_FALSE) { 1324 ThrowError(etsg, st); 1325 return; 1326 } 1327 1328 compiler::Label *trueLabel = etsg->AllocLabel(); 1329 compiler::Label *falseLabel = etsg->AllocLabel(); 1330 1331 compiler::Condition::Compile(etsg, st->Test(), falseLabel); 1332 etsg->JumpTo(st, trueLabel); 1333 1334 etsg->SetLabel(st, falseLabel); 1335 ThrowError(etsg, st); 1336 1337 etsg->SetLabel(st, trueLabel); 1338} 1339 1340void ETSCompiler::Compile(const ir::BlockStatement *st) const 1341{ 1342 ETSGen *etsg = GetETSGen(); 1343 compiler::LocalRegScope lrs(etsg, st->Scope()); 1344 1345 etsg->CompileStatements(st->Statements()); 1346} 1347 1348template <typename CodeGen> 1349static void CompileImpl(const ir::BreakStatement *self, [[maybe_unused]] CodeGen *cg) 1350{ 1351 compiler::Label *target = cg->ControlFlowChangeBreak(self->Ident()); 1352 cg->Branch(self, target); 1353} 1354 1355void ETSCompiler::Compile(const ir::BreakStatement *st) const 1356{ 1357 ETSGen *etsg = GetETSGen(); 1358 if (etsg->ExtendWithFinalizer(st->Parent(), st)) { 1359 return; 1360 } 1361 CompileImpl(st, etsg); 1362} 1363 1364void ETSCompiler::Compile([[maybe_unused]] const ir::ClassDeclaration *st) const {} 1365 1366static void CompileImpl(const ir::ContinueStatement *self, ETSGen *etsg) 1367{ 1368 compiler::Label *target = etsg->ControlFlowChangeContinue(self->Ident()); 1369 etsg->Branch(self, target); 1370} 1371 1372void ETSCompiler::Compile(const ir::ContinueStatement *st) const 1373{ 1374 ETSGen *etsg = GetETSGen(); 1375 if (etsg->ExtendWithFinalizer(st->Parent(), st)) { 1376 return; 1377 } 1378 CompileImpl(st, etsg); 1379} 1380 1381void CompileImpl(const ir::DoWhileStatement *self, ETSGen *etsg) 1382{ 1383 auto *startLabel = etsg->AllocLabel(); 1384 compiler::LabelTarget labelTarget(etsg); 1385 1386 etsg->SetLabel(self, startLabel); 1387 1388 { 1389 compiler::LocalRegScope regScope(etsg, self->Scope()); 1390 compiler::LabelContext labelCtx(etsg, labelTarget); 1391 self->Body()->Compile(etsg); 1392 } 1393 1394 etsg->SetLabel(self, labelTarget.ContinueTarget()); 1395 compiler::Condition::Compile(etsg, self->Test(), labelTarget.BreakTarget()); 1396 1397 etsg->Branch(self, startLabel); 1398 etsg->SetLabel(self, labelTarget.BreakTarget()); 1399} 1400 1401void ETSCompiler::Compile(const ir::DoWhileStatement *st) const 1402{ 1403 ETSGen *etsg = GetETSGen(); 1404 CompileImpl(st, etsg); 1405} 1406 1407void ETSCompiler::Compile([[maybe_unused]] const ir::EmptyStatement *st) const {} 1408 1409void ETSCompiler::Compile(const ir::ExpressionStatement *st) const 1410{ 1411 ETSGen *etsg = GetETSGen(); 1412 st->GetExpression()->Compile(etsg); 1413} 1414 1415void ETSCompiler::Compile(const ir::ForOfStatement *st) const 1416{ 1417 ETSGen *etsg = GetETSGen(); 1418 compiler::LocalRegScope declRegScope(etsg, st->Scope()->DeclScope()->InitScope()); 1419 1420 checker::Type const *const exprType = st->Right()->TsType(); 1421 ASSERT(exprType->IsETSArrayType() || exprType->IsETSStringType() || exprType->IsETSUnionType()); 1422 1423 st->Right()->Compile(etsg); 1424 compiler::VReg objReg = etsg->AllocReg(); 1425 etsg->StoreAccumulator(st, objReg); 1426 1427 GetSizeInForOf(etsg, exprType, st, objReg); 1428 1429 compiler::VReg sizeReg = etsg->AllocReg(); 1430 etsg->StoreAccumulator(st, sizeReg); 1431 1432 compiler::LabelTarget labelTarget(etsg); 1433 auto labelCtx = compiler::LabelContext(etsg, labelTarget); 1434 1435 etsg->BranchIfFalse(st, labelTarget.BreakTarget()); 1436 1437 compiler::VReg countReg = etsg->AllocReg(); 1438 etsg->MoveImmediateToRegister(st, countReg, checker::TypeFlag::INT, static_cast<std::int32_t>(0)); 1439 etsg->LoadAccumulatorInt(st, static_cast<std::int32_t>(0)); 1440 1441 auto *const startLabel = etsg->AllocLabel(); 1442 etsg->SetLabel(st, startLabel); 1443 1444 auto lref = compiler::ETSLReference::Create(etsg, st->Left(), false); 1445 1446 if (exprType->IsETSArrayType()) { 1447 etsg->LoadArrayElement(st, objReg); 1448 } else if (exprType->IsETSUnionType()) { 1449 HandleUnionTypeInForOf(etsg, exprType, st, objReg, &countReg); 1450 } else { 1451 etsg->LoadStringChar(st, objReg, countReg); 1452 } 1453 1454 lref.SetValue(); 1455 st->Body()->Compile(etsg); 1456 1457 etsg->SetLabel(st, labelTarget.ContinueTarget()); 1458 1459 etsg->IncrementImmediateRegister(st, countReg, checker::TypeFlag::INT, static_cast<std::int32_t>(1)); 1460 etsg->LoadAccumulator(st, countReg); 1461 1462 etsg->JumpCompareRegister<compiler::Jlt>(st, sizeReg, startLabel); 1463 etsg->SetLabel(st, labelTarget.BreakTarget()); 1464} 1465 1466void ETSCompiler::Compile(const ir::ForUpdateStatement *st) const 1467{ 1468 ETSGen *etsg = GetETSGen(); 1469 compiler::LocalRegScope declRegScope(etsg, st->Scope()->DeclScope()->InitScope()); 1470 1471 if (st->Init() != nullptr) { 1472 ASSERT(st->Init()->IsVariableDeclaration() || st->Init()->IsExpression()); 1473 st->Init()->Compile(etsg); 1474 } 1475 1476 auto *startLabel = etsg->AllocLabel(); 1477 compiler::LabelTarget labelTarget(etsg); 1478 auto labelCtx = compiler::LabelContext(etsg, labelTarget); 1479 etsg->SetLabel(st, startLabel); 1480 1481 { 1482 compiler::LocalRegScope regScope(etsg, st->Scope()); 1483 1484 if (st->Test() != nullptr) { 1485 compiler::Condition::Compile(etsg, st->Test(), labelTarget.BreakTarget()); 1486 } 1487 1488 st->Body()->Compile(etsg); 1489 etsg->SetLabel(st, labelTarget.ContinueTarget()); 1490 } 1491 1492 if (st->Update() != nullptr) { 1493 st->Update()->Compile(etsg); 1494 } 1495 1496 etsg->Branch(st, startLabel); 1497 etsg->SetLabel(st, labelTarget.BreakTarget()); 1498} 1499 1500void ETSCompiler::Compile(const ir::IfStatement *st) const 1501{ 1502 ETSGen *etsg = GetETSGen(); 1503 auto res = compiler::Condition::CheckConstantExpr(etsg, st->Test()); 1504 if (res == compiler::Condition::Result::CONST_TRUE) { 1505 st->Test()->Compile(etsg); 1506 st->Consequent()->Compile(etsg); 1507 return; 1508 } 1509 1510 if (res == compiler::Condition::Result::CONST_FALSE) { 1511 st->Test()->Compile(etsg); 1512 if (st->Alternate() != nullptr) { 1513 st->Alternate()->Compile(etsg); 1514 } 1515 return; 1516 } 1517 1518 auto *consequentEnd = etsg->AllocLabel(); 1519 compiler::Label *statementEnd = consequentEnd; 1520 1521 compiler::Condition::Compile(etsg, st->Test(), consequentEnd); 1522 1523 st->Consequent()->Compile(etsg); 1524 1525 if (st->Alternate() != nullptr) { 1526 statementEnd = etsg->AllocLabel(); 1527 etsg->Branch(etsg->Insns().back()->Node(), statementEnd); 1528 1529 etsg->SetLabel(st, consequentEnd); 1530 st->Alternate()->Compile(etsg); 1531 } 1532 1533 etsg->SetLabel(st, statementEnd); 1534} 1535 1536void CompileImpl(const ir::LabelledStatement *self, ETSGen *cg) 1537{ 1538 compiler::LabelContext labelCtx(cg, self); 1539 self->Body()->Compile(cg); 1540} 1541 1542void ETSCompiler::Compile(const ir::LabelledStatement *st) const 1543{ 1544 ETSGen *etsg = GetETSGen(); 1545 CompileImpl(st, etsg); 1546} 1547 1548void ETSCompiler::Compile(const ir::ReturnStatement *st) const 1549{ 1550 ETSGen *etsg = GetETSGen(); 1551 if (st->Argument() == nullptr) { 1552 if (etsg->ExtendWithFinalizer(st->Parent(), st)) { 1553 return; 1554 } 1555 1556 if (etsg->CheckControlFlowChange()) { 1557 etsg->ControlFlowChangeBreak(); 1558 } 1559 1560 etsg->EmitReturnVoid(st); 1561 1562 return; 1563 } 1564 1565 if (st->Argument()->IsCallExpression() && 1566 st->Argument()->AsCallExpression()->Signature()->ReturnType()->IsETSVoidType()) { 1567 st->Argument()->Compile(etsg); 1568 etsg->EmitReturnVoid(st); 1569 return; 1570 } 1571 1572 auto ttctx = compiler::TargetTypeContext(etsg, etsg->ReturnType()); 1573 1574 if (!etsg->TryLoadConstantExpression(st->Argument())) { 1575 st->Argument()->Compile(etsg); 1576 } 1577 1578 etsg->ApplyConversion(st->Argument(), nullptr); 1579 etsg->ApplyConversion(st->Argument(), st->ReturnType()); 1580 1581 if (etsg->ExtendWithFinalizer(st->Parent(), st)) { 1582 return; 1583 } 1584 1585 if (etsg->CheckControlFlowChange()) { 1586 compiler::RegScope rs(etsg); 1587 compiler::VReg res = etsg->AllocReg(); 1588 1589 etsg->StoreAccumulator(st, res); 1590 etsg->ControlFlowChangeBreak(); 1591 etsg->LoadAccumulator(st, res); 1592 } 1593 1594 etsg->ReturnAcc(st); 1595} 1596 1597static void CompileImpl(const ir::SwitchStatement *self, ETSGen *etsg) 1598{ 1599 compiler::LocalRegScope lrs(etsg, self->Scope()); 1600 compiler::SwitchBuilder builder(etsg, self); 1601 compiler::VReg tag = etsg->AllocReg(); 1602 1603 builder.CompileTagOfSwitch(tag); 1604 uint32_t defaultIndex = 0; 1605 1606 for (size_t i = 0; i < self->Cases().size(); i++) { 1607 const auto *clause = self->Cases()[i]; 1608 1609 if (clause->Test() == nullptr) { 1610 defaultIndex = i; 1611 continue; 1612 } 1613 1614 builder.JumpIfCase(tag, i); 1615 } 1616 1617 if (defaultIndex > 0) { 1618 builder.JumpToDefault(defaultIndex); 1619 } else { 1620 builder.Break(); 1621 } 1622 1623 for (size_t i = 0; i < self->Cases().size(); i++) { 1624 builder.SetCaseTarget(i); 1625 builder.CompileCaseStatements(i); 1626 } 1627} 1628 1629void ETSCompiler::Compile(const ir::SwitchStatement *st) const 1630{ 1631 ETSGen *etsg = GetETSGen(); 1632 CompileImpl(st, etsg); 1633} 1634 1635void ETSCompiler::Compile(const ir::ThrowStatement *st) const 1636{ 1637 ETSGen *etsg = GetETSGen(); 1638 etsg->ThrowException(st->Argument()); 1639} 1640 1641void ETSCompiler::Compile(const ir::TryStatement *st) const 1642{ 1643 ETSGen *etsg = GetETSGen(); 1644 1645 compiler::ETSTryContext tryCtx(etsg, etsg->Allocator(), st, st->FinallyBlock() != nullptr); 1646 1647 compiler::LabelPair tryLabelPair(etsg->AllocLabel(), etsg->AllocLabel()); 1648 1649 for (ir::CatchClause *clause : st->CatchClauses()) { 1650 tryCtx.AddNewCathTable(clause->TsType()->AsETSObjectType()->AssemblerName(), tryLabelPair); 1651 } 1652 1653 compiler::Label *statementEnd = etsg->AllocLabel(); 1654 auto catchTables = tryCtx.GetETSCatchTable(); 1655 1656 etsg->SetLabel(st, tryLabelPair.Begin()); 1657 st->Block()->Compile(etsg); 1658 etsg->Branch(st, statementEnd); 1659 etsg->SetLabel(st, tryLabelPair.End()); 1660 1661 ASSERT(st->CatchClauses().size() == catchTables.size()); 1662 1663 for (uint32_t i = 0; i < st->CatchClauses().size(); i++) { 1664 etsg->SetLabel(st, catchTables.at(i)->LabelSet().CatchBegin()); 1665 1666 st->CatchClauses().at(i)->Compile(etsg); 1667 1668 etsg->Branch(st, statementEnd); 1669 } 1670 1671 etsg->SetLabel(st, statementEnd); 1672 1673 auto trycatchLabelPair = compiler::LabelPair(tryLabelPair.Begin(), statementEnd); 1674 1675 tryCtx.EmitFinalizer(trycatchLabelPair, st->finalizerInsertions_); 1676} 1677 1678void ETSCompiler::Compile(const ir::VariableDeclarator *st) const 1679{ 1680 ETSGen *etsg = GetETSGen(); 1681 auto lref = compiler::ETSLReference::Create(etsg, st->Id(), true); 1682 auto ttctx = compiler::TargetTypeContext(etsg, st->TsType()); 1683 1684 if (st->Init() != nullptr) { 1685 if (!etsg->TryLoadConstantExpression(st->Init())) { 1686 st->Init()->Compile(etsg); 1687 etsg->ApplyConversion(st->Init(), nullptr); 1688 } 1689 } else { 1690 etsg->LoadDefaultValue(st, st->Id()->AsIdentifier()->Variable()->TsType()); 1691 } 1692 1693 etsg->ApplyConversion(st, st->TsType()); 1694 lref.SetValue(); 1695} 1696 1697void ETSCompiler::Compile(const ir::VariableDeclaration *st) const 1698{ 1699 ETSGen *etsg = GetETSGen(); 1700 for (const auto *it : st->Declarators()) { 1701 it->Compile(etsg); 1702 } 1703} 1704 1705template <typename CodeGen> 1706void CompileImpl(const ir::WhileStatement *whileStmt, [[maybe_unused]] CodeGen *cg) 1707{ 1708 compiler::LabelTarget labelTarget(cg); 1709 1710 cg->SetLabel(whileStmt, labelTarget.ContinueTarget()); 1711 compiler::Condition::Compile(cg, whileStmt->Test(), labelTarget.BreakTarget()); 1712 1713 { 1714 compiler::LocalRegScope regScope(cg, whileStmt->Scope()); 1715 compiler::LabelContext labelCtx(cg, labelTarget); 1716 whileStmt->Body()->Compile(cg); 1717 } 1718 1719 cg->Branch(whileStmt, labelTarget.ContinueTarget()); 1720 cg->SetLabel(whileStmt, labelTarget.BreakTarget()); 1721} 1722 1723void ETSCompiler::Compile(const ir::WhileStatement *st) const 1724{ 1725 ETSGen *etsg = GetETSGen(); 1726 CompileImpl(st, etsg); 1727} 1728 1729void ETSCompiler::Compile(const ir::TSArrayType *node) const 1730{ 1731 ETSGen *etsg = GetETSGen(); 1732 etsg->LoadAccumulatorNull(node, node->TsType()); 1733} 1734 1735void ETSCompiler::CompileCastUnboxable(const ir::TSAsExpression *expr) const 1736{ 1737 ETSGen *etsg = GetETSGen(); 1738 auto *targetType = etsg->Checker()->GetApparentType(expr->TsType()); 1739 ASSERT(targetType->IsETSObjectType()); 1740 1741 switch (targetType->AsETSObjectType()->BuiltInKind()) { 1742 case checker::ETSObjectFlags::BUILTIN_BOOLEAN: { 1743 etsg->CastToBoolean(expr); 1744 break; 1745 } 1746 case checker::ETSObjectFlags::BUILTIN_BYTE: { 1747 etsg->CastToByte(expr); 1748 break; 1749 } 1750 case checker::ETSObjectFlags::BUILTIN_CHAR: { 1751 etsg->CastToChar(expr); 1752 break; 1753 } 1754 case checker::ETSObjectFlags::BUILTIN_SHORT: { 1755 etsg->CastToShort(expr); 1756 break; 1757 } 1758 case checker::ETSObjectFlags::BUILTIN_INT: { 1759 etsg->CastToInt(expr); 1760 break; 1761 } 1762 case checker::ETSObjectFlags::BUILTIN_LONG: { 1763 etsg->CastToLong(expr); 1764 break; 1765 } 1766 case checker::ETSObjectFlags::BUILTIN_FLOAT: { 1767 etsg->CastToFloat(expr); 1768 break; 1769 } 1770 case checker::ETSObjectFlags::BUILTIN_DOUBLE: { 1771 etsg->CastToDouble(expr); 1772 break; 1773 } 1774 default: { 1775 UNREACHABLE(); 1776 } 1777 } 1778} 1779 1780void ETSCompiler::CompileCastPrimitives(const ir::TSAsExpression *expr) const 1781{ 1782 ETSGen *etsg = GetETSGen(); 1783 auto *targetType = etsg->Checker()->GetApparentType(expr->TsType()); 1784 1785 switch (checker::ETSChecker::TypeKind(targetType)) { 1786 case checker::TypeFlag::ETS_BOOLEAN: { 1787 etsg->CastToBoolean(expr); 1788 break; 1789 } 1790 case checker::TypeFlag::CHAR: { 1791 etsg->CastToChar(expr); 1792 break; 1793 } 1794 case checker::TypeFlag::BYTE: { 1795 etsg->CastToByte(expr); 1796 break; 1797 } 1798 case checker::TypeFlag::SHORT: { 1799 etsg->CastToShort(expr); 1800 break; 1801 } 1802 case checker::TypeFlag::INT: { 1803 etsg->CastToInt(expr); 1804 break; 1805 } 1806 case checker::TypeFlag::LONG: { 1807 etsg->CastToLong(expr); 1808 break; 1809 } 1810 case checker::TypeFlag::FLOAT: { 1811 etsg->CastToFloat(expr); 1812 break; 1813 } 1814 case checker::TypeFlag::DOUBLE: { 1815 etsg->CastToDouble(expr); 1816 break; 1817 } 1818 default: { 1819 UNREACHABLE(); 1820 } 1821 } 1822} 1823 1824void ETSCompiler::CompileCast(const ir::TSAsExpression *expr) const 1825{ 1826 ETSGen *etsg = GetETSGen(); 1827 auto *targetType = etsg->Checker()->GetApparentType(expr->TsType()); 1828 1829 switch (checker::ETSChecker::TypeKind(targetType)) { 1830 case checker::TypeFlag::ETS_ARRAY: 1831 case checker::TypeFlag::ETS_OBJECT: 1832 case checker::TypeFlag::ETS_TYPE_PARAMETER: 1833 case checker::TypeFlag::ETS_NONNULLISH: 1834 case checker::TypeFlag::ETS_UNION: 1835 case checker::TypeFlag::ETS_NULL: 1836 case checker::TypeFlag::ETS_UNDEFINED: { 1837 etsg->CastToReftype(expr, targetType, expr->isUncheckedCast_); 1838 break; 1839 } 1840 case checker::TypeFlag::ETS_DYNAMIC_TYPE: { 1841 etsg->CastToDynamic(expr, targetType->AsETSDynamicType()); 1842 break; 1843 } 1844 case checker::TypeFlag::ETS_STRING_ENUM: 1845 [[fallthrough]]; 1846 case checker::TypeFlag::ETS_INT_ENUM: { 1847 auto *const acuType = etsg->GetAccumulatorType(); 1848 if (acuType->IsETSEnumType()) { 1849 break; 1850 } 1851 ASSERT(!acuType->IsETSObjectType()); 1852 ASSERT(acuType->IsIntType()); 1853 auto *const signature = expr->TsType()->AsETSEnumType()->FromIntMethod().globalSignature; 1854 ArenaVector<ir::Expression *> arguments(etsg->Allocator()->Adapter()); 1855 arguments.push_back(expr->expression_); 1856 etsg->CallExact(expr, signature, arguments); 1857 etsg->SetAccumulatorType(signature->ReturnType()); 1858 break; 1859 } 1860 default: { 1861 return CompileCastPrimitives(expr); 1862 } 1863 } 1864} 1865 1866void ETSCompiler::Compile(const ir::TSAsExpression *expr) const 1867{ 1868 ETSGen *etsg = GetETSGen(); 1869 auto ttctx = compiler::TargetTypeContext(etsg, nullptr); 1870 if (!etsg->TryLoadConstantExpression(expr->Expr())) { 1871 expr->Expr()->Compile(etsg); 1872 } 1873 1874 auto *targetType = etsg->Checker()->GetApparentType(expr->TsType()); 1875 1876 if ((expr->Expr()->GetBoxingUnboxingFlags() & ir::BoxingUnboxingFlags::UNBOXING_FLAG) != 0U) { 1877 etsg->ApplyUnboxingConversion(expr->Expr()); 1878 } 1879 1880 if (targetType->IsETSObjectType() && 1881 ((expr->Expr()->GetBoxingUnboxingFlags() & ir::BoxingUnboxingFlags::UNBOXING_FLAG) != 0U || 1882 (expr->Expr()->GetBoxingUnboxingFlags() & ir::BoxingUnboxingFlags::BOXING_FLAG) != 0U) && 1883 checker::ETSChecker::TypeKind(etsg->GetAccumulatorType()) != checker::TypeFlag::ETS_OBJECT) { 1884 if (targetType->AsETSObjectType()->HasObjectFlag(checker::ETSObjectFlags::UNBOXABLE_TYPE)) { 1885 CompileCastUnboxable(expr); 1886 } 1887 } 1888 1889 if ((expr->Expr()->GetBoxingUnboxingFlags() & ir::BoxingUnboxingFlags::BOXING_FLAG) != 0U) { 1890 etsg->ApplyBoxingConversion(expr->Expr()); 1891 } 1892 1893 CompileCast(expr); 1894 ASSERT(etsg->Checker()->Relation()->IsIdenticalTo(etsg->GetAccumulatorType(), targetType)); 1895} 1896 1897void ETSCompiler::Compile([[maybe_unused]] const ir::TSInterfaceDeclaration *st) const {} 1898 1899void ETSCompiler::Compile(const ir::TSNonNullExpression *expr) const 1900{ 1901 ETSGen *etsg = GetETSGen(); 1902 compiler::RegScope rs(etsg); 1903 1904 expr->Expr()->Compile(etsg); 1905 1906 if (etsg->GetAccumulatorType()->PossiblyETSNullish()) { 1907 auto arg = etsg->AllocReg(); 1908 etsg->StoreAccumulator(expr, arg); 1909 etsg->LoadAccumulator(expr, arg); 1910 1911 auto endLabel = etsg->AllocLabel(); 1912 1913 etsg->BranchIfNotNullish(expr, endLabel); 1914 etsg->EmitNullishException(expr); 1915 1916 etsg->SetLabel(expr, endLabel); 1917 etsg->LoadAccumulator(expr, arg); 1918 etsg->AssumeNonNullish(expr, expr->OriginalType()); 1919 } 1920 1921 ASSERT(etsg->Checker()->Relation()->IsIdenticalTo(etsg->GetAccumulatorType(), expr->OriginalType())); 1922} 1923 1924void ETSCompiler::Compile([[maybe_unused]] const ir::TSTypeAliasDeclaration *st) const {} 1925} // namespace ark::es2panda::compiler 1926