• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 "cgfunc.h"
17 #if DEBUG
18 #include <iomanip>
19 #endif
20 #include "cg.h"
21 #include "insn.h"
22 #include "loop.h"
23 #include "mir_builder.h"
24 #include "factory.h"
25 #include "debug_info.h"
26 #include "optimize_common.h"
27 
28 namespace maplebe {
29 using namespace maple;
30 
31 #define JAVALANG (GetMirModule().IsJavaModule())
32 
HandleDread(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)33 Operand *HandleDread(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
34 {
35     auto &dreadNode = static_cast<AddrofNode &>(expr);
36     return cgFunc.SelectDread(parent, dreadNode);
37 }
38 
HandleRegread(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)39 Operand *HandleRegread(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
40 {
41     (void)parent;
42     auto &regReadNode = static_cast<RegreadNode &>(expr);
43     if (regReadNode.GetRegIdx() == -kSregRetval0 || regReadNode.GetRegIdx() == -kSregRetval1) {
44         return &cgFunc.ProcessReturnReg(regReadNode.GetPrimType(), -(regReadNode.GetRegIdx()));
45     }
46     return cgFunc.SelectRegread(regReadNode);
47 }
48 
HandleConstVal(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)49 Operand *HandleConstVal(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
50 {
51     auto &constValNode = static_cast<ConstvalNode &>(expr);
52     MIRConst *mirConst = constValNode.GetConstVal();
53     DEBUG_ASSERT(mirConst != nullptr, "get constval of constvalnode failed");
54     if (mirConst->GetKind() == kConstInt) {
55         auto *mirIntConst = safe_cast<MIRIntConst>(mirConst);
56         return cgFunc.SelectIntConst(*mirIntConst);
57     } else if (mirConst->GetKind() == kConstFloatConst) {
58         auto *mirFloatConst = safe_cast<MIRFloatConst>(mirConst);
59         return cgFunc.SelectFloatConst(*mirFloatConst, parent);
60     } else if (mirConst->GetKind() == kConstDoubleConst) {
61         auto *mirDoubleConst = safe_cast<MIRDoubleConst>(mirConst);
62         return cgFunc.SelectDoubleConst(*mirDoubleConst, parent);
63     } else {
64         CHECK_FATAL(false, "NYI");
65     }
66     return nullptr;
67 }
68 
HandleConstStr(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)69 Operand *HandleConstStr(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
70 {
71     (void)parent;
72     auto &constStrNode = static_cast<ConststrNode &>(expr);
73 #if TARGAARCH64 || TARGRISCV64
74     if (CGOptions::IsArm64ilp32()) {
75         return cgFunc.SelectStrConst(*cgFunc.GetMemoryPool()->New<MIRStrConst>(
76             constStrNode.GetStrIdx(), *GlobalTables::GetTypeTable().GetTypeFromTyIdx(static_cast<TyIdx>(PTY_a32))));
77     } else {
78         return cgFunc.SelectStrConst(*cgFunc.GetMemoryPool()->New<MIRStrConst>(
79             constStrNode.GetStrIdx(), *GlobalTables::GetTypeTable().GetTypeFromTyIdx(static_cast<TyIdx>(PTY_a64))));
80     }
81 #else
82     return cgFunc.SelectStrConst(*cgFunc.GetMemoryPool()->New<MIRStrConst>(
83         constStrNode.GetStrIdx(), *GlobalTables::GetTypeTable().GetTypeFromTyIdx((TyIdx)PTY_a32)));
84 #endif
85 }
86 
HandleConstStr16(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)87 Operand *HandleConstStr16(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
88 {
89     (void)parent;
90     auto &constStr16Node = static_cast<Conststr16Node &>(expr);
91 #if TARGAARCH64 || TARGRISCV64
92     if (CGOptions::IsArm64ilp32()) {
93         return cgFunc.SelectStr16Const(*cgFunc.GetMemoryPool()->New<MIRStr16Const>(
94             constStr16Node.GetStrIdx(), *GlobalTables::GetTypeTable().GetTypeFromTyIdx(static_cast<TyIdx>(PTY_a32))));
95     } else {
96         return cgFunc.SelectStr16Const(*cgFunc.GetMemoryPool()->New<MIRStr16Const>(
97             constStr16Node.GetStrIdx(), *GlobalTables::GetTypeTable().GetTypeFromTyIdx(static_cast<TyIdx>(PTY_a64))));
98     }
99 #else
100     return cgFunc.SelectStr16Const(*cgFunc.GetMemoryPool()->New<MIRStr16Const>(
101         constStr16Node.GetStrIdx(), *GlobalTables::GetTypeTable().GetTypeFromTyIdx((TyIdx)PTY_a32)));
102 #endif
103 }
104 
HandleAdd(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)105 Operand *HandleAdd(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
106 {
107     if (Globals::GetInstance()->GetOptimLevel() >= CGOptions::kLevel2 && expr.Opnd(0)->GetOpCode() == OP_mul &&
108         !IsPrimitiveVector(expr.GetPrimType()) && !IsPrimitiveFloat(expr.GetPrimType()) &&
109         expr.Opnd(0)->Opnd(0)->GetOpCode() != OP_constval && expr.Opnd(0)->Opnd(1)->GetOpCode() != OP_constval) {
110         return cgFunc.SelectMadd(
111             static_cast<BinaryNode &>(expr), *cgFunc.HandleExpr(*expr.Opnd(0), *expr.Opnd(0)->Opnd(0)),
112             *cgFunc.HandleExpr(*expr.Opnd(0), *expr.Opnd(0)->Opnd(1)), *cgFunc.HandleExpr(expr, *expr.Opnd(1)), parent);
113     } else if (Globals::GetInstance()->GetOptimLevel() >= CGOptions::kLevel2 && expr.Opnd(1)->GetOpCode() == OP_mul &&
114                !IsPrimitiveVector(expr.GetPrimType()) && !IsPrimitiveFloat(expr.GetPrimType()) &&
115                expr.Opnd(1)->Opnd(0)->GetOpCode() != OP_constval && expr.Opnd(1)->Opnd(1)->GetOpCode() != OP_constval) {
116         return cgFunc.SelectMadd(
117             static_cast<BinaryNode &>(expr), *cgFunc.HandleExpr(*expr.Opnd(0), *expr.Opnd(1)->Opnd(0)),
118             *cgFunc.HandleExpr(*expr.Opnd(0), *expr.Opnd(1)->Opnd(1)), *cgFunc.HandleExpr(expr, *expr.Opnd(0)), parent);
119     } else {
120         return cgFunc.SelectAdd(static_cast<BinaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)),
121                                 *cgFunc.HandleExpr(expr, *expr.Opnd(1)), parent);
122     }
123 }
124 
HandleCGArrayElemAdd(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)125 Operand *HandleCGArrayElemAdd(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
126 {
127     return &cgFunc.SelectCGArrayElemAdd(static_cast<BinaryNode &>(expr), parent);
128 }
129 
IsConstantInVectorFromScalar(BaseNode * expr)130 BaseNode *IsConstantInVectorFromScalar(BaseNode *expr)
131 {
132     if (expr->op != OP_intrinsicop) {
133         return nullptr;
134     }
135     IntrinsicopNode *intrn = static_cast<IntrinsicopNode *>(expr);
136     switch (intrn->GetIntrinsic()) {
137         case INTRN_vector_from_scalar_v8u8:
138         case INTRN_vector_from_scalar_v8i8:
139         case INTRN_vector_from_scalar_v4u16:
140         case INTRN_vector_from_scalar_v4i16:
141         case INTRN_vector_from_scalar_v2u32:
142         case INTRN_vector_from_scalar_v2i32:
143         case INTRN_vector_from_scalar_v1u64:
144         case INTRN_vector_from_scalar_v1i64:
145         case INTRN_vector_from_scalar_v16u8:
146         case INTRN_vector_from_scalar_v16i8:
147         case INTRN_vector_from_scalar_v8u16:
148         case INTRN_vector_from_scalar_v8i16:
149         case INTRN_vector_from_scalar_v4u32:
150         case INTRN_vector_from_scalar_v4i32:
151         case INTRN_vector_from_scalar_v2u64:
152         case INTRN_vector_from_scalar_v2i64: {
153             if (intrn->Opnd(0) != nullptr && intrn->Opnd(0)->op == OP_constval) {
154                 return intrn->Opnd(0);
155             }
156             break;
157         }
158         default:
159             break;
160     }
161     return nullptr;
162 }
163 
HandleShift(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)164 Operand *HandleShift(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
165 {
166     BaseNode *cExpr = IsConstantInVectorFromScalar(expr.Opnd(1));
167     if (cExpr == nullptr) {
168         return cgFunc.SelectShift(static_cast<BinaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)),
169                                   *cgFunc.HandleExpr(expr, *expr.Opnd(1)), parent);
170     } else {
171         return cgFunc.SelectShift(static_cast<BinaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)),
172                                   *cgFunc.HandleExpr(*expr.Opnd(1), *cExpr), parent);
173     }
174 }
175 
HandleRor(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)176 Operand *HandleRor(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
177 {
178     return cgFunc.SelectRor(static_cast<BinaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)),
179                             *cgFunc.HandleExpr(expr, *expr.Opnd(1)), parent);
180 }
181 
HandleMpy(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)182 Operand *HandleMpy(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
183 {
184     return cgFunc.SelectMpy(static_cast<BinaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)),
185                             *cgFunc.HandleExpr(expr, *expr.Opnd(1)), parent);
186 }
187 
HandleDiv(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)188 Operand *HandleDiv(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
189 {
190     return cgFunc.SelectDiv(static_cast<BinaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)),
191                             *cgFunc.HandleExpr(expr, *expr.Opnd(1)), parent);
192 }
193 
HandleRem(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)194 Operand *HandleRem(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
195 {
196     return cgFunc.SelectRem(static_cast<BinaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)),
197                             *cgFunc.HandleExpr(expr, *expr.Opnd(1)), parent);
198 }
199 
HandleAddrof(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)200 Operand *HandleAddrof(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
201 {
202     auto &addrofNode = static_cast<AddrofNode &>(expr);
203     return cgFunc.SelectAddrof(addrofNode, parent, false);
204 }
205 
HandleAddrofoff(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)206 Operand *HandleAddrofoff(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
207 {
208     auto &addrofoffNode = static_cast<AddrofoffNode &>(expr);
209     return cgFunc.SelectAddrofoff(addrofoffNode, parent);
210 }
211 
HandleAddroffunc(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)212 Operand *HandleAddroffunc(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
213 {
214     auto &addroffuncNode = static_cast<AddroffuncNode &>(expr);
215     return &cgFunc.SelectAddrofFunc(addroffuncNode, parent);
216 }
217 
HandleAddrofLabel(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)218 Operand *HandleAddrofLabel(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
219 {
220     auto &addrofLabelNode = static_cast<AddroflabelNode &>(expr);
221     return &cgFunc.SelectAddrofLabel(addrofLabelNode, parent);
222 }
223 
HandleIread(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)224 Operand *HandleIread(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
225 {
226     auto &ireadNode = static_cast<IreadNode &>(expr);
227     return cgFunc.SelectIread(parent, ireadNode);
228 }
229 
HandleIreadoff(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)230 Operand *HandleIreadoff(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
231 {
232     auto &ireadNode = static_cast<IreadoffNode &>(expr);
233     return cgFunc.SelectIreadoff(parent, ireadNode);
234 }
235 
HandleIreadfpoff(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)236 Operand *HandleIreadfpoff(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
237 {
238     auto &ireadNode = static_cast<IreadFPoffNode &>(expr);
239     return cgFunc.SelectIreadfpoff(parent, ireadNode);
240 }
241 
HandleSub(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)242 Operand *HandleSub(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
243 {
244     return cgFunc.SelectSub(static_cast<BinaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)),
245                             *cgFunc.HandleExpr(expr, *expr.Opnd(1)), parent);
246 }
247 
HandleBand(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)248 Operand *HandleBand(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
249 {
250     return cgFunc.SelectBand(static_cast<BinaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)),
251                              *cgFunc.HandleExpr(expr, *expr.Opnd(1)), parent);
252 }
253 
HandleBior(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)254 Operand *HandleBior(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
255 {
256     return cgFunc.SelectBior(static_cast<BinaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)),
257                              *cgFunc.HandleExpr(expr, *expr.Opnd(1)), parent);
258 }
259 
HandleBxor(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)260 Operand *HandleBxor(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
261 {
262     return cgFunc.SelectBxor(static_cast<BinaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)),
263                              *cgFunc.HandleExpr(expr, *expr.Opnd(1)), parent);
264 }
265 
HandleAbs(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)266 Operand *HandleAbs(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
267 {
268     (void)parent;
269     return cgFunc.SelectAbs(static_cast<UnaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)));
270 }
271 
HandleBnot(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)272 Operand *HandleBnot(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
273 {
274     return cgFunc.SelectBnot(static_cast<UnaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)), parent);
275 }
276 
HandleExtractBits(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)277 Operand *HandleExtractBits(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
278 {
279     ExtractbitsNode &node = static_cast<ExtractbitsNode &>(expr);
280     uint8 bitOffset = node.GetBitsOffset();
281     uint8 bitSize = node.GetBitsSize();
282     if (!CGOptions::IsBigEndian() && (bitSize == k8BitSize || bitSize == k16BitSize) &&
283         GetPrimTypeBitSize(node.GetPrimType()) != k64BitSize &&
284         (bitOffset == 0 || bitOffset == k8BitSize || bitOffset == k16BitSize || bitOffset == k24BitSize) &&
285         expr.Opnd(0)->GetOpCode() == OP_iread && node.GetOpCode() == OP_extractbits) {
286         return cgFunc.SelectRegularBitFieldLoad(node, parent);
287     }
288     return cgFunc.SelectExtractbits(static_cast<ExtractbitsNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)),
289                                     parent);
290 }
291 
HandleDepositBits(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)292 Operand *HandleDepositBits(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
293 {
294     return cgFunc.SelectDepositBits(static_cast<DepositbitsNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)),
295                                     *cgFunc.HandleExpr(expr, *expr.Opnd(1)), parent);
296 }
297 
HandleLnot(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)298 Operand *HandleLnot(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
299 {
300     return cgFunc.SelectLnot(static_cast<UnaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)), parent);
301 }
302 
HandleLand(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)303 Operand *HandleLand(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
304 {
305     return cgFunc.SelectLand(static_cast<BinaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)),
306                              *cgFunc.HandleExpr(expr, *expr.Opnd(1)), parent);
307 }
308 
HandleLor(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)309 Operand *HandleLor(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
310 {
311     if (parent.IsCondBr()) {
312         return cgFunc.SelectLor(static_cast<BinaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)),
313                                 *cgFunc.HandleExpr(expr, *expr.Opnd(1)), parent, true);
314     } else {
315         return cgFunc.SelectLor(static_cast<BinaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)),
316                                 *cgFunc.HandleExpr(expr, *expr.Opnd(1)), parent);
317     }
318 }
319 
HandleMin(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)320 Operand *HandleMin(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
321 {
322     return cgFunc.SelectMin(static_cast<BinaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)),
323                             *cgFunc.HandleExpr(expr, *expr.Opnd(1)), parent);
324 }
325 
HandleMax(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)326 Operand *HandleMax(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
327 {
328     return cgFunc.SelectMax(static_cast<BinaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)),
329                             *cgFunc.HandleExpr(expr, *expr.Opnd(1)), parent);
330 }
331 
HandleNeg(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)332 Operand *HandleNeg(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
333 {
334     return cgFunc.SelectNeg(static_cast<UnaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)), parent);
335 }
336 
HandleRecip(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)337 Operand *HandleRecip(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
338 {
339     return cgFunc.SelectRecip(static_cast<UnaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)), parent);
340 }
341 
HandleSqrt(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)342 Operand *HandleSqrt(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
343 {
344     return cgFunc.SelectSqrt(static_cast<UnaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)), parent);
345 }
346 
HandleCeil(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)347 Operand *HandleCeil(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
348 {
349     return cgFunc.SelectCeil(static_cast<TypeCvtNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)), parent);
350 }
351 
HandleFloor(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)352 Operand *HandleFloor(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
353 {
354     return cgFunc.SelectFloor(static_cast<TypeCvtNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)), parent);
355 }
356 
HandleRetype(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)357 Operand *HandleRetype(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
358 {
359     (void)parent;
360     return cgFunc.SelectRetype(static_cast<TypeCvtNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)));
361 }
362 
HandleCvt(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)363 Operand *HandleCvt(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
364 {
365     return cgFunc.SelectCvt(parent, static_cast<TypeCvtNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)));
366 }
367 
HandleRound(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)368 Operand *HandleRound(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
369 {
370     return cgFunc.SelectRound(static_cast<TypeCvtNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)), parent);
371 }
372 
HandleTrunc(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)373 Operand *HandleTrunc(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
374 {
375     return cgFunc.SelectTrunc(static_cast<TypeCvtNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)), parent);
376 }
377 
HasCompare(const BaseNode * expr)378 static bool HasCompare(const BaseNode *expr)
379 {
380     if (kOpcodeInfo.IsCompare(expr->GetOpCode())) {
381         return true;
382     }
383     for (size_t i = 0; i < expr->GetNumOpnds(); ++i) {
384         if (HasCompare(expr->Opnd(i))) {
385             return true;
386         }
387     }
388     return false;
389 }
390 
HandleSelect(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)391 Operand *HandleSelect(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
392 {
393     /* 0,1,2 represent the first opnd and the second opnd and the third opnd of expr */
394     bool hasCompare = false;
395     if (HasCompare(expr.Opnd(kSecondOpnd)) || HasCompare(expr.Opnd(kThirdOpnd))) {
396         hasCompare = true;
397     }
398     Operand &trueOpnd = *cgFunc.HandleExpr(expr, *expr.Opnd(1));
399     Operand &falseOpnd = *cgFunc.HandleExpr(expr, *expr.Opnd(2));
400     Operand *cond = cgFunc.HandleExpr(expr, *expr.Opnd(0));
401     return cgFunc.SelectSelect(static_cast<TernaryNode &>(expr), *cond, trueOpnd, falseOpnd, parent, hasCompare);
402 }
403 
HandleCmp(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)404 Operand *HandleCmp(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
405 {
406     // fix opnd type before select insn
407     PrimType targetPtyp = parent.GetPrimType();
408     if (kOpcodeInfo.IsCompare(parent.GetOpCode())) {
409         targetPtyp = static_cast<const CompareNode &>(parent).GetOpndType();
410     } else if (kOpcodeInfo.IsTypeCvt(parent.GetOpCode())) {
411         targetPtyp = static_cast<const TypeCvtNode &>(parent).FromType();
412     }
413     if (IsPrimitiveInteger(targetPtyp) && targetPtyp != expr.GetPrimType()) {
414         expr.SetPrimType(targetPtyp);
415     }
416     return cgFunc.SelectCmpOp(static_cast<CompareNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)),
417                               *cgFunc.HandleExpr(expr, *expr.Opnd(1)), parent);
418 }
419 
HandleAlloca(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)420 Operand *HandleAlloca(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
421 {
422     (void)parent;
423     return cgFunc.SelectAlloca(static_cast<UnaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)));
424 }
425 
HandleMalloc(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)426 Operand *HandleMalloc(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
427 {
428     (void)parent;
429     return cgFunc.SelectMalloc(static_cast<UnaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)));
430 }
431 
HandleGCMalloc(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)432 Operand *HandleGCMalloc(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
433 {
434     (void)parent;
435     return cgFunc.SelectGCMalloc(static_cast<GCMallocNode &>(expr));
436 }
437 
HandleJarrayMalloc(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)438 Operand *HandleJarrayMalloc(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
439 {
440     (void)parent;
441     return cgFunc.SelectJarrayMalloc(static_cast<JarrayMallocNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)));
442 }
443 
444 /* Neon intrinsic handling */
HandleVectorAddLong(const BaseNode & expr,CGFunc & cgFunc,bool isLow)445 Operand *HandleVectorAddLong(const BaseNode &expr, CGFunc &cgFunc, bool isLow)
446 {
447     Operand *o1 = cgFunc.HandleExpr(expr, *expr.Opnd(0));
448     Operand *o2 = cgFunc.HandleExpr(expr, *expr.Opnd(1));
449     return cgFunc.SelectVectorAddLong(expr.GetPrimType(), o1, o2, expr.Opnd(0)->GetPrimType(), isLow);
450 }
451 
HandleVectorAddWiden(const BaseNode & expr,CGFunc & cgFunc,bool isLow)452 Operand *HandleVectorAddWiden(const BaseNode &expr, CGFunc &cgFunc, bool isLow)
453 {
454     Operand *o1 = cgFunc.HandleExpr(expr, *expr.Opnd(0));
455     Operand *o2 = cgFunc.HandleExpr(expr, *expr.Opnd(1));
456     return cgFunc.SelectVectorAddWiden(o1, expr.Opnd(0)->GetPrimType(), o2, expr.Opnd(1)->GetPrimType(), isLow);
457 }
458 
HandleVectorFromScalar(const IntrinsicopNode & intrnNode,CGFunc & cgFunc)459 Operand *HandleVectorFromScalar(const IntrinsicopNode &intrnNode, CGFunc &cgFunc)
460 {
461     return cgFunc.SelectVectorFromScalar(intrnNode.GetPrimType(), cgFunc.HandleExpr(intrnNode, *intrnNode.Opnd(0)),
462                                          intrnNode.Opnd(0)->GetPrimType());
463 }
464 
HandleVectorAbsSubL(const IntrinsicopNode & intrnNode,CGFunc & cgFunc,bool isLow)465 Operand *HandleVectorAbsSubL(const IntrinsicopNode &intrnNode, CGFunc &cgFunc, bool isLow)
466 {
467     Operand *opnd1 = cgFunc.HandleExpr(intrnNode, *intrnNode.Opnd(0)); /* vector operand 1 */
468     Operand *opnd2 = cgFunc.HandleExpr(intrnNode, *intrnNode.Opnd(1)); /* vector operand 2 */
469     return cgFunc.SelectVectorAbsSubL(intrnNode.GetPrimType(), opnd1, opnd2, intrnNode.Opnd(0)->GetPrimType(), isLow);
470 }
471 
HandleVectorMerge(const IntrinsicopNode & intrnNode,CGFunc & cgFunc)472 Operand *HandleVectorMerge(const IntrinsicopNode &intrnNode, CGFunc &cgFunc)
473 {
474     Operand *opnd1 = cgFunc.HandleExpr(intrnNode, *intrnNode.Opnd(0)); /* vector operand1 */
475     Operand *opnd2 = cgFunc.HandleExpr(intrnNode, *intrnNode.Opnd(1)); /* vector operand2 */
476     BaseNode *index = intrnNode.Opnd(2);                               /* index operand */
477     int32 iNum = 0;
478     if (index->GetOpCode() == OP_constval) {
479         MIRConst *mirConst = static_cast<ConstvalNode *>(index)->GetConstVal();
480         iNum = static_cast<int32>(safe_cast<MIRIntConst>(mirConst)->GetExtValue());
481         PrimType ty = intrnNode.Opnd(0)->GetPrimType();
482         if (!IsPrimitiveVector(ty)) {
483             iNum = 0;
484         } else {
485             iNum *= GetPrimTypeSize(ty) / GetVecLanes(ty); /* 64x2: 0-1 -> 0-8 */
486         }
487     } else { /* 32x4: 0-3 -> 0-12 */
488         CHECK_FATAL(0, "VectorMerge does not have const index");
489     }
490     return cgFunc.SelectVectorMerge(intrnNode.GetPrimType(), opnd1, opnd2, iNum);
491 }
492 
HandleVectorGetHigh(const IntrinsicopNode & intrnNode,CGFunc & cgFunc)493 Operand *HandleVectorGetHigh(const IntrinsicopNode &intrnNode, CGFunc &cgFunc)
494 {
495     PrimType rType = intrnNode.GetPrimType();                          /* result operand */
496     Operand *opnd1 = cgFunc.HandleExpr(intrnNode, *intrnNode.Opnd(0)); /* vector operand */
497     return cgFunc.SelectVectorDup(rType, opnd1, false);
498 }
499 
HandleVectorGetLow(const IntrinsicopNode & intrnNode,CGFunc & cgFunc)500 Operand *HandleVectorGetLow(const IntrinsicopNode &intrnNode, CGFunc &cgFunc)
501 {
502     PrimType rType = intrnNode.GetPrimType();                          /* result operand */
503     Operand *opnd1 = cgFunc.HandleExpr(intrnNode, *intrnNode.Opnd(0)); /* vector operand */
504     return cgFunc.SelectVectorDup(rType, opnd1, true);
505 }
506 
HandleVectorGetElement(const IntrinsicopNode & intrnNode,CGFunc & cgFunc)507 Operand *HandleVectorGetElement(const IntrinsicopNode &intrnNode, CGFunc &cgFunc)
508 {
509     Operand *opnd1 = cgFunc.HandleExpr(intrnNode, *intrnNode.Opnd(0)); /* vector operand */
510     PrimType o1Type = intrnNode.Opnd(0)->GetPrimType();
511     Operand *opndLane = cgFunc.HandleExpr(intrnNode, *intrnNode.Opnd(1));
512     int32 laneNum = -1;
513     if (opndLane->IsConstImmediate()) {
514         MIRConst *mirConst = static_cast<ConstvalNode *>(intrnNode.Opnd(1))->GetConstVal();
515         laneNum = static_cast<int32>(safe_cast<MIRIntConst>(mirConst)->GetExtValue());
516     } else {
517         CHECK_FATAL(0, "VectorGetElement does not have lane const");
518     }
519     return cgFunc.SelectVectorGetElement(intrnNode.GetPrimType(), opnd1, o1Type, laneNum);
520 }
521 
HandleVectorPairwiseAdd(const IntrinsicopNode & intrnNode,CGFunc & cgFunc)522 Operand *HandleVectorPairwiseAdd(const IntrinsicopNode &intrnNode, CGFunc &cgFunc)
523 {
524     Operand *src = cgFunc.HandleExpr(intrnNode, *intrnNode.Opnd(0)); /* vector src operand */
525     PrimType sType = intrnNode.Opnd(0)->GetPrimType();
526     return cgFunc.SelectVectorPairwiseAdd(intrnNode.GetPrimType(), src, sType);
527 }
528 
HandleVectorPairwiseAdalp(const IntrinsicopNode & intrnNode,CGFunc & cgFunc)529 Operand *HandleVectorPairwiseAdalp(const IntrinsicopNode &intrnNode, CGFunc &cgFunc)
530 {
531     BaseNode *arg1 = intrnNode.Opnd(0);
532     BaseNode *arg2 = intrnNode.Opnd(1);
533     Operand *src1 = cgFunc.HandleExpr(intrnNode, *arg1); /* vector src operand 1 */
534     Operand *src2 = cgFunc.HandleExpr(intrnNode, *arg2); /* vector src operand 2 */
535     return cgFunc.SelectVectorPairwiseAdalp(src1, arg1->GetPrimType(), src2, arg2->GetPrimType());
536 }
537 
HandleVectorSetElement(const IntrinsicopNode & intrnNode,CGFunc & cgFunc)538 Operand *HandleVectorSetElement(const IntrinsicopNode &intrnNode, CGFunc &cgFunc)
539 {
540     BaseNode *arg0 = intrnNode.Opnd(0); /* uint32_t operand */
541     Operand *opnd0 = cgFunc.HandleExpr(intrnNode, *arg0);
542     PrimType aType = arg0->GetPrimType();
543 
544     BaseNode *arg1 = intrnNode.Opnd(1); /* vector operand == result */
545     Operand *opnd1 = cgFunc.HandleExpr(intrnNode, *arg1);
546     PrimType vType = arg1->GetPrimType();
547 
548     BaseNode *arg2 = intrnNode.Opnd(2); /* lane const operand */
549     Operand *opnd2 = cgFunc.HandleExpr(intrnNode, *arg2);
550     int32 laneNum = -1;
551     if (opnd2->IsConstImmediate()) {
552         MIRConst *mirConst = static_cast<ConstvalNode *>(arg2)->GetConstVal();
553         laneNum = static_cast<int32>(safe_cast<MIRIntConst>(mirConst)->GetExtValue());
554     } else {
555         CHECK_FATAL(0, "VectorSetElement does not have lane const");
556     }
557     return cgFunc.SelectVectorSetElement(opnd0, aType, opnd1, vType, laneNum);
558 }
559 
HandleVectorReverse(const IntrinsicopNode & intrnNode,CGFunc & cgFunc,uint32 size)560 Operand *HandleVectorReverse(const IntrinsicopNode &intrnNode, CGFunc &cgFunc, uint32 size)
561 {
562     BaseNode *argExpr = intrnNode.Opnd(0); /* src operand */
563     Operand *src = cgFunc.HandleExpr(intrnNode, *argExpr);
564     MIRType *type = intrnNode.GetIntrinDesc().GetReturnType();
565     DEBUG_ASSERT(type != nullptr, "null ptr check");
566     auto revVecType = type->GetPrimType();
567     return cgFunc.SelectVectorReverse(revVecType, src, revVecType, size);
568 }
569 
HandleVectorShiftNarrow(const IntrinsicopNode & intrnNode,CGFunc & cgFunc,bool isLow)570 Operand *HandleVectorShiftNarrow(const IntrinsicopNode &intrnNode, CGFunc &cgFunc, bool isLow)
571 {
572     PrimType rType = intrnNode.GetPrimType();                          /* vector result */
573     Operand *opnd1 = cgFunc.HandleExpr(intrnNode, *intrnNode.Opnd(0)); /* vector operand */
574     Operand *opnd2 = cgFunc.HandleExpr(intrnNode, *intrnNode.Opnd(1)); /* shift const */
575     if (!opnd2->IsConstImmediate()) {
576         CHECK_FATAL(0, "VectorShiftNarrow does not have shift const");
577     }
578     return cgFunc.SelectVectorShiftRNarrow(rType, opnd1, intrnNode.Opnd(0)->GetPrimType(), opnd2, isLow);
579 }
580 
HandleVectorSubWiden(const IntrinsicopNode & intrnNode,CGFunc & cgFunc,bool isLow,bool isWide)581 Operand *HandleVectorSubWiden(const IntrinsicopNode &intrnNode, CGFunc &cgFunc, bool isLow, bool isWide)
582 {
583     PrimType resType = intrnNode.GetPrimType(); /* uint32_t result */
584     Operand *o1 = cgFunc.HandleExpr(intrnNode, *intrnNode.Opnd(0));
585     Operand *o2 = cgFunc.HandleExpr(intrnNode, *intrnNode.Opnd(1));
586     return cgFunc.SelectVectorSubWiden(resType, o1, intrnNode.Opnd(0)->GetPrimType(), o2,
587                                        intrnNode.Opnd(1)->GetPrimType(), isLow, isWide);
588 }
589 
HandleVectorSum(const IntrinsicopNode & intrnNode,CGFunc & cgFunc)590 Operand *HandleVectorSum(const IntrinsicopNode &intrnNode, CGFunc &cgFunc)
591 {
592     PrimType resType = intrnNode.GetPrimType();                        /* uint32_t result */
593     Operand *opnd1 = cgFunc.HandleExpr(intrnNode, *intrnNode.Opnd(0)); /* vector operand */
594     return cgFunc.SelectVectorSum(resType, opnd1, intrnNode.Opnd(0)->GetPrimType());
595 }
596 
HandleVectorTableLookup(const IntrinsicopNode & intrnNode,CGFunc & cgFunc)597 Operand *HandleVectorTableLookup(const IntrinsicopNode &intrnNode, CGFunc &cgFunc)
598 {
599     PrimType rType = intrnNode.GetPrimType();                          /* result operand */
600     Operand *opnd1 = cgFunc.HandleExpr(intrnNode, *intrnNode.Opnd(0)); /* vector operand 1 */
601     Operand *opnd2 = cgFunc.HandleExpr(intrnNode, *intrnNode.Opnd(1)); /* vector operand 2 */
602     return cgFunc.SelectVectorTableLookup(rType, opnd1, opnd2);
603 }
604 
HandleVectorMadd(const IntrinsicopNode & intrnNode,CGFunc & cgFunc)605 Operand *HandleVectorMadd(const IntrinsicopNode &intrnNode, CGFunc &cgFunc)
606 {
607     Operand *opnd1 = cgFunc.HandleExpr(intrnNode, *intrnNode.Opnd(0)); /* vector operand 1 */
608     Operand *opnd2 = cgFunc.HandleExpr(intrnNode, *intrnNode.Opnd(1)); /* vector operand 2 */
609     Operand *opnd3 = cgFunc.HandleExpr(intrnNode, *intrnNode.Opnd(2)); /* vector operand 3 */
610     PrimType oTyp1 = intrnNode.Opnd(0)->GetPrimType();
611     PrimType oTyp2 = intrnNode.Opnd(1)->GetPrimType();
612     PrimType oTyp3 = intrnNode.Opnd(2)->GetPrimType();
613     return cgFunc.SelectVectorMadd(opnd1, oTyp1, opnd2, oTyp2, opnd3, oTyp3);
614 }
615 
HandleVectorMull(const IntrinsicopNode & intrnNode,CGFunc & cgFunc,bool isLow)616 Operand *HandleVectorMull(const IntrinsicopNode &intrnNode, CGFunc &cgFunc, bool isLow)
617 {
618     PrimType rType = intrnNode.GetPrimType();                          /* result operand */
619     Operand *opnd1 = cgFunc.HandleExpr(intrnNode, *intrnNode.Opnd(0)); /* vector operand 1 */
620     Operand *opnd2 = cgFunc.HandleExpr(intrnNode, *intrnNode.Opnd(1)); /* vector operand 2 */
621     PrimType oTyp1 = intrnNode.Opnd(0)->GetPrimType();
622     PrimType oTyp2 = intrnNode.Opnd(1)->GetPrimType();
623     return cgFunc.SelectVectorMull(rType, opnd1, oTyp1, opnd2, oTyp2, isLow);
624 }
625 
HandleVectorNarrow(const IntrinsicopNode & intrnNode,CGFunc & cgFunc,bool isLow)626 Operand *HandleVectorNarrow(const IntrinsicopNode &intrnNode, CGFunc &cgFunc, bool isLow)
627 {
628     PrimType rType = intrnNode.GetPrimType();                          /* result operand */
629     Operand *opnd1 = cgFunc.HandleExpr(intrnNode, *intrnNode.Opnd(0)); /* vector opnd 1 */
630     if (isLow) {
631         return cgFunc.SelectVectorNarrow(rType, opnd1, intrnNode.Opnd(0)->GetPrimType());
632     } else {
633         Operand *opnd2 = cgFunc.HandleExpr(intrnNode, *intrnNode.Opnd(1)); /* vector opnd 2 */
634         return cgFunc.SelectVectorNarrow2(rType, opnd1, intrnNode.Opnd(0)->GetPrimType(), opnd2,
635                                           intrnNode.Opnd(1)->GetPrimType());
636     }
637 }
638 
HandleVectorWiden(const IntrinsicopNode & intrnNode,CGFunc & cgFunc,bool isLow)639 Operand *HandleVectorWiden(const IntrinsicopNode &intrnNode, CGFunc &cgFunc, bool isLow)
640 {
641     PrimType rType = intrnNode.GetPrimType();                          /* result operand */
642     Operand *opnd1 = cgFunc.HandleExpr(intrnNode, *intrnNode.Opnd(0)); /* vector opnd 1 */
643     return cgFunc.SelectVectorWiden(rType, opnd1, intrnNode.Opnd(0)->GetPrimType(), isLow);
644 }
645 
HandleIntrinOp(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)646 Operand *HandleIntrinOp(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
647 {
648     auto &intrinsicopNode = static_cast<IntrinsicopNode &>(expr);
649     switch (intrinsicopNode.GetIntrinsic()) {
650         case INTRN_MPL_READ_OVTABLE_ENTRY_LAZY: {
651             Operand *srcOpnd = cgFunc.HandleExpr(intrinsicopNode, *intrinsicopNode.Opnd(0));
652             return cgFunc.SelectLazyLoad(*srcOpnd, intrinsicopNode.GetPrimType());
653         }
654         case INTRN_MPL_READ_STATIC_OFFSET_TAB: {
655             auto addrOfNode = static_cast<AddrofNode *>(intrinsicopNode.Opnd(0));
656             MIRSymbol *st = cgFunc.GetMirModule().CurFunction()->GetLocalOrGlobalSymbol(addrOfNode->GetStIdx());
657             auto constNode = static_cast<ConstvalNode *>(intrinsicopNode.Opnd(1));
658             CHECK_FATAL(constNode != nullptr, "null ptr check");
659             auto mirIntConst = static_cast<MIRIntConst *>(constNode->GetConstVal());
660             return cgFunc.SelectLazyLoadStatic(*st, mirIntConst->GetExtValue(), intrinsicopNode.GetPrimType());
661         }
662         case INTRN_MPL_READ_ARRAYCLASS_CACHE_ENTRY: {
663             auto addrOfNode = static_cast<AddrofNode *>(intrinsicopNode.Opnd(0));
664             MIRSymbol *st = cgFunc.GetMirModule().CurFunction()->GetLocalOrGlobalSymbol(addrOfNode->GetStIdx());
665             auto constNode = static_cast<ConstvalNode *>(intrinsicopNode.Opnd(1));
666             CHECK_FATAL(constNode != nullptr, "null ptr check");
667             auto mirIntConst = static_cast<MIRIntConst *>(constNode->GetConstVal());
668             return cgFunc.SelectLoadArrayClassCache(*st, mirIntConst->GetExtValue(), intrinsicopNode.GetPrimType());
669         }
670         // double
671         case INTRN_C_sin:
672             return cgFunc.SelectIntrinsicOpWithOneParam(intrinsicopNode, "sin");
673         case INTRN_C_sinh:
674             return cgFunc.SelectIntrinsicOpWithOneParam(intrinsicopNode, "sinh");
675         case INTRN_C_asin:
676             return cgFunc.SelectIntrinsicOpWithOneParam(intrinsicopNode, "asin");
677         case INTRN_C_cos:
678             return cgFunc.SelectIntrinsicOpWithOneParam(intrinsicopNode, "cos");
679         case INTRN_C_cosh:
680             return cgFunc.SelectIntrinsicOpWithOneParam(intrinsicopNode, "cosh");
681         case INTRN_C_acos:
682             return cgFunc.SelectIntrinsicOpWithOneParam(intrinsicopNode, "acos");
683         case INTRN_C_atan:
684             return cgFunc.SelectIntrinsicOpWithOneParam(intrinsicopNode, "atan");
685         case INTRN_C_exp:
686             return cgFunc.SelectIntrinsicOpWithOneParam(intrinsicopNode, "exp");
687         case INTRN_C_log:
688             return cgFunc.SelectIntrinsicOpWithOneParam(intrinsicopNode, "log");
689         case INTRN_C_log10:
690             return cgFunc.SelectIntrinsicOpWithOneParam(intrinsicopNode, "log10");
691         // float
692         case INTRN_C_sinf:
693             return cgFunc.SelectIntrinsicOpWithOneParam(intrinsicopNode, "sinf");
694         case INTRN_C_sinhf:
695             return cgFunc.SelectIntrinsicOpWithOneParam(intrinsicopNode, "sinhf");
696         case INTRN_C_asinf:
697             return cgFunc.SelectIntrinsicOpWithOneParam(intrinsicopNode, "asinf");
698         case INTRN_C_cosf:
699             return cgFunc.SelectIntrinsicOpWithOneParam(intrinsicopNode, "cosf");
700         case INTRN_C_coshf:
701             return cgFunc.SelectIntrinsicOpWithOneParam(intrinsicopNode, "coshf");
702         case INTRN_C_acosf:
703             return cgFunc.SelectIntrinsicOpWithOneParam(intrinsicopNode, "acosf");
704         case INTRN_C_atanf:
705             return cgFunc.SelectIntrinsicOpWithOneParam(intrinsicopNode, "atanf");
706         case INTRN_C_expf:
707             return cgFunc.SelectIntrinsicOpWithOneParam(intrinsicopNode, "expf");
708         case INTRN_C_logf:
709             return cgFunc.SelectIntrinsicOpWithOneParam(intrinsicopNode, "logf");
710         case INTRN_C_log10f:
711             return cgFunc.SelectIntrinsicOpWithOneParam(intrinsicopNode, "log10f");
712         // int
713         case INTRN_C_ffs:
714             return cgFunc.SelectIntrinsicOpWithOneParam(intrinsicopNode, "ffs");
715         // libc mem* and str* functions as intrinsicops
716         case INTRN_C_memcmp:
717             return cgFunc.SelectIntrinsicOpWithNParams(intrinsicopNode, PTY_i32, "memcmp");
718         case INTRN_C_strlen:
719             return cgFunc.SelectIntrinsicOpWithNParams(intrinsicopNode, PTY_u64, "strlen");
720         case INTRN_C_strcmp:
721             return cgFunc.SelectIntrinsicOpWithNParams(intrinsicopNode, PTY_i32, "strcmp");
722         case INTRN_C_strncmp:
723             return cgFunc.SelectIntrinsicOpWithNParams(intrinsicopNode, PTY_i32, "strncmp");
724         case INTRN_C_strchr:
725             return cgFunc.SelectIntrinsicOpWithNParams(intrinsicopNode, PTY_a64, "strchr");
726         case INTRN_C_strrchr:
727             return cgFunc.SelectIntrinsicOpWithNParams(intrinsicopNode, PTY_a64, "strrchr");
728 
729         case INTRN_C_rev16_2:
730         case INTRN_C_rev_4:
731         case INTRN_C_rev_8:
732             return cgFunc.SelectBswap(intrinsicopNode, *cgFunc.HandleExpr(expr, *expr.Opnd(0)), parent);
733 
734         case INTRN_C_clz32:
735         case INTRN_C_clz64:
736             return cgFunc.SelectCclz(intrinsicopNode);
737         case INTRN_C_ctz32:
738         case INTRN_C_ctz64:
739             return cgFunc.SelectCctz(intrinsicopNode);
740         case INTRN_C_popcount32:
741         case INTRN_C_popcount64:
742             return cgFunc.SelectCpopcount(intrinsicopNode);
743         case INTRN_C_parity32:
744         case INTRN_C_parity64:
745             return cgFunc.SelectCparity(intrinsicopNode);
746         case INTRN_C_clrsb32:
747         case INTRN_C_clrsb64:
748             return cgFunc.SelectCclrsb(intrinsicopNode);
749         case INTRN_C_isaligned:
750             return cgFunc.SelectCisaligned(intrinsicopNode);
751         case INTRN_C_alignup:
752             return cgFunc.SelectCalignup(intrinsicopNode);
753         case INTRN_C_aligndown:
754             return cgFunc.SelectCaligndown(intrinsicopNode);
755         case INTRN_C___sync_add_and_fetch_1:
756         case INTRN_C___sync_add_and_fetch_2:
757         case INTRN_C___sync_add_and_fetch_4:
758         case INTRN_C___sync_add_and_fetch_8:
759             return cgFunc.SelectCSyncFetch(intrinsicopNode, OP_add, false);
760         case INTRN_C___sync_sub_and_fetch_1:
761         case INTRN_C___sync_sub_and_fetch_2:
762         case INTRN_C___sync_sub_and_fetch_4:
763         case INTRN_C___sync_sub_and_fetch_8:
764             return cgFunc.SelectCSyncFetch(intrinsicopNode, OP_sub, false);
765         case INTRN_C___sync_fetch_and_add_1:
766         case INTRN_C___sync_fetch_and_add_2:
767         case INTRN_C___sync_fetch_and_add_4:
768         case INTRN_C___sync_fetch_and_add_8:
769             return cgFunc.SelectCSyncFetch(intrinsicopNode, OP_add, true);
770         case INTRN_C___sync_fetch_and_sub_1:
771         case INTRN_C___sync_fetch_and_sub_2:
772         case INTRN_C___sync_fetch_and_sub_4:
773         case INTRN_C___sync_fetch_and_sub_8:
774             return cgFunc.SelectCSyncFetch(intrinsicopNode, OP_sub, true);
775         case INTRN_C___sync_bool_compare_and_swap_1:
776         case INTRN_C___sync_bool_compare_and_swap_2:
777         case INTRN_C___sync_bool_compare_and_swap_4:
778         case INTRN_C___sync_bool_compare_and_swap_8:
779             return cgFunc.SelectCSyncBoolCmpSwap(intrinsicopNode);
780         case INTRN_C___sync_val_compare_and_swap_1:
781         case INTRN_C___sync_val_compare_and_swap_2:
782         case INTRN_C___sync_val_compare_and_swap_4:
783         case INTRN_C___sync_val_compare_and_swap_8:
784             return cgFunc.SelectCSyncValCmpSwap(intrinsicopNode);
785         case INTRN_C___sync_lock_test_and_set_1:
786             return cgFunc.SelectCSyncLockTestSet(intrinsicopNode, PTY_i8);
787         case INTRN_C___sync_lock_test_and_set_2:
788             return cgFunc.SelectCSyncLockTestSet(intrinsicopNode, PTY_i16);
789         case INTRN_C___sync_lock_test_and_set_4:
790             return cgFunc.SelectCSyncLockTestSet(intrinsicopNode, PTY_i32);
791         case INTRN_C___sync_lock_test_and_set_8:
792             return cgFunc.SelectCSyncLockTestSet(intrinsicopNode, PTY_i64);
793         case INTRN_C___sync_fetch_and_and_1:
794         case INTRN_C___sync_fetch_and_and_2:
795         case INTRN_C___sync_fetch_and_and_4:
796         case INTRN_C___sync_fetch_and_and_8:
797             return cgFunc.SelectCSyncFetch(intrinsicopNode, OP_band, true);
798         case INTRN_C___sync_and_and_fetch_1:
799         case INTRN_C___sync_and_and_fetch_2:
800         case INTRN_C___sync_and_and_fetch_4:
801         case INTRN_C___sync_and_and_fetch_8:
802             return cgFunc.SelectCSyncFetch(intrinsicopNode, OP_band, false);
803         case INTRN_C___sync_fetch_and_or_1:
804         case INTRN_C___sync_fetch_and_or_2:
805         case INTRN_C___sync_fetch_and_or_4:
806         case INTRN_C___sync_fetch_and_or_8:
807             return cgFunc.SelectCSyncFetch(intrinsicopNode, OP_bior, true);
808         case INTRN_C___sync_or_and_fetch_1:
809         case INTRN_C___sync_or_and_fetch_2:
810         case INTRN_C___sync_or_and_fetch_4:
811         case INTRN_C___sync_or_and_fetch_8:
812             return cgFunc.SelectCSyncFetch(intrinsicopNode, OP_bior, false);
813         case INTRN_C___sync_fetch_and_xor_1:
814         case INTRN_C___sync_fetch_and_xor_2:
815         case INTRN_C___sync_fetch_and_xor_4:
816         case INTRN_C___sync_fetch_and_xor_8:
817             return cgFunc.SelectCSyncFetch(intrinsicopNode, OP_bxor, true);
818         case INTRN_C___sync_xor_and_fetch_1:
819         case INTRN_C___sync_xor_and_fetch_2:
820         case INTRN_C___sync_xor_and_fetch_4:
821         case INTRN_C___sync_xor_and_fetch_8:
822             return cgFunc.SelectCSyncFetch(intrinsicopNode, OP_bxor, false);
823         case INTRN_C___sync_synchronize:
824             return cgFunc.SelectCSyncSynchronize(intrinsicopNode);
825         case INTRN_C___atomic_load_n:
826             return cgFunc.SelectCAtomicLoadN(intrinsicopNode);
827         case INTRN_C___atomic_exchange_n:
828             return cgFunc.SelectCAtomicExchangeN(intrinsicopNode);
829         case INTRN_C__builtin_return_address:
830         case INTRN_C__builtin_extract_return_addr:
831             return cgFunc.SelectCReturnAddress(intrinsicopNode);
832 
833         case INTRN_vector_abs_v8i8:
834         case INTRN_vector_abs_v4i16:
835         case INTRN_vector_abs_v2i32:
836         case INTRN_vector_abs_v1i64:
837         case INTRN_vector_abs_v16i8:
838         case INTRN_vector_abs_v8i16:
839         case INTRN_vector_abs_v4i32:
840         case INTRN_vector_abs_v2i64:
841             return HandleAbs(parent, intrinsicopNode, cgFunc);
842 
843         case INTRN_vector_addl_low_v8i8:
844         case INTRN_vector_addl_low_v8u8:
845         case INTRN_vector_addl_low_v4i16:
846         case INTRN_vector_addl_low_v4u16:
847         case INTRN_vector_addl_low_v2i32:
848         case INTRN_vector_addl_low_v2u32:
849             return HandleVectorAddLong(intrinsicopNode, cgFunc, true);
850 
851         case INTRN_vector_addl_high_v8i8:
852         case INTRN_vector_addl_high_v8u8:
853         case INTRN_vector_addl_high_v4i16:
854         case INTRN_vector_addl_high_v4u16:
855         case INTRN_vector_addl_high_v2i32:
856         case INTRN_vector_addl_high_v2u32:
857             return HandleVectorAddLong(intrinsicopNode, cgFunc, false);
858 
859         case INTRN_vector_addw_low_v8i8:
860         case INTRN_vector_addw_low_v8u8:
861         case INTRN_vector_addw_low_v4i16:
862         case INTRN_vector_addw_low_v4u16:
863         case INTRN_vector_addw_low_v2i32:
864         case INTRN_vector_addw_low_v2u32:
865             return HandleVectorAddWiden(intrinsicopNode, cgFunc, true);
866 
867         case INTRN_vector_addw_high_v8i8:
868         case INTRN_vector_addw_high_v8u8:
869         case INTRN_vector_addw_high_v4i16:
870         case INTRN_vector_addw_high_v4u16:
871         case INTRN_vector_addw_high_v2i32:
872         case INTRN_vector_addw_high_v2u32:
873             return HandleVectorAddWiden(intrinsicopNode, cgFunc, false);
874 
875         case INTRN_vector_sum_v8u8:
876         case INTRN_vector_sum_v8i8:
877         case INTRN_vector_sum_v4u16:
878         case INTRN_vector_sum_v4i16:
879         case INTRN_vector_sum_v2u32:
880         case INTRN_vector_sum_v2i32:
881         case INTRN_vector_sum_v16u8:
882         case INTRN_vector_sum_v16i8:
883         case INTRN_vector_sum_v8u16:
884         case INTRN_vector_sum_v8i16:
885         case INTRN_vector_sum_v4u32:
886         case INTRN_vector_sum_v4i32:
887         case INTRN_vector_sum_v2u64:
888         case INTRN_vector_sum_v2i64:
889             return HandleVectorSum(intrinsicopNode, cgFunc);
890 
891         case INTRN_vector_from_scalar_v8u8:
892         case INTRN_vector_from_scalar_v8i8:
893         case INTRN_vector_from_scalar_v4u16:
894         case INTRN_vector_from_scalar_v4i16:
895         case INTRN_vector_from_scalar_v2u32:
896         case INTRN_vector_from_scalar_v2i32:
897         case INTRN_vector_from_scalar_v1u64:
898         case INTRN_vector_from_scalar_v1i64:
899         case INTRN_vector_from_scalar_v16u8:
900         case INTRN_vector_from_scalar_v16i8:
901         case INTRN_vector_from_scalar_v8u16:
902         case INTRN_vector_from_scalar_v8i16:
903         case INTRN_vector_from_scalar_v4u32:
904         case INTRN_vector_from_scalar_v4i32:
905         case INTRN_vector_from_scalar_v2u64:
906         case INTRN_vector_from_scalar_v2i64:
907             return HandleVectorFromScalar(intrinsicopNode, cgFunc);
908 
909         case INTRN_vector_labssub_low_v8u8:
910         case INTRN_vector_labssub_low_v8i8:
911         case INTRN_vector_labssub_low_v4u16:
912         case INTRN_vector_labssub_low_v4i16:
913         case INTRN_vector_labssub_low_v2u32:
914         case INTRN_vector_labssub_low_v2i32:
915             return HandleVectorAbsSubL(intrinsicopNode, cgFunc, true);
916 
917         case INTRN_vector_labssub_high_v8u8:
918         case INTRN_vector_labssub_high_v8i8:
919         case INTRN_vector_labssub_high_v4u16:
920         case INTRN_vector_labssub_high_v4i16:
921         case INTRN_vector_labssub_high_v2u32:
922         case INTRN_vector_labssub_high_v2i32:
923             return HandleVectorAbsSubL(intrinsicopNode, cgFunc, false);
924 
925         case INTRN_vector_merge_v8u8:
926         case INTRN_vector_merge_v8i8:
927         case INTRN_vector_merge_v4u16:
928         case INTRN_vector_merge_v4i16:
929         case INTRN_vector_merge_v2u32:
930         case INTRN_vector_merge_v2i32:
931         case INTRN_vector_merge_v1u64:
932         case INTRN_vector_merge_v1i64:
933         case INTRN_vector_merge_v16u8:
934         case INTRN_vector_merge_v16i8:
935         case INTRN_vector_merge_v8u16:
936         case INTRN_vector_merge_v8i16:
937         case INTRN_vector_merge_v4u32:
938         case INTRN_vector_merge_v4i32:
939         case INTRN_vector_merge_v2u64:
940         case INTRN_vector_merge_v2i64:
941             return HandleVectorMerge(intrinsicopNode, cgFunc);
942 
943         case INTRN_vector_set_element_v8u8:
944         case INTRN_vector_set_element_v8i8:
945         case INTRN_vector_set_element_v4u16:
946         case INTRN_vector_set_element_v4i16:
947         case INTRN_vector_set_element_v2u32:
948         case INTRN_vector_set_element_v2i32:
949         case INTRN_vector_set_element_v1u64:
950         case INTRN_vector_set_element_v1i64:
951         case INTRN_vector_set_element_v16u8:
952         case INTRN_vector_set_element_v16i8:
953         case INTRN_vector_set_element_v8u16:
954         case INTRN_vector_set_element_v8i16:
955         case INTRN_vector_set_element_v4u32:
956         case INTRN_vector_set_element_v4i32:
957         case INTRN_vector_set_element_v2u64:
958         case INTRN_vector_set_element_v2i64:
959             return HandleVectorSetElement(intrinsicopNode, cgFunc);
960 
961         case INTRN_vector_get_high_v16u8:
962         case INTRN_vector_get_high_v16i8:
963         case INTRN_vector_get_high_v8u16:
964         case INTRN_vector_get_high_v8i16:
965         case INTRN_vector_get_high_v4u32:
966         case INTRN_vector_get_high_v4i32:
967         case INTRN_vector_get_high_v2u64:
968         case INTRN_vector_get_high_v2i64:
969             return HandleVectorGetHigh(intrinsicopNode, cgFunc);
970 
971         case INTRN_vector_get_low_v16u8:
972         case INTRN_vector_get_low_v16i8:
973         case INTRN_vector_get_low_v8u16:
974         case INTRN_vector_get_low_v8i16:
975         case INTRN_vector_get_low_v4u32:
976         case INTRN_vector_get_low_v4i32:
977         case INTRN_vector_get_low_v2u64:
978         case INTRN_vector_get_low_v2i64:
979             return HandleVectorGetLow(intrinsicopNode, cgFunc);
980 
981         case INTRN_vector_get_element_v8u8:
982         case INTRN_vector_get_element_v8i8:
983         case INTRN_vector_get_element_v4u16:
984         case INTRN_vector_get_element_v4i16:
985         case INTRN_vector_get_element_v2u32:
986         case INTRN_vector_get_element_v2i32:
987         case INTRN_vector_get_element_v1u64:
988         case INTRN_vector_get_element_v1i64:
989         case INTRN_vector_get_element_v16u8:
990         case INTRN_vector_get_element_v16i8:
991         case INTRN_vector_get_element_v8u16:
992         case INTRN_vector_get_element_v8i16:
993         case INTRN_vector_get_element_v4u32:
994         case INTRN_vector_get_element_v4i32:
995         case INTRN_vector_get_element_v2u64:
996         case INTRN_vector_get_element_v2i64:
997             return HandleVectorGetElement(intrinsicopNode, cgFunc);
998 
999         case INTRN_vector_pairwise_adalp_v8i8:
1000         case INTRN_vector_pairwise_adalp_v4i16:
1001         case INTRN_vector_pairwise_adalp_v2i32:
1002         case INTRN_vector_pairwise_adalp_v8u8:
1003         case INTRN_vector_pairwise_adalp_v4u16:
1004         case INTRN_vector_pairwise_adalp_v2u32:
1005         case INTRN_vector_pairwise_adalp_v16i8:
1006         case INTRN_vector_pairwise_adalp_v8i16:
1007         case INTRN_vector_pairwise_adalp_v4i32:
1008         case INTRN_vector_pairwise_adalp_v16u8:
1009         case INTRN_vector_pairwise_adalp_v8u16:
1010         case INTRN_vector_pairwise_adalp_v4u32:
1011             return HandleVectorPairwiseAdalp(intrinsicopNode, cgFunc);
1012 
1013         case INTRN_vector_pairwise_add_v8u8:
1014         case INTRN_vector_pairwise_add_v8i8:
1015         case INTRN_vector_pairwise_add_v4u16:
1016         case INTRN_vector_pairwise_add_v4i16:
1017         case INTRN_vector_pairwise_add_v2u32:
1018         case INTRN_vector_pairwise_add_v2i32:
1019         case INTRN_vector_pairwise_add_v16u8:
1020         case INTRN_vector_pairwise_add_v16i8:
1021         case INTRN_vector_pairwise_add_v8u16:
1022         case INTRN_vector_pairwise_add_v8i16:
1023         case INTRN_vector_pairwise_add_v4u32:
1024         case INTRN_vector_pairwise_add_v4i32:
1025             return HandleVectorPairwiseAdd(intrinsicopNode, cgFunc);
1026 
1027         case INTRN_vector_madd_v8u8:
1028         case INTRN_vector_madd_v8i8:
1029         case INTRN_vector_madd_v4u16:
1030         case INTRN_vector_madd_v4i16:
1031         case INTRN_vector_madd_v2u32:
1032         case INTRN_vector_madd_v2i32:
1033             return HandleVectorMadd(intrinsicopNode, cgFunc);
1034 
1035         case INTRN_vector_mull_low_v8u8:
1036         case INTRN_vector_mull_low_v8i8:
1037         case INTRN_vector_mull_low_v4u16:
1038         case INTRN_vector_mull_low_v4i16:
1039         case INTRN_vector_mull_low_v2u32:
1040         case INTRN_vector_mull_low_v2i32:
1041             return HandleVectorMull(intrinsicopNode, cgFunc, true);
1042 
1043         case INTRN_vector_mull_high_v8u8:
1044         case INTRN_vector_mull_high_v8i8:
1045         case INTRN_vector_mull_high_v4u16:
1046         case INTRN_vector_mull_high_v4i16:
1047         case INTRN_vector_mull_high_v2u32:
1048         case INTRN_vector_mull_high_v2i32:
1049             return HandleVectorMull(intrinsicopNode, cgFunc, false);
1050 
1051         case INTRN_vector_narrow_low_v8u16:
1052         case INTRN_vector_narrow_low_v8i16:
1053         case INTRN_vector_narrow_low_v4u32:
1054         case INTRN_vector_narrow_low_v4i32:
1055         case INTRN_vector_narrow_low_v2u64:
1056         case INTRN_vector_narrow_low_v2i64:
1057             return HandleVectorNarrow(intrinsicopNode, cgFunc, true);
1058 
1059         case INTRN_vector_narrow_high_v8u16:
1060         case INTRN_vector_narrow_high_v8i16:
1061         case INTRN_vector_narrow_high_v4u32:
1062         case INTRN_vector_narrow_high_v4i32:
1063         case INTRN_vector_narrow_high_v2u64:
1064         case INTRN_vector_narrow_high_v2i64:
1065             return HandleVectorNarrow(intrinsicopNode, cgFunc, false);
1066 
1067         case INTRN_vector_reverse_v8u8:
1068         case INTRN_vector_reverse_v8i8:
1069         case INTRN_vector_reverse_v4u16:
1070         case INTRN_vector_reverse_v4i16:
1071         case INTRN_vector_reverse_v16u8:
1072         case INTRN_vector_reverse_v16i8:
1073         case INTRN_vector_reverse_v8u16:
1074         case INTRN_vector_reverse_v8i16:
1075             return HandleVectorReverse(intrinsicopNode, cgFunc, k32BitSize);
1076 
1077         case INTRN_vector_reverse16_v16u8:
1078         case INTRN_vector_reverse16_v16i8:
1079         case INTRN_vector_reverse16_v8u8:
1080         case INTRN_vector_reverse16_v8i8:
1081             return HandleVectorReverse(intrinsicopNode, cgFunc, k16BitSize);
1082 
1083         case INTRN_vector_reverse64_v16u8:
1084         case INTRN_vector_reverse64_v16i8:
1085         case INTRN_vector_reverse64_v8u8:
1086         case INTRN_vector_reverse64_v8i8:
1087         case INTRN_vector_reverse64_v8u16:
1088         case INTRN_vector_reverse64_v8i16:
1089         case INTRN_vector_reverse64_v4u16:
1090         case INTRN_vector_reverse64_v4i16:
1091         case INTRN_vector_reverse64_v4u32:
1092         case INTRN_vector_reverse64_v4i32:
1093         case INTRN_vector_reverse64_v2u32:
1094         case INTRN_vector_reverse64_v2i32:
1095             return HandleVectorReverse(intrinsicopNode, cgFunc, k64BitSize);
1096 
1097         case INTRN_vector_shr_narrow_low_v8u16:
1098         case INTRN_vector_shr_narrow_low_v8i16:
1099         case INTRN_vector_shr_narrow_low_v4u32:
1100         case INTRN_vector_shr_narrow_low_v4i32:
1101         case INTRN_vector_shr_narrow_low_v2u64:
1102         case INTRN_vector_shr_narrow_low_v2i64:
1103             return HandleVectorShiftNarrow(intrinsicopNode, cgFunc, true);
1104 
1105         case INTRN_vector_subl_low_v8i8:
1106         case INTRN_vector_subl_low_v8u8:
1107         case INTRN_vector_subl_low_v4i16:
1108         case INTRN_vector_subl_low_v4u16:
1109         case INTRN_vector_subl_low_v2i32:
1110         case INTRN_vector_subl_low_v2u32:
1111             return HandleVectorSubWiden(intrinsicopNode, cgFunc, true, false);
1112 
1113         case INTRN_vector_subl_high_v8i8:
1114         case INTRN_vector_subl_high_v8u8:
1115         case INTRN_vector_subl_high_v4i16:
1116         case INTRN_vector_subl_high_v4u16:
1117         case INTRN_vector_subl_high_v2i32:
1118         case INTRN_vector_subl_high_v2u32:
1119             return HandleVectorSubWiden(intrinsicopNode, cgFunc, false, false);
1120 
1121         case INTRN_vector_subw_low_v8i8:
1122         case INTRN_vector_subw_low_v8u8:
1123         case INTRN_vector_subw_low_v4i16:
1124         case INTRN_vector_subw_low_v4u16:
1125         case INTRN_vector_subw_low_v2i32:
1126         case INTRN_vector_subw_low_v2u32:
1127             return HandleVectorSubWiden(intrinsicopNode, cgFunc, true, true);
1128 
1129         case INTRN_vector_subw_high_v8i8:
1130         case INTRN_vector_subw_high_v8u8:
1131         case INTRN_vector_subw_high_v4i16:
1132         case INTRN_vector_subw_high_v4u16:
1133         case INTRN_vector_subw_high_v2i32:
1134         case INTRN_vector_subw_high_v2u32:
1135             return HandleVectorSubWiden(intrinsicopNode, cgFunc, false, true);
1136 
1137         case INTRN_vector_table_lookup_v8u8:
1138         case INTRN_vector_table_lookup_v8i8:
1139         case INTRN_vector_table_lookup_v16u8:
1140         case INTRN_vector_table_lookup_v16i8:
1141             return HandleVectorTableLookup(intrinsicopNode, cgFunc);
1142 
1143         case INTRN_vector_widen_low_v8u8:
1144         case INTRN_vector_widen_low_v8i8:
1145         case INTRN_vector_widen_low_v4u16:
1146         case INTRN_vector_widen_low_v4i16:
1147         case INTRN_vector_widen_low_v2u32:
1148         case INTRN_vector_widen_low_v2i32:
1149             return HandleVectorWiden(intrinsicopNode, cgFunc, true);
1150 
1151         case INTRN_vector_widen_high_v8u8:
1152         case INTRN_vector_widen_high_v8i8:
1153         case INTRN_vector_widen_high_v4u16:
1154         case INTRN_vector_widen_high_v4i16:
1155         case INTRN_vector_widen_high_v2u32:
1156         case INTRN_vector_widen_high_v2i32:
1157             return HandleVectorWiden(intrinsicopNode, cgFunc, false);
1158 
1159         default:
1160             DEBUG_ASSERT(false, "Should not reach here.");
1161             return nullptr;
1162     }
1163 }
1164 
1165 using HandleExprFactory = FunctionFactory<Opcode, maplebe::Operand *, const BaseNode &, BaseNode &, CGFunc &>;
InitHandleExprFactory()1166 void InitHandleExprFactory()
1167 {
1168     RegisterFactoryFunction<HandleExprFactory>(OP_dread, HandleDread);
1169     RegisterFactoryFunction<HandleExprFactory>(OP_regread, HandleRegread);
1170     RegisterFactoryFunction<HandleExprFactory>(OP_constval, HandleConstVal);
1171     RegisterFactoryFunction<HandleExprFactory>(OP_conststr, HandleConstStr);
1172     RegisterFactoryFunction<HandleExprFactory>(OP_conststr16, HandleConstStr16);
1173     RegisterFactoryFunction<HandleExprFactory>(OP_add, HandleAdd);
1174     RegisterFactoryFunction<HandleExprFactory>(OP_CG_array_elem_add, HandleCGArrayElemAdd);
1175     RegisterFactoryFunction<HandleExprFactory>(OP_ashr, HandleShift);
1176     RegisterFactoryFunction<HandleExprFactory>(OP_lshr, HandleShift);
1177     RegisterFactoryFunction<HandleExprFactory>(OP_shl, HandleShift);
1178     RegisterFactoryFunction<HandleExprFactory>(OP_ror, HandleRor);
1179     RegisterFactoryFunction<HandleExprFactory>(OP_mul, HandleMpy);
1180     RegisterFactoryFunction<HandleExprFactory>(OP_div, HandleDiv);
1181     RegisterFactoryFunction<HandleExprFactory>(OP_rem, HandleRem);
1182     RegisterFactoryFunction<HandleExprFactory>(OP_addrof, HandleAddrof);
1183     RegisterFactoryFunction<HandleExprFactory>(OP_addrofoff, HandleAddrofoff);
1184     RegisterFactoryFunction<HandleExprFactory>(OP_addroffunc, HandleAddroffunc);
1185     RegisterFactoryFunction<HandleExprFactory>(OP_addroflabel, HandleAddrofLabel);
1186     RegisterFactoryFunction<HandleExprFactory>(OP_iread, HandleIread);
1187     RegisterFactoryFunction<HandleExprFactory>(OP_ireadoff, HandleIreadoff);
1188     RegisterFactoryFunction<HandleExprFactory>(OP_ireadfpoff, HandleIreadfpoff);
1189     RegisterFactoryFunction<HandleExprFactory>(OP_sub, HandleSub);
1190     RegisterFactoryFunction<HandleExprFactory>(OP_band, HandleBand);
1191     RegisterFactoryFunction<HandleExprFactory>(OP_bior, HandleBior);
1192     RegisterFactoryFunction<HandleExprFactory>(OP_bxor, HandleBxor);
1193     RegisterFactoryFunction<HandleExprFactory>(OP_abs, HandleAbs);
1194     RegisterFactoryFunction<HandleExprFactory>(OP_bnot, HandleBnot);
1195     RegisterFactoryFunction<HandleExprFactory>(OP_sext, HandleExtractBits);
1196     RegisterFactoryFunction<HandleExprFactory>(OP_zext, HandleExtractBits);
1197     RegisterFactoryFunction<HandleExprFactory>(OP_extractbits, HandleExtractBits);
1198     RegisterFactoryFunction<HandleExprFactory>(OP_depositbits, HandleDepositBits);
1199     RegisterFactoryFunction<HandleExprFactory>(OP_lnot, HandleLnot);
1200     RegisterFactoryFunction<HandleExprFactory>(OP_land, HandleLand);
1201     RegisterFactoryFunction<HandleExprFactory>(OP_lior, HandleLor);
1202     RegisterFactoryFunction<HandleExprFactory>(OP_min, HandleMin);
1203     RegisterFactoryFunction<HandleExprFactory>(OP_max, HandleMax);
1204     RegisterFactoryFunction<HandleExprFactory>(OP_neg, HandleNeg);
1205     RegisterFactoryFunction<HandleExprFactory>(OP_recip, HandleRecip);
1206     RegisterFactoryFunction<HandleExprFactory>(OP_sqrt, HandleSqrt);
1207     RegisterFactoryFunction<HandleExprFactory>(OP_ceil, HandleCeil);
1208     RegisterFactoryFunction<HandleExprFactory>(OP_floor, HandleFloor);
1209     RegisterFactoryFunction<HandleExprFactory>(OP_retype, HandleRetype);
1210     RegisterFactoryFunction<HandleExprFactory>(OP_cvt, HandleCvt);
1211     RegisterFactoryFunction<HandleExprFactory>(OP_round, HandleRound);
1212     RegisterFactoryFunction<HandleExprFactory>(OP_trunc, HandleTrunc);
1213     RegisterFactoryFunction<HandleExprFactory>(OP_select, HandleSelect);
1214     RegisterFactoryFunction<HandleExprFactory>(OP_le, HandleCmp);
1215     RegisterFactoryFunction<HandleExprFactory>(OP_ge, HandleCmp);
1216     RegisterFactoryFunction<HandleExprFactory>(OP_gt, HandleCmp);
1217     RegisterFactoryFunction<HandleExprFactory>(OP_lt, HandleCmp);
1218     RegisterFactoryFunction<HandleExprFactory>(OP_ne, HandleCmp);
1219     RegisterFactoryFunction<HandleExprFactory>(OP_eq, HandleCmp);
1220     RegisterFactoryFunction<HandleExprFactory>(OP_cmp, HandleCmp);
1221     RegisterFactoryFunction<HandleExprFactory>(OP_cmpl, HandleCmp);
1222     RegisterFactoryFunction<HandleExprFactory>(OP_cmpg, HandleCmp);
1223     RegisterFactoryFunction<HandleExprFactory>(OP_alloca, HandleAlloca);
1224     RegisterFactoryFunction<HandleExprFactory>(OP_malloc, HandleMalloc);
1225     RegisterFactoryFunction<HandleExprFactory>(OP_gcmalloc, HandleGCMalloc);
1226     RegisterFactoryFunction<HandleExprFactory>(OP_gcpermalloc, HandleGCMalloc);
1227     RegisterFactoryFunction<HandleExprFactory>(OP_gcmallocjarray, HandleJarrayMalloc);
1228     RegisterFactoryFunction<HandleExprFactory>(OP_gcpermallocjarray, HandleJarrayMalloc);
1229     RegisterFactoryFunction<HandleExprFactory>(OP_intrinsicop, HandleIntrinOp);
1230 }
1231 
HandleLabel(StmtNode & stmt,CGFunc & cgFunc)1232 void HandleLabel(StmtNode &stmt, CGFunc &cgFunc)
1233 {
1234     DEBUG_ASSERT(stmt.GetOpCode() == OP_label, "error");
1235     auto &label = static_cast<LabelNode &>(stmt);
1236     BB *newBB = cgFunc.StartNewBBImpl(false, label);
1237     newBB->AddLabel(label.GetLabelIdx());
1238     if (newBB->GetId() == 1) {
1239         newBB->SetFrequency(kFreqBase);
1240     }
1241     cgFunc.SetLab2BBMap(newBB->GetLabIdx(), *newBB);
1242     cgFunc.SetCurBB(*newBB);
1243 }
1244 
HandleGoto(StmtNode & stmt,CGFunc & cgFunc)1245 void HandleGoto(StmtNode &stmt, CGFunc &cgFunc)
1246 {
1247     cgFunc.UpdateFrequency(stmt);
1248     auto &gotoNode = static_cast<GotoNode &>(stmt);
1249     cgFunc.SetCurBBKind(BB::kBBGoto);
1250     cgFunc.SelectGoto(gotoNode);
1251     cgFunc.SetCurBB(*cgFunc.StartNewBB(gotoNode));
1252     DEBUG_ASSERT(&stmt == &gotoNode, "stmt must be same as gotoNoe");
1253 
1254     if ((gotoNode.GetNext() != nullptr) && (gotoNode.GetNext()->GetOpCode() != OP_label)) {
1255         DEBUG_ASSERT(cgFunc.GetCurBB()->GetPrev()->GetLastStmt() == &stmt, "check the relation between BB and stmt");
1256     }
1257 }
1258 
HandleIgoto(StmtNode & stmt,CGFunc & cgFunc)1259 void HandleIgoto(StmtNode &stmt, CGFunc &cgFunc)
1260 {
1261     auto &igotoNode = static_cast<UnaryStmtNode &>(stmt);
1262     Operand *targetOpnd = cgFunc.HandleExpr(stmt, *igotoNode.Opnd(0));
1263     cgFunc.SelectIgoto(targetOpnd);
1264     cgFunc.SetCurBB(*cgFunc.StartNewBB(igotoNode));
1265 }
1266 
HandleCondbr(StmtNode & stmt,CGFunc & cgFunc)1267 void HandleCondbr(StmtNode &stmt, CGFunc &cgFunc)
1268 {
1269     cgFunc.UpdateFrequency(stmt);
1270     auto &condGotoNode = static_cast<CondGotoNode &>(stmt);
1271     BaseNode *condNode = condGotoNode.Opnd(0);
1272     DEBUG_ASSERT(condNode != nullptr, "expect first operand of cond br");
1273     Opcode condOp = condGotoNode.GetOpCode();
1274     if (condNode->GetOpCode() == OP_constval) {
1275         auto *constValNode = static_cast<ConstvalNode *>(condNode);
1276         if ((constValNode->GetConstVal()->IsZero() && (OP_brfalse == condOp)) ||
1277             (!constValNode->GetConstVal()->IsZero() && (OP_brtrue == condOp))) {
1278             auto *gotoStmt = cgFunc.GetMemoryPool()->New<GotoNode>(OP_goto);
1279             gotoStmt->SetOffset(condGotoNode.GetOffset());
1280             HandleGoto(*gotoStmt, cgFunc);
1281             auto *labelStmt = cgFunc.GetMemoryPool()->New<LabelNode>();
1282             labelStmt->SetLabelIdx(cgFunc.CreateLabel());
1283             HandleLabel(*labelStmt, cgFunc);
1284         }
1285         return;
1286     }
1287     cgFunc.SetCurBBKind(BB::kBBIf);
1288     /* if condNode is not a cmp node, cmp it with zero. */
1289     if (!kOpcodeInfo.IsCompare(condNode->GetOpCode())) {
1290         Operand *opnd0 = cgFunc.HandleExpr(condGotoNode, *condNode);
1291         PrimType primType = condNode->GetPrimType();
1292         Operand *zeroOpnd = nullptr;
1293         if (IsPrimitiveInteger(primType)) {
1294             zeroOpnd = &cgFunc.CreateImmOperand(primType, 0);
1295         } else {
1296             DEBUG_ASSERT(((PTY_f32 == primType) || (PTY_f64 == primType)),
1297                          "we don't support half-precision FP operands yet");
1298             zeroOpnd = &cgFunc.CreateImmOperand(primType, 0);
1299         }
1300         cgFunc.SelectCondGoto(condGotoNode, *opnd0, *zeroOpnd);
1301         cgFunc.SetCurBB(*cgFunc.StartNewBB(condGotoNode));
1302         return;
1303     }
1304     /*
1305      * Special case:
1306      * bgt (cmp (op0, op1), 0) ==>
1307      * bgt (op0, op1)
1308      * but skip the case cmp(op0, 0)
1309      */
1310     BaseNode *op0 = condNode->Opnd(0);
1311     DEBUG_ASSERT(op0 != nullptr, "get first opnd of a condNode failed");
1312     BaseNode *op1 = condNode->Opnd(1);
1313     DEBUG_ASSERT(op1 != nullptr, "get second opnd of a condNode failed");
1314     if ((op0->GetOpCode() == OP_cmp) && (op1->GetOpCode() == OP_constval)) {
1315         auto *constValNode = static_cast<ConstvalNode *>(op1);
1316         MIRConst *mirConst = constValNode->GetConstVal();
1317         auto *cmpNode = static_cast<CompareNode *>(op0);
1318         bool skip = false;
1319         if (cmpNode->Opnd(1)->GetOpCode() == OP_constval) {
1320             auto *constVal = static_cast<ConstvalNode *>(cmpNode->Opnd(1))->GetConstVal();
1321             if (constVal->IsZero()) {
1322                 skip = true;
1323             }
1324         }
1325         if (!skip && mirConst->IsZero()) {
1326             cgFunc.SelectCondSpecialCase1(condGotoNode, *op0);
1327             cgFunc.SetCurBB(*cgFunc.StartNewBB(condGotoNode));
1328             return;
1329         }
1330     }
1331     /*
1332      * Special case:
1333      * brfalse(ge (cmpg (op0, op1), 0) ==>
1334      * fcmp op1, op2
1335      * blo
1336      */
1337     if ((condGotoNode.GetOpCode() == OP_brfalse) && (condNode->GetOpCode() == OP_ge) && (op0->GetOpCode() == OP_cmpg) &&
1338         (op1->GetOpCode() == OP_constval)) {
1339         auto *constValNode = static_cast<ConstvalNode *>(op1);
1340         MIRConst *mirConst = constValNode->GetConstVal();
1341         if (mirConst->IsZero()) {
1342             cgFunc.SelectCondSpecialCase2(condGotoNode, *op0);
1343             cgFunc.SetCurBB(*cgFunc.StartNewBB(condGotoNode));
1344             return;
1345         }
1346     }
1347     Operand *opnd0 = cgFunc.HandleExpr(*condNode, *condNode->Opnd(0));
1348     Operand *opnd1 = cgFunc.HandleExpr(*condNode, *condNode->Opnd(1));
1349     cgFunc.SelectCondGoto(condGotoNode, *opnd0, *opnd1);
1350     cgFunc.SetCurBB(*cgFunc.StartNewBB(condGotoNode));
1351 }
1352 
HandleReturn(StmtNode & stmt,CGFunc & cgFunc)1353 void HandleReturn(StmtNode &stmt, CGFunc &cgFunc)
1354 {
1355     cgFunc.UpdateFrequency(stmt);
1356     auto &retNode = static_cast<NaryStmtNode &>(stmt);
1357     cgFunc.HandleRetCleanup(retNode);
1358     DEBUG_ASSERT(retNode.NumOpnds() <= 1, "NYI return nodes number > 1");
1359     Operand *opnd = nullptr;
1360     if (retNode.NumOpnds() != 0) {
1361         if (!cgFunc.GetFunction().StructReturnedInRegs()) {
1362             opnd = cgFunc.HandleExpr(retNode, *retNode.Opnd(0));
1363         } else {
1364             cgFunc.SelectReturnSendOfStructInRegs(retNode.Opnd(0));
1365         }
1366     }
1367     cgFunc.SelectReturn(opnd);
1368     cgFunc.SetCurBBKind(BB::kBBReturn);
1369     cgFunc.SetCurBB(*cgFunc.StartNewBB(retNode));
1370 }
1371 
HandleCall(StmtNode & stmt,CGFunc & cgFunc)1372 void HandleCall(StmtNode &stmt, CGFunc &cgFunc)
1373 {
1374     cgFunc.UpdateFrequency(stmt);
1375     auto &callNode = static_cast<CallNode &>(stmt);
1376     cgFunc.SelectCall(callNode);
1377     if (cgFunc.GetCurBB()->GetKind() != BB::kBBFallthru) {
1378         cgFunc.SetCurBB(*cgFunc.StartNewBB(callNode));
1379     }
1380 
1381     StmtNode *prevStmt = stmt.GetPrev();
1382     if (prevStmt == nullptr || prevStmt->GetOpCode() != OP_catch) {
1383         return;
1384     }
1385     if ((stmt.GetNext() != nullptr) && (stmt.GetNext()->GetOpCode() == OP_label)) {
1386         cgFunc.SetCurBB(*cgFunc.StartNewBBImpl(true, stmt));
1387     }
1388     cgFunc.HandleCatch();
1389 }
1390 
HandleICall(StmtNode & stmt,CGFunc & cgFunc)1391 void HandleICall(StmtNode &stmt, CGFunc &cgFunc)
1392 {
1393     cgFunc.UpdateFrequency(stmt);
1394     auto &icallNode = static_cast<IcallNode &>(stmt);
1395     cgFunc.GetCurBB()->SetHasCall();
1396     Operand *opnd0 = cgFunc.HandleExpr(stmt, *icallNode.GetNopndAt(0));
1397     cgFunc.SelectIcall(icallNode, *opnd0);
1398     if (cgFunc.GetCurBB()->GetKind() != BB::kBBFallthru) {
1399         cgFunc.SetCurBB(*cgFunc.StartNewBB(icallNode));
1400     }
1401 }
1402 
HandleIntrinCall(StmtNode & stmt,CGFunc & cgFunc)1403 void HandleIntrinCall(StmtNode &stmt, CGFunc &cgFunc)
1404 {
1405     auto &call = static_cast<IntrinsiccallNode &>(stmt);
1406     cgFunc.SelectIntrinCall(call);
1407 }
1408 
HandleDassign(StmtNode & stmt,CGFunc & cgFunc)1409 void HandleDassign(StmtNode &stmt, CGFunc &cgFunc)
1410 {
1411     auto &dassignNode = static_cast<DassignNode &>(stmt);
1412     DEBUG_ASSERT(dassignNode.GetOpCode() == OP_dassign, "expect dassign");
1413     BaseNode *rhs = dassignNode.GetRHS();
1414     DEBUG_ASSERT(rhs != nullptr, "get rhs of dassignNode failed");
1415     if (rhs->GetOpCode() == OP_malloc || rhs->GetOpCode() == OP_alloca) {
1416         UnaryStmtNode &uNode = static_cast<UnaryStmtNode &>(stmt);
1417         Operand *opnd0 = cgFunc.HandleExpr(dassignNode, *(uNode.Opnd()));
1418         cgFunc.SelectDassign(dassignNode, *opnd0);
1419         return;
1420     } else if (rhs->GetPrimType() == PTY_agg) {
1421         cgFunc.SelectAggDassign(dassignNode);
1422         return;
1423     }
1424     bool isSaveRetvalToLocal = false;
1425     if (rhs->GetOpCode() == OP_regread) {
1426         isSaveRetvalToLocal = (static_cast<RegreadNode *>(rhs)->GetRegIdx() == -kSregRetval0);
1427     }
1428     Operand *opnd0 = cgFunc.HandleExpr(dassignNode, *rhs);
1429     cgFunc.SelectDassign(dassignNode, *opnd0);
1430     if (isSaveRetvalToLocal) {
1431         cgFunc.GetCurBB()->GetLastInsn()->MarkAsSaveRetValToLocal();
1432     }
1433 }
1434 
HandleDassignoff(StmtNode & stmt,CGFunc & cgFunc)1435 void HandleDassignoff(StmtNode &stmt, CGFunc &cgFunc)
1436 {
1437     auto &dassignoffNode = static_cast<DassignoffNode &>(stmt);
1438     BaseNode *rhs = dassignoffNode.GetRHS();
1439     CHECK_FATAL(rhs->GetOpCode() == OP_constval, "dassignoffNode without constval");
1440     Operand *opnd0 = cgFunc.HandleExpr(dassignoffNode, *rhs);
1441     cgFunc.SelectDassignoff(dassignoffNode, *opnd0);
1442 }
1443 
HandleRegassign(StmtNode & stmt,CGFunc & cgFunc)1444 void HandleRegassign(StmtNode &stmt, CGFunc &cgFunc)
1445 {
1446     DEBUG_ASSERT(stmt.GetOpCode() == OP_regassign, "expect regAssign");
1447     auto &regAssignNode = static_cast<RegassignNode &>(stmt);
1448     bool isSaveRetvalToLocal = false;
1449     BaseNode *operand = regAssignNode.Opnd(0);
1450     DEBUG_ASSERT(operand != nullptr, "get operand of regassignNode failed");
1451     if (operand->GetOpCode() == OP_regread) {
1452         isSaveRetvalToLocal = (static_cast<RegreadNode *>(operand)->GetRegIdx() == -kSregRetval0);
1453     }
1454     Operand *opnd0 = cgFunc.HandleExpr(regAssignNode, *operand);
1455     cgFunc.SelectRegassign(regAssignNode, *opnd0);
1456     if (isSaveRetvalToLocal) {
1457         cgFunc.GetCurBB()->GetLastInsn()->MarkAsSaveRetValToLocal();
1458     }
1459 }
1460 
HandleIassign(StmtNode & stmt,CGFunc & cgFunc)1461 void HandleIassign(StmtNode &stmt, CGFunc &cgFunc)
1462 {
1463     DEBUG_ASSERT(stmt.GetOpCode() == OP_iassign, "expect stmt");
1464     auto &iassignNode = static_cast<IassignNode &>(stmt);
1465     if ((iassignNode.GetRHS() != nullptr) && iassignNode.GetRHS()->GetPrimType() != PTY_agg) {
1466         cgFunc.SelectIassign(iassignNode);
1467     } else {
1468         BaseNode *addrNode = iassignNode.Opnd(0);
1469         if (addrNode == nullptr) {
1470             return;
1471         }
1472         cgFunc.SelectAggIassign(iassignNode, *cgFunc.HandleExpr(stmt, *addrNode));
1473     }
1474 }
1475 
HandleIassignoff(StmtNode & stmt,CGFunc & cgFunc)1476 void HandleIassignoff(StmtNode &stmt, CGFunc &cgFunc)
1477 {
1478     DEBUG_ASSERT(stmt.GetOpCode() == OP_iassignoff, "expect iassignoff");
1479     auto &iassignoffNode = static_cast<IassignoffNode &>(stmt);
1480     cgFunc.SelectIassignoff(iassignoffNode);
1481 }
1482 
HandleIassignfpoff(StmtNode & stmt,CGFunc & cgFunc)1483 void HandleIassignfpoff(StmtNode &stmt, CGFunc &cgFunc)
1484 {
1485     DEBUG_ASSERT(stmt.GetOpCode() == OP_iassignfpoff, "expect iassignfpoff");
1486     auto &iassignfpoffNode = static_cast<IassignFPoffNode &>(stmt);
1487     cgFunc.SelectIassignfpoff(iassignfpoffNode, *cgFunc.HandleExpr(stmt, *stmt.Opnd(0)));
1488 }
1489 
HandleIassignspoff(StmtNode & stmt,CGFunc & cgFunc)1490 void HandleIassignspoff(StmtNode &stmt, CGFunc &cgFunc)
1491 {
1492     DEBUG_ASSERT(stmt.GetOpCode() == OP_iassignspoff, "expect iassignspoff");
1493     auto &baseNode = static_cast<IassignFPoffNode &>(stmt); /* same as FP */
1494     BaseNode *rhs = baseNode.GetRHS();
1495     DEBUG_ASSERT(rhs != nullptr, "get rhs of iassignspoffNode failed");
1496     Operand *opnd0 = cgFunc.HandleExpr(baseNode, *rhs);
1497     cgFunc.SelectIassignspoff(baseNode.GetPrimType(), baseNode.GetOffset(), *opnd0);
1498 }
1499 
HandleBlkassignoff(StmtNode & stmt,CGFunc & cgFunc)1500 void HandleBlkassignoff(StmtNode &stmt, CGFunc &cgFunc)
1501 {
1502     DEBUG_ASSERT(stmt.GetOpCode() == OP_blkassignoff, "expect blkassignoff");
1503     auto &baseNode = static_cast<BlkassignoffNode &>(stmt);
1504     Operand *src = cgFunc.HandleExpr(baseNode, *baseNode.Opnd(1));
1505     cgFunc.SelectBlkassignoff(baseNode, src);
1506 }
1507 
HandleEval(const StmtNode & stmt,CGFunc & cgFunc)1508 void HandleEval(const StmtNode &stmt, CGFunc &cgFunc)
1509 {
1510     (void)cgFunc.HandleExpr(stmt, *static_cast<const UnaryStmtNode &>(stmt).Opnd(0));
1511 }
1512 
HandleRangeGoto(StmtNode & stmt,CGFunc & cgFunc)1513 void HandleRangeGoto(StmtNode &stmt, CGFunc &cgFunc)
1514 {
1515     cgFunc.UpdateFrequency(stmt);
1516     auto &rangeGotoNode = static_cast<RangeGotoNode &>(stmt);
1517     cgFunc.SetCurBBKind(BB::kBBRangeGoto);
1518     cgFunc.SelectRangeGoto(rangeGotoNode, *cgFunc.HandleExpr(rangeGotoNode, *rangeGotoNode.Opnd(0)));
1519     cgFunc.SetCurBB(*cgFunc.StartNewBB(rangeGotoNode));
1520 }
1521 
HandleMembar(StmtNode & stmt,CGFunc & cgFunc)1522 void HandleMembar(StmtNode &stmt, CGFunc &cgFunc)
1523 {
1524     cgFunc.SelectMembar(stmt);
1525     if (stmt.GetOpCode() != OP_membarrelease) {
1526         return;
1527     }
1528 #if TARGAARCH64 || TARGRISCV64
1529     if (CGOptions::UseBarriersForVolatile()) {
1530         return;
1531     }
1532 #endif
1533     StmtNode *secondStmt = stmt.GetRealNext();
1534     if (secondStmt == nullptr || ((secondStmt->GetOpCode() != OP_iassign) && (secondStmt->GetOpCode() != OP_dassign))) {
1535         return;
1536     }
1537     StmtNode *thirdStmt = secondStmt->GetRealNext();
1538     if (thirdStmt == nullptr || thirdStmt->GetOpCode() != OP_membarstoreload) {
1539         return;
1540     }
1541     cgFunc.SetVolStore(true);
1542     cgFunc.SetVolReleaseInsn(cgFunc.GetCurBB()->GetLastInsn());
1543 }
1544 
HandleComment(StmtNode & stmt,CGFunc & cgFunc)1545 void HandleComment(StmtNode &stmt, CGFunc &cgFunc)
1546 {
1547     if (cgFunc.GetCG()->GenerateVerboseAsm() || cgFunc.GetCG()->GenerateVerboseCG()) {
1548         cgFunc.SelectComment(static_cast<CommentNode &>(stmt));
1549     }
1550 }
1551 
HandleCatchOp(const StmtNode & stmt,const CGFunc & cgFunc)1552 void HandleCatchOp(const StmtNode &stmt, const CGFunc &cgFunc)
1553 {
1554     (void)stmt;
1555     (void)cgFunc;
1556     DEBUG_ASSERT(stmt.GetNext()->GetOpCode() == OP_call, "The next statement of OP_catch should be OP_call.");
1557 }
1558 
HandleAssertNull(StmtNode & stmt,CGFunc & cgFunc)1559 void HandleAssertNull(StmtNode &stmt, CGFunc &cgFunc)
1560 {
1561     auto &cgAssertNode = static_cast<UnaryStmtNode &>(stmt);
1562     cgFunc.SelectAssertNull(cgAssertNode);
1563 }
1564 
HandleAbort(const StmtNode & stmt,CGFunc & cgFunc)1565 void HandleAbort(const StmtNode &stmt, CGFunc &cgFunc)
1566 {
1567     (void)stmt;
1568     cgFunc.SelectAbort();
1569 }
1570 
HandleAsm(StmtNode & stmt,CGFunc & cgFunc)1571 void HandleAsm(StmtNode &stmt, CGFunc &cgFunc)
1572 {
1573     cgFunc.SelectAsm(static_cast<AsmNode &>(stmt));
1574 }
1575 
1576 using HandleStmtFactory = FunctionFactory<Opcode, void, StmtNode &, CGFunc &>;
InitHandleStmtFactory()1577 void InitHandleStmtFactory()
1578 {
1579     RegisterFactoryFunction<HandleStmtFactory>(OP_label, HandleLabel);
1580     RegisterFactoryFunction<HandleStmtFactory>(OP_goto, HandleGoto);
1581     RegisterFactoryFunction<HandleStmtFactory>(OP_igoto, HandleIgoto);
1582     RegisterFactoryFunction<HandleStmtFactory>(OP_brfalse, HandleCondbr);
1583     RegisterFactoryFunction<HandleStmtFactory>(OP_brtrue, HandleCondbr);
1584     RegisterFactoryFunction<HandleStmtFactory>(OP_return, HandleReturn);
1585     RegisterFactoryFunction<HandleStmtFactory>(OP_call, HandleCall);
1586     RegisterFactoryFunction<HandleStmtFactory>(OP_icall, HandleICall);
1587     RegisterFactoryFunction<HandleStmtFactory>(OP_icallproto, HandleICall);
1588     RegisterFactoryFunction<HandleStmtFactory>(OP_intrinsiccall, HandleIntrinCall);
1589     RegisterFactoryFunction<HandleStmtFactory>(OP_intrinsiccallassigned, HandleIntrinCall);
1590     RegisterFactoryFunction<HandleStmtFactory>(OP_intrinsiccallwithtype, HandleIntrinCall);
1591     RegisterFactoryFunction<HandleStmtFactory>(OP_intrinsiccallwithtypeassigned, HandleIntrinCall);
1592     RegisterFactoryFunction<HandleStmtFactory>(OP_dassign, HandleDassign);
1593     RegisterFactoryFunction<HandleStmtFactory>(OP_dassignoff, HandleDassignoff);
1594     RegisterFactoryFunction<HandleStmtFactory>(OP_regassign, HandleRegassign);
1595     RegisterFactoryFunction<HandleStmtFactory>(OP_iassign, HandleIassign);
1596     RegisterFactoryFunction<HandleStmtFactory>(OP_iassignoff, HandleIassignoff);
1597     RegisterFactoryFunction<HandleStmtFactory>(OP_iassignfpoff, HandleIassignfpoff);
1598     RegisterFactoryFunction<HandleStmtFactory>(OP_iassignspoff, HandleIassignspoff);
1599     RegisterFactoryFunction<HandleStmtFactory>(OP_blkassignoff, HandleBlkassignoff);
1600     RegisterFactoryFunction<HandleStmtFactory>(OP_eval, HandleEval);
1601     RegisterFactoryFunction<HandleStmtFactory>(OP_rangegoto, HandleRangeGoto);
1602     RegisterFactoryFunction<HandleStmtFactory>(OP_membarrelease, HandleMembar);
1603     RegisterFactoryFunction<HandleStmtFactory>(OP_membaracquire, HandleMembar);
1604     RegisterFactoryFunction<HandleStmtFactory>(OP_membarstoreload, HandleMembar);
1605     RegisterFactoryFunction<HandleStmtFactory>(OP_membarstorestore, HandleMembar);
1606     RegisterFactoryFunction<HandleStmtFactory>(OP_comment, HandleComment);
1607     RegisterFactoryFunction<HandleStmtFactory>(OP_catch, HandleCatchOp);
1608     RegisterFactoryFunction<HandleStmtFactory>(OP_abort, HandleAbort);
1609     RegisterFactoryFunction<HandleStmtFactory>(OP_assertnonnull, HandleAssertNull);
1610     RegisterFactoryFunction<HandleStmtFactory>(OP_callassertnonnull, HandleAssertNull);
1611     RegisterFactoryFunction<HandleStmtFactory>(OP_assignassertnonnull, HandleAssertNull);
1612     RegisterFactoryFunction<HandleStmtFactory>(OP_returnassertnonnull, HandleAssertNull);
1613     RegisterFactoryFunction<HandleStmtFactory>(OP_asm, HandleAsm);
1614 }
1615 
CGFunc(MIRModule & mod,CG & cg,MIRFunction & mirFunc,BECommon & beCommon,MemPool & memPool,StackMemPool & stackMp,MapleAllocator & allocator,uint32 funcId)1616 CGFunc::CGFunc(MIRModule &mod, CG &cg, MIRFunction &mirFunc, BECommon &beCommon, MemPool &memPool,
1617                StackMemPool &stackMp, MapleAllocator &allocator, uint32 funcId)
1618     : vRegTable(allocator.Adapter()),
1619       bbVec(allocator.Adapter()),
1620       vRegOperandTable(allocator.Adapter()),
1621       referenceVirtualRegs(allocator.Adapter()),
1622       referenceStackSlots(allocator.Adapter()),
1623       pregIdx2Opnd(mirFunc.GetPregTab()->Size(), nullptr, allocator.Adapter()),
1624       pRegSpillMemOperands(allocator.Adapter()),
1625       spillRegMemOperands(allocator.Adapter()),
1626       reuseSpillLocMem(allocator.Adapter()),
1627       labelMap(std::less<LabelIdx>(), allocator.Adapter()),
1628       vregsToPregsMap(std::less<regno_t>(), allocator.Adapter()),
1629       stackMapInsns(allocator.Adapter()),
1630       hasVLAOrAlloca(mirFunc.HasVlaOrAlloca()),
1631       dbgCallFrameLocations(allocator.Adapter()),
1632       cg(&cg),
1633       mirModule(mod),
1634       memPool(&memPool),
1635       stackMp(stackMp),
1636       func(mirFunc),
1637       exitBBVec(allocator.Adapter()),
1638       extendSet(allocator.Adapter()),
1639       lab2BBMap(allocator.Adapter()),
1640       beCommon(beCommon),
1641       funcScopeAllocator(&allocator),
1642       emitStVec(allocator.Adapter()),
1643       switchLabelCnt(allocator.Adapter()),
1644 #if TARGARM32
1645       sortedBBs(allocator.Adapter()),
1646       lrVec(allocator.Adapter()),
1647 #endif /* TARGARM32 */
1648       loops(allocator.Adapter()),
1649       lmbcParamVec(allocator.Adapter()),
1650       shortFuncName(cg.ExtractFuncName(mirFunc.GetName()) + "." + std::to_string(funcId), &memPool)
1651 {
1652     mirModule.SetCurFunction(&func);
1653     dummyBB = CreateNewBB();
1654     vRegCount = firstMapleIrVRegNO + func.GetPregTab()->Size();
1655     firstNonPregVRegNO = vRegCount;
1656     /* maximum register count initial be increased by 1024 */
1657     maxRegCount = vRegCount + 1024;
1658 
1659     insnBuilder = memPool.New<InsnBuilder>(memPool);
1660     opndBuilder = memPool.New<OperandBuilder>(memPool, func.GetPregTab()->Size());
1661 
1662     vRegTable.resize(maxRegCount);
1663     /* func.GetPregTab()->_preg_table[0] is nullptr, so skip it */
1664     DEBUG_ASSERT(func.GetPregTab()->PregFromPregIdx(0) == nullptr, "PregFromPregIdx(0) must be nullptr");
1665     for (size_t i = 1; i < func.GetPregTab()->Size(); ++i) {
1666         PrimType primType = func.GetPregTab()->PregFromPregIdx(i)->GetPrimType();
1667         uint32 byteLen = GetPrimTypeSize(primType);
1668         if (byteLen < k4ByteSize) {
1669             byteLen = k4ByteSize;
1670         }
1671         if (primType == PTY_u128 || primType == PTY_i128) {
1672             byteLen = k8ByteSize;
1673         }
1674         new (&GetVirtualRegNodeFromPseudoRegIdx(i)) VirtualRegNode(GetRegTyFromPrimTy(primType), byteLen);
1675     }
1676     firstCGGenLabelIdx = func.GetLabelTab()->GetLabelTableSize();
1677     lSymSize = 0;
1678     if (func.GetSymTab()) {
1679         lSymSize = func.GetSymTab()->GetSymbolTableSize();
1680     }
1681     callingConventionKind = CCImpl::GetCallConvKind(mirFunc);
1682 }
1683 
~CGFunc()1684 CGFunc::~CGFunc()
1685 {
1686     mirModule.SetCurFunction(nullptr);
1687 }
1688 
HandleExpr(const BaseNode & parent,BaseNode & expr)1689 Operand *CGFunc::HandleExpr(const BaseNode &parent, BaseNode &expr)
1690 {
1691     auto function = CreateProductFunction<HandleExprFactory>(expr.GetOpCode());
1692     CHECK_FATAL(function != nullptr, "unsupported opCode in HandleExpr()");
1693     return function(parent, expr, *this);
1694 }
1695 
HandleFirstStmt()1696 StmtNode *CGFunc::HandleFirstStmt()
1697 {
1698     BlockNode *block = func.GetBody();
1699 
1700     DEBUG_ASSERT(block != nullptr, "get func body block failed in CGFunc::GenerateInstruction");
1701     StmtNode *stmt = block->GetFirst();
1702     if (stmt == nullptr) {
1703         return nullptr;
1704     }
1705     bool withFreqInfo = func.HasFreqMap() && !func.GetLastFreqMap().empty();
1706     if (withFreqInfo) {
1707         frequency = kFreqBase;
1708     }
1709     DEBUG_ASSERT(stmt->GetOpCode() == OP_label, "The first statement should be a label");
1710     HandleLabel(*stmt, *this);
1711     firstBB = curBB;
1712     stmt = stmt->GetNext();
1713     if (stmt == nullptr) {
1714         return nullptr;
1715     }
1716     curBB = StartNewBBImpl(false, *stmt);
1717     curBB->SetFrequency(frequency);
1718     if (JAVALANG) {
1719         HandleRCCall(true);
1720     }
1721     return stmt;
1722 }
1723 
CheckSkipMembarOp(const StmtNode & stmt)1724 bool CGFunc::CheckSkipMembarOp(const StmtNode &stmt)
1725 {
1726     StmtNode *nextStmt = stmt.GetRealNext();
1727     if (nextStmt == nullptr) {
1728         return false;
1729     }
1730 
1731     Opcode opCode = stmt.GetOpCode();
1732     if (((opCode == OP_membaracquire) || (opCode == OP_membarrelease)) && (nextStmt->GetOpCode() == stmt.GetOpCode())) {
1733         return true;
1734     }
1735     if ((opCode == OP_membarstorestore) && (nextStmt->GetOpCode() == OP_membarrelease)) {
1736         return true;
1737     }
1738     if ((opCode == OP_membarstorestore) && func.IsConstructor() && MemBarOpt(stmt)) {
1739         return true;
1740         ;
1741     }
1742 #if TARGAARCH64 || TARGRISCV64
1743     if ((!CGOptions::UseBarriersForVolatile()) && (nextStmt->GetOpCode() == OP_membaracquire)) {
1744         isVolLoad = true;
1745     }
1746 #endif /* TARGAARCH64 */
1747     return false;
1748 }
1749 
GenerateLoc(StmtNode * stmt,unsigned & lastSrcLoc,unsigned & lastMplLoc)1750 void CGFunc::GenerateLoc(StmtNode *stmt, unsigned &lastSrcLoc, unsigned &lastMplLoc)
1751 {
1752     /* insert Insn for .loc before cg for the stmt */
1753     if (cg->GetCGOptions().WithLoc() && stmt->op != OP_label && stmt->op != OP_comment) {
1754         /* if original src file location info is availiable for this stmt,
1755          * use it and skip mpl file location info for this stmt
1756          */
1757         bool hasLoc = false;
1758         unsigned newSrcLoc = cg->GetCGOptions().WithSrc() ? stmt->GetSrcPos().LineNum() : 0;
1759         if (newSrcLoc != 0 && newSrcLoc != lastSrcLoc) {
1760             /* .loc for original src file */
1761             unsigned fileid = stmt->GetSrcPos().FileNum();
1762             Operand *o0 = CreateDbgImmOperand(fileid);
1763             Operand *o1 = CreateDbgImmOperand(newSrcLoc);
1764             Insn &loc = GetInsnBuilder()->BuildDbgInsn(mpldbg::OP_DBG_loc).AddOpndChain(*o0).AddOpndChain(*o1);
1765             curBB->AppendInsn(loc);
1766             lastSrcLoc = newSrcLoc;
1767             hasLoc = true;
1768         }
1769         /* .loc for mpl file, skip if already has .loc from src for this stmt */
1770         unsigned newMplLoc = cg->GetCGOptions().WithMpl() ? stmt->GetSrcPos().MplLineNum() : 0;
1771         if (newMplLoc != 0 && newMplLoc != lastMplLoc && !hasLoc) {
1772             unsigned fileid = 1;
1773             Operand *o0 = CreateDbgImmOperand(fileid);
1774             Operand *o1 = CreateDbgImmOperand(newMplLoc);
1775             Insn &loc = GetInsnBuilder()->BuildDbgInsn(mpldbg::OP_DBG_loc).AddOpndChain(*o0).AddOpndChain(*o1);
1776             curBB->AppendInsn(loc);
1777             lastMplLoc = newMplLoc;
1778         }
1779     }
1780 }
1781 
GetFreqFromStmt(uint32 stmtId)1782 int32 CGFunc::GetFreqFromStmt(uint32 stmtId)
1783 {
1784     int32 freq = GetFunction().GetFreqFromLastStmt(stmtId);
1785     if (freq != -1) {
1786         return freq;
1787     }
1788     return GetFunction().GetFreqFromFirstStmt(stmtId);
1789 }
1790 
GetLmbcFormalParamInfo(uint32 offset)1791 LmbcFormalParamInfo *CGFunc::GetLmbcFormalParamInfo(uint32 offset)
1792 {
1793     MapleVector<LmbcFormalParamInfo *> &paramVec = GetLmbcParamVec();
1794     for (auto *param : paramVec) {
1795         uint32 paramOffset = param->GetOffset();
1796         uint32 paramSize = param->GetSize();
1797         if (paramOffset <= offset && offset < (paramOffset + paramSize)) {
1798             return param;
1799         }
1800     }
1801     return nullptr;
1802 }
1803 
1804 /*
1805  * For formals of lmbc, the formal list is deleted if there is no
1806  * passing of aggregate by value.
1807  */
CreateLmbcFormalParamInfo()1808 void CGFunc::CreateLmbcFormalParamInfo()
1809 {
1810     if (GetMirModule().GetFlavor() != MIRFlavor::kFlavorLmbc) {
1811         return;
1812     }
1813     PrimType primType;
1814     uint32 offset;
1815     uint32 typeSize;
1816     MIRFunction &lmbcFunc = GetFunction();
1817     if (lmbcFunc.GetFormalCount() > 0) {
1818         /* Whenever lmbc cannot delete call type info, the prototype is available */
1819         uint32 stackOffset = 0;
1820         for (size_t idx = 0; idx < lmbcFunc.GetFormalCount(); ++idx) {
1821             MIRSymbol *sym = lmbcFunc.GetFormal(idx);
1822             MIRType *type;
1823             TyIdx tyIdx;
1824             if (sym) {
1825                 tyIdx = lmbcFunc.GetFormalDefVec()[idx].formalTyIdx;
1826                 type = GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx);
1827             } else {
1828                 FormalDef vec =
1829                     const_cast<MIRFunction *>(GetBecommon().GetMIRModule().CurFunction())->GetFormalDefAt(idx);
1830                 tyIdx = vec.formalTyIdx;
1831                 type = GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx);
1832             }
1833             primType = type->GetPrimType();
1834             offset = stackOffset;
1835             typeSize = static_cast<uint32>(GetBecommon().GetTypeSize(tyIdx));
1836             stackOffset += (typeSize + k7BitSize) & (kNegative8BitSize);
1837             LmbcFormalParamInfo *info = GetMemoryPool()->New<LmbcFormalParamInfo>(primType, offset, typeSize);
1838             lmbcParamVec.push_back(info);
1839             if (idx == 0 && lmbcFunc.IsFirstArgReturn()) {
1840                 info->SetIsReturn();
1841             }
1842             if (type->GetKind() == kTypeStruct) {
1843                 MIRStructType *structType = static_cast<MIRStructType *>(type);
1844                 info->SetType(structType);
1845                 uint32 fpSize;
1846                 uint32 numFpRegs = FloatParamRegRequired(structType, fpSize);
1847                 if (numFpRegs > 0) {
1848                     info->SetIsPureFloat();
1849                     info->SetNumRegs(numFpRegs);
1850                     info->SetFpSize(fpSize);
1851                 }
1852             }
1853         }
1854     } else {
1855         /* No aggregate pass by value here */
1856         for (StmtNode *stmt = lmbcFunc.GetBody()->GetFirst(); stmt != nullptr; stmt = stmt->GetNext()) {
1857             if (stmt == nullptr) {
1858                 break;
1859             }
1860             if (stmt->GetOpCode() == OP_label) {
1861                 continue;
1862             }
1863             if (stmt->GetOpCode() != OP_regassign) {
1864                 break;
1865             }
1866             RegassignNode *regAssignNode = static_cast<RegassignNode *>(stmt);
1867             BaseNode *operand = regAssignNode->Opnd(0);
1868             if (operand->GetOpCode() != OP_ireadfpoff) {
1869                 break;
1870             }
1871             IreadFPoffNode *ireadNode = static_cast<IreadFPoffNode *>(operand);
1872             primType = ireadNode->GetPrimType();
1873             if (ireadNode->GetOffset() < 0) {
1874                 continue;
1875             }
1876             offset = static_cast<uint32>(ireadNode->GetOffset());
1877             typeSize = GetPrimTypeSize(primType);
1878             CHECK_FATAL((offset % k8ByteSize) == 0, ""); /* scalar only, no struct for now */
1879             LmbcFormalParamInfo *info = GetMemoryPool()->New<LmbcFormalParamInfo>(primType, offset, typeSize);
1880             lmbcParamVec.push_back(info);
1881         }
1882     }
1883     std::sort(lmbcParamVec.begin(), lmbcParamVec.end(), [](const LmbcFormalParamInfo *x, const LmbcFormalParamInfo *y) {
1884         return x->GetOffset() < y->GetOffset();
1885     });
1886 
1887     /* When a scalar param address is taken, its regassign is not in the 1st block */
1888     for (StmtNode *stmt = lmbcFunc.GetBody()->GetFirst(); stmt != nullptr; stmt = stmt->GetNext()) {
1889         if (stmt == nullptr) {
1890             break;
1891         }
1892         if (stmt->GetOpCode() == OP_label) {
1893             continue;
1894         }
1895         if (stmt->GetOpCode() != OP_regassign) {
1896             break;
1897         }
1898         RegassignNode *regAssignNode = static_cast<RegassignNode *>(stmt);
1899         BaseNode *operand = regAssignNode->Opnd(0);
1900         if (operand->GetOpCode() != OP_ireadfpoff) {
1901             break;
1902         }
1903         IreadFPoffNode *ireadNode = static_cast<IreadFPoffNode *>(operand);
1904         if (ireadNode->GetOffset() < 0) {
1905             continue;
1906         }
1907         LmbcFormalParamInfo *info = GetLmbcFormalParamInfo(static_cast<uint32>(ireadNode->GetOffset()));
1908         ASSERT_NOT_NULL(info);
1909         info->SetHasRegassign();
1910     }
1911 
1912     AssignLmbcFormalParams();
1913 }
1914 
GenerateInstruction()1915 void CGFunc::GenerateInstruction()
1916 {
1917     InitHandleExprFactory();
1918     InitHandleStmtFactory();
1919     StmtNode *secondStmt = HandleFirstStmt();
1920 
1921     /* First Pass: Creates the doubly-linked list of BBs (next,prev) */
1922     volReleaseInsn = nullptr;
1923     unsigned lastSrcLoc = 0;
1924     unsigned lastMplLoc = 0;
1925     std::set<uint32> bbFreqSet;
1926     for (StmtNode *stmt = secondStmt; stmt != nullptr; stmt = stmt->GetNext()) {
1927         /* insert Insn for .loc before cg for the stmt */
1928         GenerateLoc(stmt, lastSrcLoc, lastMplLoc);
1929         BB *tmpBB = curBB;
1930         isVolLoad = false;
1931         if (CheckSkipMembarOp(*stmt)) {
1932             continue;
1933         }
1934         bool tempLoad = isVolLoad;
1935         auto function = CreateProductFunction<HandleStmtFactory>(stmt->GetOpCode());
1936         CHECK_FATAL(function != nullptr, "unsupported opCode or has been lowered before");
1937         function(*stmt, *this);
1938         /* skip the membar acquire if it is just after the iread. ldr + membaraquire->ldar */
1939         if (tempLoad && !isVolLoad) {
1940             stmt = stmt->GetNext();
1941         }
1942         int32 freq = GetFreqFromStmt(stmt->GetStmtID());
1943         if (freq != -1) {
1944             if (tmpBB != curBB) {
1945                 if (curBB->GetFirstInsn() == nullptr && curBB->GetLabIdx() == 0 &&
1946                     bbFreqSet.count(tmpBB->GetId()) == 0) {
1947                     tmpBB->SetFrequency(static_cast<uint32>(freq));
1948                     bbFreqSet.insert(tmpBB->GetId());
1949                 } else if ((curBB->GetFirstInsn() != nullptr || curBB->GetLabIdx() != 0) &&
1950                            bbFreqSet.count(curBB->GetId()) == 0) {
1951                     curBB->SetFrequency(static_cast<uint32>(freq));
1952                     bbFreqSet.insert(tmpBB->GetId());
1953                 }
1954             } else if (bbFreqSet.count(curBB->GetId()) == 0) {
1955                 curBB->SetFrequency(static_cast<uint32>(freq));
1956                 bbFreqSet.insert(curBB->GetId());
1957             }
1958         }
1959 
1960         /*
1961          * skip the membarstoreload if there is the pattern for volatile write( membarrelease + store + membarstoreload
1962          * ) membarrelease + store + membarstoreload -> stlr
1963          */
1964         if (volReleaseInsn != nullptr) {
1965             if ((stmt->GetOpCode() != OP_membarrelease) && (stmt->GetOpCode() != OP_comment)) {
1966                 if (!isVolStore) {
1967                     /* remove the generated membar release insn. */
1968                     curBB->RemoveInsn(*volReleaseInsn);
1969                     /* skip the membarstoreload. */
1970                     stmt = stmt->GetNext();
1971                 }
1972                 volReleaseInsn = nullptr;
1973                 isVolStore = false;
1974             }
1975         }
1976         if (curBB != tmpBB) {
1977             lastSrcLoc = 0;
1978         }
1979     }
1980 
1981     /* Set lastbb's frequency */
1982     BlockNode *block = func.GetBody();
1983     DEBUG_ASSERT(block != nullptr, "get func body block failed in CGFunc::GenerateInstruction");
1984     curBB->SetLastStmt(*block->GetLast());
1985     curBB->SetFrequency(frequency);
1986     lastBB = curBB;
1987     cleanupBB = lastBB->GetPrev();
1988     /* All stmts are handled */
1989     frequency = 0;
1990 }
1991 
CreateLabel()1992 LabelIdx CGFunc::CreateLabel()
1993 {
1994     MIRSymbol *funcSt = GlobalTables::GetGsymTable().GetSymbolFromStidx(func.GetStIdx().Idx());
1995     DEBUG_ASSERT(funcSt != nullptr, "Get func failed at CGFunc::CreateLabel");
1996     std::string funcName = funcSt->GetName();
1997     std::string labelStr = funcName += std::to_string(labelIdx++);
1998     return func.GetOrCreateLableIdxFromName(labelStr);
1999 }
2000 
GetRetRefSymbol(BaseNode & expr)2001 MIRSymbol *CGFunc::GetRetRefSymbol(BaseNode &expr)
2002 {
2003     Opcode opcode = expr.GetOpCode();
2004     if (opcode != OP_dread) {
2005         return nullptr;
2006     }
2007     auto &retExpr = static_cast<AddrofNode &>(expr);
2008     MIRSymbol *symbol = mirModule.CurFunction()->GetLocalOrGlobalSymbol(retExpr.GetStIdx());
2009     DEBUG_ASSERT(symbol != nullptr, "get symbol in mirmodule failed");
2010     if (symbol->IsRefType()) {
2011         MIRSymbol *sym = nullptr;
2012         for (uint32 i = 0; i < func.GetFormalCount(); i++) {
2013             sym = func.GetFormal(i);
2014             if (sym == symbol) {
2015                 return nullptr;
2016             }
2017         }
2018         return symbol;
2019     }
2020     return nullptr;
2021 }
2022 
GenerateCfiPrologEpilog()2023 void CGFunc::GenerateCfiPrologEpilog()
2024 {
2025     if (GenCfi() == false) {
2026         return;
2027     }
2028     Insn &ipoint = GetInsnBuilder()->BuildCfiInsn(cfi::OP_CFI_startproc);
2029     /* prolog */
2030     if (firstBB->GetFirstInsn() != nullptr) {
2031         firstBB->InsertInsnBefore(*firstBB->GetFirstInsn(), ipoint);
2032     } else {
2033         firstBB->AppendInsn(ipoint);
2034     }
2035 
2036 #if !defined(TARGARM32)
2037     /*
2038      * always generate ".cfi_personality 155, DW.ref.__mpl_personality_v0" for Java methods.
2039      * we depend on this to tell whether it is a java method.
2040      */
2041     if (mirModule.IsJavaModule() && func.IsJava()) {
2042         Insn &personality = GetInsnBuilder()
2043                                 ->BuildCfiInsn(cfi::OP_CFI_personality_symbol)
2044                                 .AddOpndChain(CreateCfiImmOperand(EHFunc::kTypeEncoding, k8BitSize))
2045                                 .AddOpndChain(CreateCfiStrOperand("DW.ref.__mpl_personality_v0"));
2046         firstBB->InsertInsnAfter(ipoint, personality);
2047     }
2048 #endif
2049 
2050     /* epilog */
2051     lastBB->AppendInsn(GetInsnBuilder()->BuildCfiInsn(cfi::OP_CFI_endproc));
2052 }
2053 
TraverseAndClearCatchMark(BB & bb)2054 void CGFunc::TraverseAndClearCatchMark(BB &bb)
2055 {
2056     /* has bb been visited */
2057     if (bb.GetInternalFlag3()) {
2058         return;
2059     }
2060     bb.SetIsCatch(false);
2061     bb.SetInternalFlag3(1);
2062     for (auto succBB : bb.GetSuccs()) {
2063         TraverseAndClearCatchMark(*succBB);
2064     }
2065 }
2066 
2067 /*
2068  * Two types of successor edges, normal and eh. Any bb which is not
2069  * reachable by a normal successor edge is considered to be in a
2070  * catch block.
2071  * Marking it as a catch block does not automatically make it into
2072  * a catch block. Unreachables can be marked as such too.
2073  */
MarkCatchBBs()2074 void CGFunc::MarkCatchBBs()
2075 {
2076     /* First, suspect all bb to be in catch */
2077     FOR_ALL_BB(bb, this) {
2078         bb->SetIsCatch(true);
2079         bb->SetInternalFlag3(0); /* mark as not visited */
2080     }
2081     /* Eliminate cleanup section from catch */
2082     FOR_ALL_BB(bb, this) {
2083         if (bb->GetFirstStmt() == cleanupLabel) {
2084             bb->SetIsCatch(false);
2085             DEBUG_ASSERT(bb->GetSuccs().size() <= 1, "MarkCatchBBs incorrect cleanup label");
2086             BB *succ = nullptr;
2087             if (!bb->GetSuccs().empty()) {
2088                 succ = bb->GetSuccs().front();
2089             } else {
2090                 continue;
2091             }
2092             DEBUG_ASSERT(succ != nullptr, "Get front succsBB failed");
2093             while (1) {
2094                 DEBUG_ASSERT(succ->GetSuccs().size() <= 1, "MarkCatchBBs incorrect cleanup label");
2095                 succ->SetIsCatch(false);
2096                 if (!succ->GetSuccs().empty()) {
2097                     succ = succ->GetSuccs().front();
2098                 } else {
2099                     break;
2100                 }
2101             }
2102         }
2103     }
2104     /* Unmark all normally reachable bb as NOT catch. */
2105     TraverseAndClearCatchMark(*firstBB);
2106 }
2107 
2108 /*
2109  * Mark CleanupEntryBB
2110  * Note: Cleanup bbs and func body bbs are seperated, no edges between them.
2111  * No ehSuccs or eh_prevs between cleanup bbs.
2112  */
MarkCleanupEntryBB()2113 void CGFunc::MarkCleanupEntryBB()
2114 {
2115     BB *cleanupEntry = nullptr;
2116     FOR_ALL_BB(bb, this) {
2117         bb->SetIsCleanup(0);     /* Use to mark cleanup bb */
2118         bb->SetInternalFlag3(0); /* Use to mark if visited. */
2119         if (bb->GetFirstStmt() == this->cleanupLabel) {
2120             cleanupEntry = bb;
2121         }
2122     }
2123     /* If a function without cleanup bb, return. */
2124     if (cleanupEntry == nullptr) {
2125         return;
2126     }
2127     /* after merge bb, update cleanupBB. */
2128     if (cleanupEntry->GetSuccs().empty()) {
2129         this->cleanupBB = cleanupEntry;
2130     }
2131     SetCleanupLabel(*cleanupEntry);
2132     DEBUG_ASSERT(cleanupEntry->GetEhSuccs().empty(), "CG internal error. Cleanup bb should not have ehSuccs.");
2133 #if DEBUG /* Please don't remove me. */
2134     /* Check if all of the cleanup bb is at bottom of the function. */
2135     bool isCleanupArea = true;
2136     if (!mirModule.IsCModule()) {
2137         FOR_ALL_BB_REV(bb, this) {
2138             if (isCleanupArea) {
2139                 DEBUG_ASSERT(bb->IsCleanup(),
2140                              "CG internal error, cleanup BBs should be at the bottom of the function.");
2141             } else {
2142                 DEBUG_ASSERT(!bb->IsCleanup(),
2143                              "CG internal error, cleanup BBs should be at the bottom of the function.");
2144             }
2145 
2146             if (bb == cleanupEntry) {
2147                 isCleanupArea = false;
2148             }
2149         }
2150     }
2151 #endif /* DEBUG */
2152     this->cleanupEntryBB = cleanupEntry;
2153 }
2154 
2155 /* Tranverse from current bb's successor and set isCleanup true. */
SetCleanupLabel(BB & cleanupEntry)2156 void CGFunc::SetCleanupLabel(BB &cleanupEntry)
2157 {
2158     /* If bb hasn't been visited, return. */
2159     if (cleanupEntry.GetInternalFlag3()) {
2160         return;
2161     }
2162     cleanupEntry.SetInternalFlag3(1);
2163     cleanupEntry.SetIsCleanup(1);
2164     for (auto tmpBB : cleanupEntry.GetSuccs()) {
2165         if (tmpBB->GetKind() != BB::kBBReturn) {
2166             SetCleanupLabel(*tmpBB);
2167         } else {
2168             DEBUG_ASSERT(ExitbbNotInCleanupArea(cleanupEntry), "exitBB created in cleanupArea.");
2169         }
2170     }
2171 }
2172 
ExitbbNotInCleanupArea(const BB & bb) const2173 bool CGFunc::ExitbbNotInCleanupArea(const BB &bb) const
2174 {
2175     for (const BB *nextBB = bb.GetNext(); nextBB != nullptr; nextBB = nextBB->GetNext()) {
2176         if (nextBB->GetKind() == BB::kBBReturn) {
2177             return false;
2178         }
2179     }
2180     return true;
2181 }
2182 
2183 /*
2184  * Do mem barrier optimization for constructor funcs as follow:
2185  * membarstorestore
2186  * write field of this_  ==> write field of this_
2187  * membarrelease             membarrelease.
2188  */
MemBarOpt(const StmtNode & membar)2189 bool CGFunc::MemBarOpt(const StmtNode &membar)
2190 {
2191     if (func.GetFormalCount() == 0) {
2192         return false;
2193     }
2194     MIRSymbol *thisSym = func.GetFormal(0);
2195     if (thisSym == nullptr) {
2196         return false;
2197     }
2198     StmtNode *stmt = membar.GetNext();
2199     for (; stmt != nullptr; stmt = stmt->GetNext()) {
2200         BaseNode *base = nullptr;
2201         if (stmt->GetOpCode() == OP_comment) {
2202             continue;
2203         } else if (stmt->GetOpCode() == OP_iassign) {
2204             base = static_cast<IassignNode *>(stmt)->Opnd(0);
2205         } else if (stmt->GetOpCode() == OP_call) {
2206             auto *callNode = static_cast<CallNode *>(stmt);
2207             MIRFunction *fn = GlobalTables::GetFunctionTable().GetFunctionFromPuidx(callNode->GetPUIdx());
2208             MIRSymbol *fsym = GetMirModule().CurFunction()->GetLocalOrGlobalSymbol(fn->GetStIdx(), false);
2209             DEBUG_ASSERT(fsym != nullptr, "null ptr check");
2210             if (fsym->GetName() == "MCC_WriteRefFieldNoDec") {
2211                 base = callNode->Opnd(0);
2212             }
2213         }
2214         if (base != nullptr) {
2215             Opcode op = base->GetOpCode();
2216             if (op == OP_regread && thisSym->IsPreg() &&
2217                 thisSym->GetPreg()->GetPregNo() == static_cast<RegreadNode *>(base)->GetRegIdx()) {
2218                 continue;
2219             }
2220             if ((op == OP_dread || op == OP_addrof) && !thisSym->IsPreg() &&
2221                 static_cast<AddrofNode *>(base)->GetStIdx() == thisSym->GetStIdx()) {
2222                 continue;
2223             }
2224         }
2225         break;
2226     }
2227 
2228     CHECK_NULL_FATAL(stmt);
2229     return stmt->GetOpCode() == OP_membarrelease;
2230 }
2231 
ProcessExitBBVec()2232 void CGFunc::ProcessExitBBVec()
2233 {
2234     if (exitBBVec.empty()) {
2235         LabelIdx newLabelIdx = CreateLabel();
2236         BB *retBB = CreateNewBB(newLabelIdx, cleanupBB->IsUnreachable(), BB::kBBReturn, cleanupBB->GetFrequency());
2237         cleanupBB->PrependBB(*retBB);
2238         exitBBVec.emplace_back(retBB);
2239         return;
2240     }
2241     /* split an empty exitBB */
2242     BB *bb = exitBBVec[0];
2243     if (bb->NumInsn() > 0) {
2244         BB *retBBPart = CreateNewBB(false, BB::kBBFallthru, bb->GetFrequency());
2245         DEBUG_ASSERT(retBBPart != nullptr, "retBBPart should not be nullptr");
2246         LabelIdx retBBPartLabelIdx = bb->GetLabIdx();
2247         if (retBBPartLabelIdx != MIRLabelTable::GetDummyLabel()) {
2248             retBBPart->AddLabel(retBBPartLabelIdx);
2249             lab2BBMap[retBBPartLabelIdx] = retBBPart;
2250         }
2251         Insn *insn = bb->GetFirstInsn();
2252         while (insn != nullptr) {
2253             bb->RemoveInsn(*insn);
2254             retBBPart->AppendInsn(*insn);
2255             insn = bb->GetFirstInsn();
2256         }
2257         bb->PrependBB(*retBBPart);
2258         LabelIdx newLabelIdx = CreateLabel();
2259         bb->AddLabel(newLabelIdx);
2260         lab2BBMap[newLabelIdx] = bb;
2261     }
2262 }
2263 
AddCommonExitBB()2264 void CGFunc::AddCommonExitBB()
2265 {
2266     uint32 i = 0;
2267     while (exitBBVec[i]->IsUnreachable() && i < exitBBVec.size()) {
2268         i++;
2269     }
2270     DEBUG_ASSERT(i < exitBBVec.size(), "all exit BBs are unreachable");
2271     // create fake commonExitBB
2272     commonExitBB = CreateNewBB(true, BB::kBBFallthru, 0);
2273     DEBUG_ASSERT(commonExitBB != nullptr, "cannot create fake commonExitBB");
2274     for (BB *cgbb : exitBBVec) {
2275         if (!cgbb->IsUnreachable()) {
2276             commonExitBB->PushBackPreds(*cgbb);
2277         }
2278     }
2279 }
2280 
UpdateCallBBFrequency()2281 void CGFunc::UpdateCallBBFrequency()
2282 {
2283     if (!func.HasFreqMap() || func.GetLastFreqMap().empty()) {
2284         return;
2285     }
2286     FOR_ALL_BB(bb, this) {
2287         if (bb->GetKind() != BB::kBBFallthru || !bb->HasCall()) {
2288             continue;
2289         }
2290         DEBUG_ASSERT(bb->GetSuccs().size() <= 1, "fallthru BB has only one successor.");
2291         if (!bb->GetSuccs().empty()) {
2292             bb->SetFrequency((*(bb->GetSuccsBegin()))->GetFrequency());
2293         }
2294     }
2295 }
2296 
HandleFunction()2297 void CGFunc::HandleFunction()
2298 {
2299     /* select instruction */
2300     GenerateInstruction();
2301     /* merge multi return */
2302     if (!func.GetModule()->IsCModule() || CGOptions::DoRetMerge() || CGOptions::OptimizeForSize()) {
2303         MergeReturn();
2304     }
2305     if (func.IsJava()) {
2306         DEBUG_ASSERT(exitBBVec.size() <= 1, "there are more than one BB_return in func");
2307     }
2308     ProcessExitBBVec();
2309     LmbcGenSaveSpForAlloca();
2310 
2311     if (func.IsJava()) {
2312         GenerateCleanupCodeForExtEpilog(*cleanupBB);
2313     } else if (!func.GetModule()->IsCModule()) {
2314         GenerateCleanupCode(*cleanupBB);
2315     }
2316     GenSaveMethodInfoCode(*firstBB);
2317     /* build control flow graph */
2318     theCFG = memPool->New<CGCFG>(*this);
2319     theCFG->BuildCFG();
2320     AddCommonExitBB();
2321     if (mirModule.GetSrcLang() != kSrcLangC) {
2322         MarkCatchBBs();
2323     }
2324     MarkCleanupEntryBB();
2325     DetermineReturnTypeofCall();
2326     theCFG->MarkLabelTakenBB();
2327     theCFG->UnreachCodeAnalysis();
2328     EraseUnreachableStackMapInsns();
2329     if (mirModule.GetSrcLang() == kSrcLangC) {
2330         theCFG->WontExitAnalysis();
2331     }
2332     if (CGOptions::IsLazyBinding() && !GetCG()->IsLibcore()) {
2333         ProcessLazyBinding();
2334     }
2335     if (GetCG()->DoPatchLongBranch()) {
2336         PatchLongBranch();
2337     }
2338     if (CGOptions::DoEnableHotColdSplit()) {
2339         theCFG->CheckCFGFreq();
2340     }
2341 }
2342 
AddDIESymbolLocation(const MIRSymbol * sym,SymbolAlloc * loc)2343 void CGFunc::AddDIESymbolLocation(const MIRSymbol *sym, SymbolAlloc *loc)
2344 {
2345     DEBUG_ASSERT(debugInfo != nullptr, "debugInfo is null!");
2346     DEBUG_ASSERT(loc->GetMemSegment() != nullptr, "only support those variable that locate at stack now");
2347     DBGDie *sdie = debugInfo->GetLocalDie(&func, sym->GetNameStrIdx());
2348     if (sdie == nullptr) {
2349         return;
2350     }
2351 
2352     DBGExprLoc *exprloc = sdie->GetExprLoc();
2353     CHECK_FATAL(exprloc != nullptr, "exprloc is null in CGFunc::AddDIESymbolLocation");
2354     exprloc->SetSymLoc(loc);
2355 
2356     GetDbgCallFrameLocations().push_back(exprloc);
2357 }
2358 
DumpCFG() const2359 void CGFunc::DumpCFG() const
2360 {
2361     MIRSymbol *funcSt = GlobalTables::GetGsymTable().GetSymbolFromStidx(func.GetStIdx().Idx());
2362     DEBUG_ASSERT(funcSt != nullptr, "null ptr check");
2363     LogInfo::MapleLogger() << "\n****** CFG built by CG for " << funcSt->GetName() << " *******\n";
2364     FOR_ALL_BB_CONST(bb, this) {
2365         LogInfo::MapleLogger() << "=== BB ( " << std::hex << bb << std::dec << " ) <" << bb->GetKindName() << "> ===\n";
2366         LogInfo::MapleLogger() << "BB id:" << bb->GetId() << "\n";
2367         if (!bb->GetPreds().empty()) {
2368             LogInfo::MapleLogger() << " pred [ ";
2369             for (auto *pred : bb->GetPreds()) {
2370                 LogInfo::MapleLogger() << pred->GetId() << " ";
2371             }
2372             LogInfo::MapleLogger() << "]\n";
2373         }
2374         if (!bb->GetSuccs().empty()) {
2375             LogInfo::MapleLogger() << " succ [ ";
2376             for (auto *succ : bb->GetSuccs()) {
2377                 LogInfo::MapleLogger() << succ->GetId() << " ";
2378             }
2379             LogInfo::MapleLogger() << "]\n";
2380         }
2381         const StmtNode *stmt = bb->GetFirstStmt();
2382         if (stmt != nullptr) {
2383             bool done = false;
2384             do {
2385                 done = stmt == bb->GetLastStmt();
2386                 stmt->Dump(1);
2387                 LogInfo::MapleLogger() << "\n";
2388                 stmt = stmt->GetNext();
2389             } while (!done);
2390         } else {
2391             LogInfo::MapleLogger() << "<empty BB>\n";
2392         }
2393     }
2394 }
2395 
DumpCGIR() const2396 void CGFunc::DumpCGIR() const
2397 {
2398     MIRSymbol *funcSt = GlobalTables::GetGsymTable().GetSymbolFromStidx(func.GetStIdx().Idx());
2399     DEBUG_ASSERT(funcSt != nullptr, "null ptr check");
2400     LogInfo::MapleLogger() << "\n******  CGIR for " << funcSt->GetName() << " *******\n";
2401     FOR_ALL_BB_CONST(bb, this) {
2402         if (bb->IsUnreachable()) {
2403             continue;
2404         }
2405         LogInfo::MapleLogger() << "=== BB "
2406                                << " <" << bb->GetKindName();
2407         if (bb->GetLabIdx() != MIRLabelTable::GetDummyLabel()) {
2408             LogInfo::MapleLogger() << "[labeled with " << bb->GetLabIdx();
2409             LogInfo::MapleLogger() << " ==> @" << func.GetLabelName(bb->GetLabIdx()) << "]";
2410         }
2411 
2412         LogInfo::MapleLogger() << "> <" << bb->GetId() << "> ";
2413         if (bb->GetLoop()) {
2414             LogInfo::MapleLogger() << "[Loop level " << bb->GetLoop()->GetLoopLevel();
2415             LogInfo::MapleLogger() << ", head BB " << bb->GetLoop()->GetHeader()->GetId() << "]";
2416         }
2417         if (bb->IsCleanup()) {
2418             LogInfo::MapleLogger() << "[is_cleanup] ";
2419         }
2420         if (bb->IsUnreachable()) {
2421             LogInfo::MapleLogger() << "[unreachable] ";
2422         }
2423         if (bb->GetFirstStmt() == cleanupLabel) {
2424             LogInfo::MapleLogger() << "cleanup ";
2425         }
2426         if (!bb->GetSuccs().empty()) {
2427             LogInfo::MapleLogger() << "succs: ";
2428             for (auto *succBB : bb->GetSuccs()) {
2429                 LogInfo::MapleLogger() << succBB->GetId() << " ";
2430             }
2431         }
2432         if (!bb->GetPreds().empty()) {
2433             LogInfo::MapleLogger() << "preds: ";
2434             for (auto *predBB : bb->GetPreds()) {
2435                 LogInfo::MapleLogger() << predBB->GetId() << " ";
2436             }
2437         }
2438         if (!bb->GetEhSuccs().empty()) {
2439             LogInfo::MapleLogger() << "eh_succs: ";
2440             for (auto *ehSuccBB : bb->GetEhSuccs()) {
2441                 LogInfo::MapleLogger() << ehSuccBB->GetId() << " ";
2442             }
2443         }
2444         if (!bb->GetEhPreds().empty()) {
2445             LogInfo::MapleLogger() << "eh_preds: ";
2446             for (auto *ehPredBB : bb->GetEhPreds()) {
2447                 LogInfo::MapleLogger() << ehPredBB->GetId() << " ";
2448             }
2449         }
2450         LogInfo::MapleLogger() << "===\n";
2451         LogInfo::MapleLogger() << "frequency:" << bb->GetFrequency() << "\n";
2452 
2453         FOR_BB_INSNS_CONST(insn, bb) {
2454             insn->Dump();
2455         }
2456     }
2457 }
2458 
DumpLoop() const2459 void CGFunc::DumpLoop() const
2460 {
2461     for (const auto *lp : loops) {
2462         lp->PrintLoops(*lp);
2463     }
2464 }
2465 
ClearLoopInfo()2466 void CGFunc::ClearLoopInfo()
2467 {
2468     loops.clear();
2469     loops.shrink_to_fit();
2470     FOR_ALL_BB(bb, this) {
2471         bb->ClearLoopPreds();
2472         bb->ClearLoopSuccs();
2473     }
2474 }
2475 
DumpCFGToDot(const std::string & fileNamePrefix)2476 void CGFunc::DumpCFGToDot(const std::string &fileNamePrefix)
2477 {
2478     std::ofstream file(fileNamePrefix + GetName());
2479     file << "digraph {" << std::endl;
2480     for (auto *bb : GetAllBBs()) {
2481         if (bb == nullptr) {
2482             continue;
2483         }
2484         auto &succs = bb->GetSuccs();
2485         if (succs.empty()) {
2486             continue;
2487         }
2488         file << "  " << bb->GetId() << "->{";
2489         for (auto *succ : succs) {
2490             file << succ->GetId() << " ";
2491         }
2492         file << "};";
2493     }
2494     file << "}" << std::endl;
2495 }
2496 
PatchLongBranch()2497 void CGFunc::PatchLongBranch()
2498 {
2499     for (BB *bb = firstBB->GetNext(); bb != nullptr; bb = bb->GetNext()) {
2500         bb->SetInternalFlag1(bb->GetInternalFlag1() + bb->GetPrev()->GetInternalFlag1());
2501     }
2502     BB *next = nullptr;
2503     for (BB *bb = firstBB; bb != nullptr; bb = next) {
2504         next = bb->GetNext();
2505         if (bb->GetKind() != BB::kBBIf && bb->GetKind() != BB::kBBGoto) {
2506             continue;
2507         }
2508         Insn *insn = bb->GetLastInsn();
2509         while (insn->IsImmaterialInsn()) {
2510             insn = insn->GetPrev();
2511         }
2512         BB *tbb = GetBBFromLab2BBMap(GetLabelInInsn(*insn));
2513         if ((tbb->GetInternalFlag1() - bb->GetInternalFlag1()) < MaxCondBranchDistance()) {
2514             continue;
2515         }
2516         InsertJumpPad(insn);
2517     }
2518 }
2519 
UpdateAllRegisterVregMapping(MapleMap<regno_t,PregIdx> & newMap)2520 void CGFunc::UpdateAllRegisterVregMapping(MapleMap<regno_t, PregIdx> &newMap)
2521 {
2522     vregsToPregsMap.clear();
2523     for (auto it : newMap) {
2524         vregsToPregsMap[it.first] = it.second;
2525     }
2526 }
2527 
PhaseRun(maplebe::CGFunc & f)2528 bool CgHandleFunction::PhaseRun(maplebe::CGFunc &f)
2529 {
2530     f.HandleFunction();
2531     return false;
2532 }
MAPLE_TRANSFORM_PHASE_REGISTER(CgHandleFunction,handlefunction)2533 MAPLE_TRANSFORM_PHASE_REGISTER(CgHandleFunction, handlefunction)
2534 
2535 bool CgFixCFLocOsft::PhaseRun(maplebe::CGFunc &f)
2536 {
2537     if (f.GetCG()->GetCGOptions().WithDwarf()) {
2538         f.DBGFixCallFrameLocationOffsets();
2539     }
2540     return false;
2541 }
2542 MAPLE_TRANSFORM_PHASE_REGISTER(CgFixCFLocOsft, dbgfixcallframeoffsets)
2543 } /* namespace maplebe */
2544