• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2025 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 "compiler/core/ETSGen.h"
20 #include "ir/expressions/assignmentExpression.h"
21 #include "ir/expressions/binaryExpression.h"
22 #include "ir/expressions/callExpression.h"
23 #include "ir/expressions/unaryExpression.h"
24 
25 namespace ark::es2panda::compiler {
CompileBinaryExpr(PandaGen * pg,const ir::BinaryExpression * binExpr,Label * falseLabel)26 bool Condition::CompileBinaryExpr(PandaGen *pg, const ir::BinaryExpression *binExpr, Label *falseLabel)
27 {
28     switch (binExpr->OperatorType()) {
29         case lexer::TokenType::PUNCTUATOR_EQUAL:
30         case lexer::TokenType::PUNCTUATOR_NOT_EQUAL:
31         case lexer::TokenType::PUNCTUATOR_STRICT_EQUAL:
32         case lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL:
33         case lexer::TokenType::PUNCTUATOR_LESS_THAN:
34         case lexer::TokenType::PUNCTUATOR_LESS_THAN_EQUAL:
35         case lexer::TokenType::PUNCTUATOR_GREATER_THAN:
36         case lexer::TokenType::PUNCTUATOR_GREATER_THAN_EQUAL: {
37             // This is a special case
38             // These operators are expressed via cmp instructions and the following
39             // if-else branches. Condition also expressed via cmp instruction and
40             // the following if-else.
41             // the goal of this method is to merge these two sequences of instructions.
42             RegScope rs(pg);
43             VReg lhs = pg->AllocReg();
44 
45             binExpr->Left()->Compile(pg);
46             pg->StoreAccumulator(binExpr, lhs);
47             binExpr->Right()->Compile(pg);
48             pg->Condition(binExpr, binExpr->OperatorType(), lhs, falseLabel);
49             return true;
50         }
51         case lexer::TokenType::PUNCTUATOR_LOGICAL_AND: {
52             binExpr->Left()->Compile(pg);
53             pg->ToBoolean(binExpr);
54             pg->BranchIfFalse(binExpr, falseLabel);
55 
56             binExpr->Right()->Compile(pg);
57             pg->ToBoolean(binExpr);
58             pg->BranchIfFalse(binExpr, falseLabel);
59             return true;
60         }
61         case lexer::TokenType::PUNCTUATOR_LOGICAL_OR: {
62             auto *endLabel = pg->AllocLabel();
63 
64             binExpr->Left()->Compile(pg);
65             pg->ToBoolean(binExpr);
66             pg->BranchIfTrue(binExpr, endLabel);
67 
68             binExpr->Right()->Compile(pg);
69             pg->ToBoolean(binExpr);
70             pg->BranchIfFalse(binExpr, falseLabel);
71             pg->SetLabel(binExpr, endLabel);
72             return true;
73         }
74         default: {
75             break;
76         }
77     }
78     return false;
79 }
80 
Compile(PandaGen * pg,const ir::Expression * expr,Label * falseLabel)81 void Condition::Compile(PandaGen *pg, const ir::Expression *expr, Label *falseLabel)
82 {
83     if (expr->IsBinaryExpression()) {
84         if (CompileBinaryExpr(pg, expr->AsBinaryExpression(), falseLabel)) {
85             return;
86         }
87     } else if (expr->IsUnaryExpression() &&
88                expr->AsUnaryExpression()->OperatorType() == lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK) {
89         expr->AsUnaryExpression()->Argument()->Compile(pg);
90 
91         pg->Negate(expr);
92         pg->BranchIfFalse(expr, falseLabel);
93         return;
94     }
95 
96     // General case including some binExpr i.E.(a+b)
97     expr->Compile(pg);
98     pg->ToBoolean(expr);
99     pg->BranchIfFalse(expr, falseLabel);
100 }
101 
CompileBinaryExprForBigInt(ETSGen * etsg,const ir::BinaryExpression * expr,Label * falseLabel)102 bool Condition::CompileBinaryExprForBigInt(ETSGen *etsg, const ir::BinaryExpression *expr, Label *falseLabel)
103 {
104     if ((expr->Left()->TsType() == nullptr) || (expr->Right()->TsType() == nullptr)) {
105         return false;
106     }
107 
108     if (!expr->Left()->TsType()->IsETSBigIntType()) {
109         return false;
110     }
111 
112     if (!expr->Right()->TsType()->IsETSBigIntType()) {
113         return false;
114     }
115 
116     std::string_view signature = compiler::Signatures::ANY;
117     switch (expr->OperatorType()) {
118         case lexer::TokenType::PUNCTUATOR_LESS_THAN:
119             signature = compiler::Signatures::BUILTIN_BIGINT_OPERATOR_LESS_THAN;
120             break;
121         case lexer::TokenType::PUNCTUATOR_LESS_THAN_EQUAL:
122             signature = compiler::Signatures::BUILTIN_BIGINT_OPERATOR_LESS_THAN_EQUAL;
123             break;
124         case lexer::TokenType::PUNCTUATOR_GREATER_THAN:
125             signature = compiler::Signatures::BUILTIN_BIGINT_OPERATOR_GREATER_THAN;
126             break;
127         case lexer::TokenType::PUNCTUATOR_GREATER_THAN_EQUAL:
128             signature = compiler::Signatures::BUILTIN_BIGINT_OPERATOR_GREATER_THAN_EQUAL;
129             break;
130         default:
131             // Other operations are handled in the CompileBinaryExpr function
132             return false;
133     }
134 
135     auto ttctx = TargetTypeContext(etsg, expr->OperationType());
136     RegScope rs(etsg);
137     VReg lhs = etsg->AllocReg();
138     expr->Left()->Compile(etsg);
139     etsg->ApplyConversionAndStoreAccumulator(expr->Left(), lhs, expr->OperationType());
140     expr->Right()->Compile(etsg);
141     etsg->ApplyConversion(expr->Right(), expr->OperationType());
142     compiler::VReg rhs = etsg->AllocReg();
143     etsg->StoreAccumulator(expr, rhs);
144     etsg->CallBigIntBinaryComparison(expr, lhs, rhs, signature);
145     etsg->BranchIfFalse(expr, falseLabel);
146 
147     return true;
148 }
149 
CompileInstanceofExpr(ETSGen * etsg,const ir::BinaryExpression * binExpr,Label * falseLabel)150 void Condition::CompileInstanceofExpr(ETSGen *etsg, const ir::BinaryExpression *binExpr, Label *falseLabel)
151 {
152     ES2PANDA_ASSERT(binExpr->OperatorType() == lexer::TokenType::KEYW_INSTANCEOF);
153     binExpr->Compile(etsg);
154     etsg->BranchIfFalse(binExpr, falseLabel);
155 }
156 
CompileLogical(ETSGen * etsg,const ir::BinaryExpression * binExpr,Label * falseLabel)157 void Condition::CompileLogical(ETSGen *etsg, const ir::BinaryExpression *binExpr, Label *falseLabel)
158 {
159     ES2PANDA_ASSERT(binExpr->IsLogicalExtended());
160 
161     // If the Result is given, we can optimize the process.
162     if (binExpr->Result() != nullptr) {
163         if (binExpr->Result() != binExpr->Left()) {
164             ES2PANDA_ASSERT(binExpr->Result() == binExpr->Right());
165             etsg->CompileAndCheck(binExpr->Left());
166         }
167         Compile(etsg, binExpr->Result(), falseLabel);
168         return;
169     }
170 
171     compiler::RegScope rs(etsg);
172     auto *endLabel = etsg->AllocLabel();
173 
174     if (binExpr->OperatorType() == lexer::TokenType::PUNCTUATOR_LOGICAL_AND) {
175         Compile(etsg, binExpr->Left(), falseLabel);
176     } else {
177         ES2PANDA_ASSERT(binExpr->OperatorType() == lexer::TokenType::PUNCTUATOR_LOGICAL_OR);
178         etsg->CompileAndCheck(binExpr->Left());
179         etsg->BranchConditionalIfTrue(binExpr->Left(), endLabel);
180     }
181 
182     Compile(etsg, binExpr->Right(), falseLabel);
183     etsg->SetLabel(binExpr, endLabel);
184 }
185 
CompileBinaryExpr(ETSGen * etsg,const ir::BinaryExpression * binExpr,Label * falseLabel)186 bool Condition::CompileBinaryExpr(ETSGen *etsg, const ir::BinaryExpression *binExpr, Label *falseLabel)
187 {
188     if (CompileBinaryExprForBigInt(etsg, binExpr, falseLabel)) {
189         return true;
190     }
191 
192     switch (binExpr->OperatorType()) {
193         case lexer::TokenType::PUNCTUATOR_EQUAL:
194         case lexer::TokenType::PUNCTUATOR_NOT_EQUAL:
195         case lexer::TokenType::PUNCTUATOR_LESS_THAN:
196         case lexer::TokenType::PUNCTUATOR_LESS_THAN_EQUAL:
197         case lexer::TokenType::PUNCTUATOR_GREATER_THAN:
198         case lexer::TokenType::PUNCTUATOR_GREATER_THAN_EQUAL: {
199             auto ttctx = TargetTypeContext(etsg, binExpr->OperationType());
200 
201             RegScope rs(etsg);
202             VReg lhs = etsg->AllocReg();
203 
204             binExpr->CompileOperands(etsg, lhs);
205             etsg->Condition(binExpr, binExpr->OperatorType(), lhs, falseLabel);
206             return true;
207         }
208         case lexer::TokenType::PUNCTUATOR_LOGICAL_OR:
209         case lexer::TokenType::PUNCTUATOR_LOGICAL_AND: {
210             CompileLogical(etsg, binExpr, falseLabel);
211             return true;
212         }
213         case lexer::TokenType::KEYW_INSTANCEOF: {
214             CompileInstanceofExpr(etsg, binExpr, falseLabel);
215             return true;
216         }
217         default: {
218             break;
219         }
220     }
221     return false;
222 }
223 
Compile(ETSGen * etsg,const ir::Expression * expr,Label * falseLabel)224 void Condition::Compile(ETSGen *etsg, const ir::Expression *expr, Label *falseLabel)
225 {
226     if (expr->IsBinaryExpression()) {
227         if (CompileBinaryExpr(etsg, expr->AsBinaryExpression(), falseLabel)) {
228             return;
229         }
230     } else if (expr->IsUnaryExpression() &&
231                expr->AsUnaryExpression()->OperatorType() == lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK) {
232         expr->AsUnaryExpression()->Argument()->Compile(etsg);
233         etsg->ApplyConversion(expr->AsUnaryExpression()->Argument(), etsg->Checker()->GlobalETSBooleanType());
234         etsg->ResolveConditionalResultIfTrue<false, false>(expr, falseLabel);
235         etsg->BranchIfTrue(expr, falseLabel);
236         return;
237     }
238     expr->Compile(etsg);
239     etsg->ApplyConversion(expr, etsg->Checker()->GlobalETSBooleanType());
240     etsg->ResolveConditionalResultIfFalse(expr, falseLabel);
241     etsg->BranchIfFalse(expr, falseLabel);
242 }
243 }  // namespace ark::es2panda::compiler
244