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