• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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