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 ®ReadNode = 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 ®AssignNode = 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 *> ¶mVec = 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