1/*
2 * Copyright (c) 2021-2022 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 "condition.h"
17
18#include <compiler/core/pandagen.h>
19#include <ir/expressions/binaryExpression.h>
20#include <ir/expressions/unaryExpression.h>
21
22namespace panda::es2panda::compiler {
23
24void Condition::Compile(PandaGen *pg, const ir::Expression *expr, Label *falseLabel)
25{
26    if (expr->IsBinaryExpression()) {
27        const auto *binExpr = expr->AsBinaryExpression();
28
29        switch (binExpr->OperatorType()) {
30            case lexer::TokenType::PUNCTUATOR_EQUAL:
31            case lexer::TokenType::PUNCTUATOR_NOT_EQUAL:
32            case lexer::TokenType::PUNCTUATOR_STRICT_EQUAL:
33            case lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL:
34            case lexer::TokenType::PUNCTUATOR_LESS_THAN:
35            case lexer::TokenType::PUNCTUATOR_LESS_THAN_EQUAL:
36            case lexer::TokenType::PUNCTUATOR_GREATER_THAN:
37            case lexer::TokenType::PUNCTUATOR_GREATER_THAN_EQUAL: {
38                // This is a special case
39                // These operators are expressed via cmp instructions and the following
40                // if-else branches. Condition also expressed via cmp instruction and
41                // the following if-else.
42                // the goal of this method is to merge these two sequences of instructions.
43                RegScope rs(pg);
44                VReg lhs = pg->AllocReg();
45
46                binExpr->Left()->Compile(pg);
47                pg->StoreAccumulator(binExpr, lhs);
48                binExpr->Right()->Compile(pg);
49                pg->Condition(binExpr, binExpr->OperatorType(), lhs, falseLabel);
50                return;
51            }
52            case lexer::TokenType::PUNCTUATOR_LOGICAL_AND: {
53                binExpr->Left()->Compile(pg);
54                pg->BranchIfFalse(binExpr, falseLabel);
55
56                binExpr->Right()->Compile(pg);
57                pg->BranchIfFalse(binExpr, falseLabel);
58                return;
59            }
60            case lexer::TokenType::PUNCTUATOR_LOGICAL_OR: {
61                auto *endLabel = pg->AllocLabel();
62
63                binExpr->Left()->Compile(pg);
64                pg->BranchIfTrue(binExpr, endLabel);
65
66                binExpr->Right()->Compile(pg);
67                pg->BranchIfFalse(binExpr, falseLabel);
68                pg->SetLabel(binExpr, endLabel);
69                return;
70            }
71            default: {
72                break;
73            }
74        }
75    } else if (expr->IsUnaryExpression() &&
76               expr->AsUnaryExpression()->OperatorType() == lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK) {
77        expr->AsUnaryExpression()->Argument()->Compile(pg);
78
79        pg->Negate(expr);
80        pg->BranchIfFalse(expr, falseLabel);
81        return;
82    }
83
84    // General case including some binExpr i.E.(a+b)
85    expr->Compile(pg);
86    pg->BranchIfFalse(expr, falseLabel);
87}
88
89}  // namespace panda::es2panda::compiler
90