From 60f5085887b6d3b31cf5f324c11317a5157df548 Mon Sep 17 00:00:00 2001 From: Martin Sajti Date: Fri, 5 Jan 2024 15:53:39 +0100 Subject: [PATCH] Get enum value, when used with '&' operator in binary expression Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/I8UVCM Internal issue: #15017 Test: build, new runtime test Signed-off-by: Martin Sajti --- ets2panda/checker/ets/arithmetic.cpp | 13 ++++++++ ets2panda/compiler/core/ETSGen.cpp | 7 ++++ ets2panda/ir/astNode.h | 2 +- ets2panda/ir/astNodeFlags.h | 1 + ets2panda/test/runtime/ets/Enum6.ets | 50 ++++++++++++++++++++++++++++ 5 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 ets2panda/test/runtime/ets/Enum6.ets diff --git a/ets2panda/checker/ets/arithmetic.cpp b/ets2panda/checker/ets/arithmetic.cpp index e65660e159..8714258e63 100644 --- a/ets2panda/checker/ets/arithmetic.cpp +++ b/ets2panda/checker/ets/arithmetic.cpp @@ -236,6 +236,19 @@ checker::Type *ETSChecker::CheckBinaryOperatorBitwise(ir::Expression *left, ir:: bool isEqualOp, checker::Type *const leftType, checker::Type *const rightType, Type *unboxedL, Type *unboxedR) { + // NOTE (mmartin): These need to be done for other binary expressions, but currently it's not defined precisely when + // to apply this conversion + + if (leftType->IsETSEnumType()) { + left->AddAstNodeFlags(ir::AstNodeFlags::ENUM_GET_VALUE); + unboxedL = GlobalIntType(); + } + + if (rightType->IsETSEnumType()) { + right->AddAstNodeFlags(ir::AstNodeFlags::ENUM_GET_VALUE); + unboxedR = GlobalIntType(); + } + if (leftType->IsETSUnionType() || rightType->IsETSUnionType()) { ThrowTypeError("Bad operand type, unions are not allowed in binary expressions except equality.", pos); } diff --git a/ets2panda/compiler/core/ETSGen.cpp b/ets2panda/compiler/core/ETSGen.cpp index 9603461920..a7f000ba11 100644 --- a/ets2panda/compiler/core/ETSGen.cpp +++ b/ets2panda/compiler/core/ETSGen.cpp @@ -961,6 +961,13 @@ void ETSGen::ApplyConversion(const ir::AstNode *node, const checker::Type *targe { auto ttctx = TargetTypeContext(this, targetType); + if (node->HasAstNodeFlags(ir::AstNodeFlags::ENUM_GET_VALUE)) { + Ra().Emit( + node, node->AsExpression()->TsType()->AsETSEnumType()->GetValueMethod().globalSignature->InternalName(), + dummyReg_, 0); + node->RemoveAstNodeFlags(ir::AstNodeFlags::ENUM_GET_VALUE); + } + if ((node->GetBoxingUnboxingFlags() & ir::BoxingUnboxingFlags::BOXING_FLAG) != 0U) { ApplyBoxingConversion(node); return; diff --git a/ets2panda/ir/astNode.h b/ets2panda/ir/astNode.h index f6eedfb88e..4b20f93db3 100644 --- a/ets2panda/ir/astNode.h +++ b/ets2panda/ir/astNode.h @@ -450,7 +450,7 @@ public: { \ return ((member_name)&flag) != 0U; \ } \ - void Remove##flag_type(flag_type flag) noexcept \ + void Remove##flag_type(flag_type flag) const noexcept \ { \ (member_name) &= ~flag; \ } diff --git a/ets2panda/ir/astNodeFlags.h b/ets2panda/ir/astNodeFlags.h index f6420bb131..fb74be021b 100644 --- a/ets2panda/ir/astNodeFlags.h +++ b/ets2panda/ir/astNodeFlags.h @@ -22,6 +22,7 @@ namespace panda::es2panda::ir { enum class AstNodeFlags { NO_OPTS = 0, CHECKCAST = 1U << 0U, + ENUM_GET_VALUE = 1U << 1U, }; enum class ModifierFlags : uint32_t { diff --git a/ets2panda/test/runtime/ets/Enum6.ets b/ets2panda/test/runtime/ets/Enum6.ets new file mode 100644 index 0000000000..39b8f0c5db --- /dev/null +++ b/ets2panda/test/runtime/ets/Enum6.ets @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2023 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. + */ + +enum Access { + READ = 1, + WRITE = 2, + READWRITE = 3 +} + +enum TestEnum { + A = 144, + B, + C = 795 +} + +function main(): void { + test_access_enum_bitwise(Access.WRITE); + assert (Access.WRITE & Access.READWRITE) == 2; + + test_test_enum_bitwise(TestEnum.C); + assert (TestEnum.B & TestEnum.A) == 144 + +} + +function test_access_enum_bitwise(enum_val: Access): void { + assert (enum_val & Access.READ) == 0 + assert (enum_val & Access.WRITE) == 2 + assert (enum_val | Access.READ) == 3 + assert (enum_val | Access.READWRITE) == 3 + assert (enum_val & Access.READWRITE) == 2 +} + +function test_test_enum_bitwise(enum_val: TestEnum): void { + assert (enum_val & TestEnum.A) == 16 + assert (enum_val | TestEnum.A) == 923 + assert (enum_val & TestEnum.B) == 17 + assert (enum_val | TestEnum.B) == 923 +} -- Gitee