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 "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
CheckConstantExpr(ETSGen * etsg,const ir::Expression * expr)102 Condition::Result Condition::CheckConstantExpr(ETSGen *etsg, const ir::Expression *expr)
103 {
104 const auto resultingExpression = [](const ir::Expression *e) {
105 if (e->IsBinaryExpression() && e->AsBinaryExpression()->IsLogicalExtended()) {
106 return e->AsBinaryExpression()->Result();
107 }
108 if (e->IsAssignmentExpression() && e->AsAssignmentExpression()->IsLogicalExtended()) {
109 return e->AsAssignmentExpression()->Result();
110 }
111 return e;
112 }(expr);
113 if (resultingExpression == nullptr) {
114 return Result::UNKNOWN;
115 }
116
117 if (etsg->Checker()->IsNullLikeOrVoidExpression(resultingExpression)) {
118 return Result::CONST_FALSE;
119 }
120
121 auto exprRes = resultingExpression->TsType()->ResolveConditionExpr();
122 if (std::get<0>(exprRes)) {
123 return std::get<1>(exprRes) ? Result::CONST_TRUE : Result::CONST_FALSE;
124 }
125
126 return Result::UNKNOWN;
127 }
128
CompileLogicalOrExpr(ETSGen * etsg,const ir::BinaryExpression * binExpr,Label * falseLabel)129 void Condition::CompileLogicalOrExpr(ETSGen *etsg, const ir::BinaryExpression *binExpr, Label *falseLabel)
130 {
131 auto ttctx = TargetTypeContext(etsg, binExpr->OperationType());
132 RegScope rs(etsg);
133 VReg lhs = etsg->AllocReg();
134 VReg rhs = etsg->AllocReg();
135 auto *returnLeftLabel = etsg->AllocLabel();
136 auto *returnRightTrueLabel = etsg->AllocLabel();
137 auto *returnRightFalseLabel = etsg->AllocLabel();
138
139 binExpr->Left()->Compile(etsg);
140 etsg->ApplyConversionAndStoreAccumulator(binExpr->Left(), lhs, binExpr->OperationType());
141 etsg->ResolveConditionalResultIfTrue(binExpr->Left(), returnLeftLabel);
142 etsg->BranchIfTrue(binExpr, returnLeftLabel);
143
144 binExpr->Right()->Compile(etsg);
145 etsg->ApplyConversionAndStoreAccumulator(binExpr->Right(), rhs, binExpr->OperationType());
146 etsg->ResolveConditionalResultIfFalse(binExpr->Right(), returnRightFalseLabel);
147 etsg->BranchIfFalse(binExpr, returnRightFalseLabel);
148 etsg->LoadAccumulator(binExpr, rhs);
149 etsg->Branch(binExpr, returnRightTrueLabel);
150
151 etsg->SetLabel(binExpr, returnRightFalseLabel);
152 etsg->LoadAccumulator(binExpr, rhs);
153 etsg->Branch(binExpr, falseLabel);
154 etsg->SetLabel(binExpr, returnLeftLabel);
155 etsg->LoadAccumulator(binExpr, lhs);
156 etsg->SetLabel(binExpr, returnRightTrueLabel);
157 }
158
CompileLogicalAndExpr(ETSGen * etsg,const ir::BinaryExpression * binExpr,Label * falseLabel)159 void Condition::CompileLogicalAndExpr(ETSGen *etsg, const ir::BinaryExpression *binExpr, Label *falseLabel)
160 {
161 auto ttctx = TargetTypeContext(etsg, binExpr->OperationType());
162 RegScope rs(etsg);
163 VReg lhs = etsg->AllocReg();
164 VReg rhs = etsg->AllocReg();
165 auto *returnLeftLabel = etsg->AllocLabel();
166 auto *returnRightTrueLabel = etsg->AllocLabel();
167 auto *returnRightFalseLabel = etsg->AllocLabel();
168
169 binExpr->Left()->Compile(etsg);
170 etsg->ApplyConversionAndStoreAccumulator(binExpr->Left(), lhs, binExpr->OperationType());
171 etsg->ResolveConditionalResultIfFalse(binExpr->Left(), returnLeftLabel);
172 etsg->BranchIfFalse(binExpr, returnLeftLabel);
173
174 binExpr->Right()->Compile(etsg);
175 etsg->ApplyConversionAndStoreAccumulator(binExpr->Right(), rhs, binExpr->OperationType());
176 etsg->ResolveConditionalResultIfFalse(binExpr->Right(), returnRightFalseLabel);
177 etsg->BranchIfFalse(binExpr, returnRightFalseLabel);
178 etsg->LoadAccumulator(binExpr, rhs);
179 etsg->Branch(binExpr, returnRightTrueLabel);
180
181 etsg->SetLabel(binExpr, returnLeftLabel);
182 etsg->LoadAccumulator(binExpr, lhs);
183 etsg->Branch(binExpr, falseLabel);
184 etsg->SetLabel(binExpr, returnRightFalseLabel);
185 etsg->LoadAccumulator(binExpr, rhs);
186 etsg->Branch(binExpr, falseLabel);
187 etsg->SetLabel(binExpr, returnRightTrueLabel);
188 }
189
CompileBinaryExprForBigInt(ETSGen * etsg,const ir::BinaryExpression * expr,Label * falseLabel)190 bool Condition::CompileBinaryExprForBigInt(ETSGen *etsg, const ir::BinaryExpression *expr, Label *falseLabel)
191 {
192 if ((expr->Left()->TsType() == nullptr) || (expr->Right()->TsType() == nullptr)) {
193 return false;
194 }
195
196 if (!expr->Left()->TsType()->IsETSBigIntType()) {
197 return false;
198 }
199
200 if (!expr->Right()->TsType()->IsETSBigIntType()) {
201 return false;
202 }
203
204 std::string_view signature = compiler::Signatures::ANY;
205 switch (expr->OperatorType()) {
206 case lexer::TokenType::PUNCTUATOR_LESS_THAN:
207 signature = compiler::Signatures::BUILTIN_BIGINT_OPERATOR_LESS_THAN;
208 break;
209 case lexer::TokenType::PUNCTUATOR_LESS_THAN_EQUAL:
210 signature = compiler::Signatures::BUILTIN_BIGINT_OPERATOR_LESS_THAN_EQUAL;
211 break;
212 case lexer::TokenType::PUNCTUATOR_GREATER_THAN:
213 signature = compiler::Signatures::BUILTIN_BIGINT_OPERATOR_GREATER_THAN;
214 break;
215 case lexer::TokenType::PUNCTUATOR_GREATER_THAN_EQUAL:
216 signature = compiler::Signatures::BUILTIN_BIGINT_OPERATOR_GREATER_THAN_EQUAL;
217 break;
218 default:
219 // Other operations are handled in the CompileBinaryExpr function
220 return false;
221 }
222
223 auto ttctx = TargetTypeContext(etsg, expr->OperationType());
224 RegScope rs(etsg);
225 VReg lhs = etsg->AllocReg();
226 expr->Left()->Compile(etsg);
227 etsg->ApplyConversionAndStoreAccumulator(expr->Left(), lhs, expr->OperationType());
228 expr->Right()->Compile(etsg);
229 etsg->ApplyConversion(expr->Right(), expr->OperationType());
230 compiler::VReg rhs = etsg->AllocReg();
231 etsg->StoreAccumulator(expr, rhs);
232 etsg->CallBigIntBinaryComparison(expr, lhs, rhs, signature);
233 etsg->BranchIfFalse(expr, falseLabel);
234
235 return true;
236 }
237
CompileInstanceofExpr(ETSGen * etsg,const ir::BinaryExpression * binExpr,Label * falseLabel)238 void Condition::CompileInstanceofExpr(ETSGen *etsg, const ir::BinaryExpression *binExpr, Label *falseLabel)
239 {
240 ASSERT(binExpr->OperatorType() == lexer::TokenType::KEYW_INSTANCEOF);
241 binExpr->Compile(etsg);
242 etsg->BranchIfFalse(binExpr, falseLabel);
243 }
244
CompileBinaryExpr(ETSGen * etsg,const ir::BinaryExpression * binExpr,Label * falseLabel)245 bool Condition::CompileBinaryExpr(ETSGen *etsg, const ir::BinaryExpression *binExpr, Label *falseLabel)
246 {
247 if (CompileBinaryExprForBigInt(etsg, binExpr, falseLabel)) {
248 return true;
249 }
250
251 switch (binExpr->OperatorType()) {
252 case lexer::TokenType::PUNCTUATOR_EQUAL:
253 case lexer::TokenType::PUNCTUATOR_NOT_EQUAL:
254 case lexer::TokenType::PUNCTUATOR_LESS_THAN:
255 case lexer::TokenType::PUNCTUATOR_LESS_THAN_EQUAL:
256 case lexer::TokenType::PUNCTUATOR_GREATER_THAN:
257 case lexer::TokenType::PUNCTUATOR_GREATER_THAN_EQUAL: {
258 auto ttctx = TargetTypeContext(etsg, binExpr->OperationType());
259
260 RegScope rs(etsg);
261 VReg lhs = etsg->AllocReg();
262
263 binExpr->CompileOperands(etsg, lhs);
264 etsg->Condition(binExpr, binExpr->OperatorType(), lhs, falseLabel);
265 return true;
266 }
267 case lexer::TokenType::PUNCTUATOR_LOGICAL_AND: {
268 CompileLogicalAndExpr(etsg, binExpr, falseLabel);
269 return true;
270 }
271 case lexer::TokenType::PUNCTUATOR_LOGICAL_OR: {
272 CompileLogicalOrExpr(etsg, binExpr, falseLabel);
273 return true;
274 }
275 case lexer::TokenType::KEYW_INSTANCEOF: {
276 CompileInstanceofExpr(etsg, binExpr, falseLabel);
277 return true;
278 }
279 default: {
280 break;
281 }
282 }
283 return false;
284 }
285
Compile(ETSGen * etsg,const ir::Expression * expr,Label * falseLabel)286 void Condition::Compile(ETSGen *etsg, const ir::Expression *expr, Label *falseLabel)
287 {
288 if (expr->IsBinaryExpression()) {
289 if (CompileBinaryExpr(etsg, expr->AsBinaryExpression(), falseLabel)) {
290 return;
291 }
292 } else if (expr->IsUnaryExpression() &&
293 expr->AsUnaryExpression()->OperatorType() == lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK) {
294 expr->AsUnaryExpression()->Argument()->Compile(etsg);
295 etsg->ApplyConversion(expr->AsUnaryExpression()->Argument(), etsg->Checker()->GlobalETSBooleanType());
296 etsg->ResolveConditionalResultIfTrue(expr, falseLabel);
297 etsg->BranchIfTrue(expr, falseLabel);
298 return;
299 }
300 ASSERT(expr->TsType()->IsConditionalExprType());
301 expr->Compile(etsg);
302 etsg->ApplyConversion(expr, etsg->Checker()->GlobalETSBooleanType());
303 etsg->ResolveConditionalResultIfFalse(expr, falseLabel);
304 etsg->BranchIfFalse(expr, falseLabel);
305 }
306 } // namespace ark::es2panda::compiler
307