diff --git a/ets2panda/compiler/core/ETSGen.h b/ets2panda/compiler/core/ETSGen.h index 44062c41cc13294f29efe3e31854726d9f54fa0d..27d3939b1ed781e30ff6c68b2a78d6cceab7e9eb 100644 --- a/ets2panda/compiler/core/ETSGen.h +++ b/ets2panda/compiler/core/ETSGen.h @@ -387,11 +387,22 @@ public: Ra().Emit(node, AssemblerSignatureReference(name), arg0, dummyReg_); } + void CallExactDevirtual(const ir::AstNode *const node, const util::StringView name, const VReg arg0) + { + Ra().EmitDevirtual(node, name, arg0, dummyReg_); + } + void CallExact(const ir::AstNode *const node, const util::StringView name, const VReg arg0, const VReg arg1) { Ra().Emit(node, AssemblerSignatureReference(name), arg0, arg1); } + void CallExactDevirtual(const ir::AstNode *const node, const util::StringView name, const VReg arg0, + const VReg arg1) + { + Ra().EmitDevirtual(node, name, arg0, arg1); + } + void CallExact(const ir::AstNode *const node, const util::StringView name, const VReg arg0, const VReg arg1, const VReg arg2) { @@ -415,7 +426,7 @@ public: ES2PANDA_ASSERT(!signature->HasSignatureFlag(checker::SignatureFlags::STATIC)); ES2PANDA_ASSERT(!signature->Owner()->GetDeclNode()->IsFinal() || signature->IsFinal()); if (IsDevirtualizedSignature(signature)) { - CallArgStart(node, signature, athis, arguments); + CallArgStartDevirtual(node, signature, athis, arguments); } else { CallArgStart(node, signature, athis, arguments); } @@ -424,7 +435,7 @@ public: void CallVirtual(const ir::AstNode *const node, const checker::Signature *signature, const VReg athis) { if (IsDevirtualizedSignature(signature)) { - CallExact(node, signature->InternalName(), athis); + CallExactDevirtual(node, signature->InternalName(), athis); } else { CallVirtual(node, signature->InternalName(), athis); } @@ -434,7 +445,7 @@ public: const VReg arg0) { if (IsDevirtualizedSignature(signature)) { - CallExact(node, signature->InternalName(), athis, arg0); + CallExactDevirtual(node, signature->InternalName(), athis, arg0); } else { CallVirtual(node, signature->InternalName(), athis, arg0); } @@ -683,6 +694,46 @@ private: } } + template + void CallArgStartDevirtual(const ir::AstNode *const node, const checker::Signature *signature, const VReg argStart, + const ArenaVector &arguments) + { + RegScope rs(this); + const auto name = signature->InternalName(); + switch (arguments.size()) { + case 0U: { + Ra().EmitDevirtual(node, name, argStart, dummyReg_); + break; + } + case 1U: { + COMPILE_ARG(0); + Ra().EmitDevirtual(node, name, argStart, arg0); + break; + } + case 2U: { + COMPILE_ARG(0); + COMPILE_ARG(1); + Ra().EmitDevirtual(node, name, argStart, arg0, arg1, dummyReg_); + break; + } + case 3U: { + COMPILE_ARG(0); + COMPILE_ARG(1); + COMPILE_ARG(2); + Ra().EmitDevirtual(node, name, argStart, arg0, arg1, arg2); + break; + } + default: { + for (size_t idx = 0; idx < arguments.size(); idx++) { + COMPILE_ARG(idx); + } + + Rra().EmitDevirtual(node, argStart, arguments.size() + 1, name, argStart); + break; + } + } + } + template void CallImpl(const ir::AstNode *node, checker::Signature const *signature, const ArenaVector &arguments) diff --git a/ets2panda/compiler/core/regAllocator.h b/ets2panda/compiler/core/regAllocator.h index 2f48a9a674721672c9b08917471833c38ca41fa7..469d2558100340c3ea6693a596117f6fd9a9d91d 100644 --- a/ets2panda/compiler/core/regAllocator.h +++ b/ets2panda/compiler/core/regAllocator.h @@ -108,6 +108,14 @@ public: Run(ins, VALID_VREGS); } + template ::max(), typename... Args> + void EmitDevirtual(const ir::AstNode *const node, Args &&...args) + { + auto *const ins = Alloc(node, std::forward(args)...); + Run(ins, VALID_VREGS); + ins->SetDevirtual(); + } + private: void Run(IRNode *ins, int32_t spillMax); }; @@ -126,6 +134,14 @@ public: Run(ins, rangeStart, argCount); } + template + void EmitDevirtual(const ir::AstNode *const node, const VReg rangeStart, const std::size_t argCount, Args &&...args) + { + auto *const ins = Alloc(node, std::forward(args)...); + Run(ins, rangeStart, argCount); + ins->SetDevirtual(); + } + private: void Run(IRNode *ins, VReg rangeStart, size_t argCount); }; diff --git a/ets2panda/compiler/templates/isa.h.erb b/ets2panda/compiler/templates/isa.h.erb index 87789468d6a2b3be303b102b63b620f2f57f4855..07104538a9dbd6f4a72bf2262cac61eecdc4a8ec 100644 --- a/ets2panda/compiler/templates/isa.h.erb +++ b/ets2panda/compiler/templates/isa.h.erb @@ -183,6 +183,9 @@ public: void Transform(pandasm::Ins *ins, [[maybe_unused]] ProgramElement *programElement, [[maybe_unused]] uint32_t totalRegs) const override { ins->opcode = pandasm::Opcode::<%= node_kind %>; + if (IsDevirtual()) { + ins->SetIsDevirtual(); + } % for reg in op_map['reg'] ins->EmplaceReg(MapRegister(<%= reg %>.GetIndex(), totalRegs)); % end diff --git a/ets2panda/ir/irnode.h b/ets2panda/ir/irnode.h index 84f269da1f3a6988cc6c3effb51e17278f6a8b0b..dc8e81cd3ffc1da4d5f8bb66053e9e557f599e4e 100644 --- a/ets2panda/ir/irnode.h +++ b/ets2panda/ir/irnode.h @@ -151,9 +151,19 @@ public: virtual size_t OutRegisters([[maybe_unused]] std::array *regs) const = 0; virtual void Transform(ark::pandasm::Ins *ins, [[maybe_unused]] ProgramElement *programElement, [[maybe_unused]] uint32_t totalRegs) const = 0; + bool IsDevirtual() const + { + return isDevirtual_; + } + + void SetDevirtual() + { + isDevirtual_ = true; + } private: const ir::AstNode *node_; + bool isDevirtual_ = false; }; } // namespace ark::es2panda::compiler diff --git a/ets2panda/test/runtime/ets/StaticAndInstanceMethodCall.ets b/ets2panda/test/runtime/ets/StaticAndInstanceMethodCall.ets new file mode 100644 index 0000000000000000000000000000000000000000..96417dd5958925fdf27f340817db95492abb860b --- /dev/null +++ b/ets2panda/test/runtime/ets/StaticAndInstanceMethodCall.ets @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +let res: string = ""; +final class AA { + getString(arg: number) { res = "instance" } + static getString(arg: number) { res = "static"; } +} + +function foo() { + let a = new AA() + let radix: number = 16 + a.getString(radix) +} + +foo(); +arktest.assertTrue(res == "instance"); +