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 #endif
19 #include "cg.h"
20 #include "factory.h"
21 #include "cfgo.h"
22
23 namespace maplebe {
24 using namespace maple;
25
HandleDread(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)26 static Operand *HandleDread(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
27 {
28 auto &dreadNode = static_cast<AddrofNode &>(expr);
29 return cgFunc.SelectDread(parent, dreadNode);
30 }
31
HandleRegread(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)32 static Operand *HandleRegread(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
33 {
34 (void)parent;
35 auto ®ReadNode = static_cast<RegreadNode &>(expr);
36 return cgFunc.SelectRegread(regReadNode);
37 }
38
HandleConstVal(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)39 static Operand *HandleConstVal(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
40 {
41 auto &constValNode = static_cast<ConstvalNode &>(expr);
42 MIRConst *mirConst = constValNode.GetConstVal();
43 DEBUG_ASSERT(mirConst != nullptr, "get constval of constvalnode failed");
44 if (mirConst->GetKind() == kConstInt) {
45 auto *mirIntConst = safe_cast<MIRIntConst>(mirConst);
46 return cgFunc.SelectIntConst(*mirIntConst, parent);
47 } else if (mirConst->GetKind() == kConstFloatConst) {
48 auto *mirFloatConst = safe_cast<MIRFloatConst>(mirConst);
49 return cgFunc.SelectFloatConst(*mirFloatConst, parent);
50 } else {
51 CHECK_FATAL(mirConst->GetKind() == kConstDoubleConst, "NYI");
52 auto *mirDoubleConst = safe_cast<MIRDoubleConst>(mirConst);
53 return cgFunc.SelectDoubleConst(*mirDoubleConst, parent);
54 }
55 return nullptr;
56 }
57
HandleAdd(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)58 static Operand *HandleAdd(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
59 {
60 return cgFunc.SelectAdd(static_cast<BinaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)),
61 *cgFunc.HandleExpr(expr, *expr.Opnd(1)), parent);
62 }
63
HandleShift(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)64 static Operand *HandleShift(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
65 {
66 return cgFunc.SelectShift(static_cast<BinaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)),
67 *cgFunc.HandleExpr(expr, *expr.Opnd(1)), parent);
68 }
69
HandleMpy(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)70 static Operand *HandleMpy(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
71 {
72 return cgFunc.SelectMpy(static_cast<BinaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)),
73 *cgFunc.HandleExpr(expr, *expr.Opnd(1)), parent);
74 }
75
HandleDiv(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)76 static Operand *HandleDiv(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
77 {
78 return cgFunc.SelectDiv(static_cast<BinaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)),
79 *cgFunc.HandleExpr(expr, *expr.Opnd(1)), parent);
80 }
81
HandleRem(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)82 static Operand *HandleRem(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
83 {
84 return cgFunc.SelectRem(static_cast<BinaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)),
85 *cgFunc.HandleExpr(expr, *expr.Opnd(1)), parent);
86 }
87
HandleIread(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)88 static Operand *HandleIread(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
89 {
90 auto &ireadNode = static_cast<IreadNode &>(expr);
91 return cgFunc.SelectIread(parent, ireadNode);
92 }
93
HandleSub(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)94 static Operand *HandleSub(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
95 {
96 return cgFunc.SelectSub(static_cast<BinaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)),
97 *cgFunc.HandleExpr(expr, *expr.Opnd(1)), parent);
98 }
99
HandleBand(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)100 static Operand *HandleBand(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
101 {
102 return cgFunc.SelectBand(static_cast<BinaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)),
103 *cgFunc.HandleExpr(expr, *expr.Opnd(1)), parent);
104 }
105
HandleBior(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)106 static Operand *HandleBior(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
107 {
108 return cgFunc.SelectBior(static_cast<BinaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)),
109 *cgFunc.HandleExpr(expr, *expr.Opnd(1)), parent);
110 }
111
HandleBxor(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)112 static Operand *HandleBxor(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
113 {
114 return cgFunc.SelectBxor(static_cast<BinaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)),
115 *cgFunc.HandleExpr(expr, *expr.Opnd(1)), parent);
116 }
117
HandleAbs(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)118 static Operand *HandleAbs(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
119 {
120 (void)parent;
121 DEBUG_ASSERT(expr.Opnd(0) != nullptr, "expr.Opnd(0) should not be nullptr");
122 return cgFunc.SelectAbs(static_cast<UnaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)));
123 }
124
HandleBnot(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)125 static Operand *HandleBnot(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
126 {
127 return cgFunc.SelectBnot(static_cast<UnaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)), parent);
128 }
129
HandleExtractBits(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)130 static Operand *HandleExtractBits(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
131 {
132 ExtractbitsNode &node = static_cast<ExtractbitsNode &>(expr);
133 uint8 bitOffset = node.GetBitsOffset();
134 uint8 bitSize = node.GetBitsSize();
135 if (!CGOptions::IsBigEndian() && (bitSize == k8BitSize || bitSize == k16BitSize) &&
136 GetPrimTypeBitSize(node.GetPrimType()) != k64BitSize &&
137 (bitOffset == 0 || bitOffset == k8BitSize || bitOffset == k16BitSize || bitOffset == k24BitSize) &&
138 expr.Opnd(0)->GetOpCode() == OP_iread && node.GetOpCode() == OP_extractbits) {
139 return cgFunc.SelectRegularBitFieldLoad(node, parent);
140 }
141 return cgFunc.SelectExtractbits(static_cast<ExtractbitsNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)),
142 parent);
143 }
144
HandleLnot(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)145 static Operand *HandleLnot(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
146 {
147 DEBUG_ASSERT(expr.Opnd(0) != nullptr, "nullptr check");
148 return cgFunc.SelectLnot(static_cast<UnaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)), parent);
149 }
150
151
HandleMin(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)152 static Operand *HandleMin(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
153 {
154 return cgFunc.SelectMin(static_cast<BinaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)),
155 *cgFunc.HandleExpr(expr, *expr.Opnd(1)), parent);
156 }
157
HandleMax(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)158 static Operand *HandleMax(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
159 {
160 return cgFunc.SelectMax(static_cast<BinaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)),
161 *cgFunc.HandleExpr(expr, *expr.Opnd(1)), parent);
162 }
163
HandleSqrt(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)164 static Operand *HandleSqrt(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
165 {
166 return cgFunc.SelectSqrt(static_cast<UnaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)), parent);
167 }
168
HandleCeil(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)169 static Operand *HandleCeil(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
170 {
171 return cgFunc.SelectCeil(static_cast<TypeCvtNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)), parent);
172 }
173
HandleFloor(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)174 static Operand *HandleFloor(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
175 {
176 DEBUG_ASSERT(expr.Opnd(0) != nullptr, "expr.Opnd(0) should not be nullptr");
177 return cgFunc.SelectFloor(static_cast<TypeCvtNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)), parent);
178 }
179
HandleRetype(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)180 static Operand *HandleRetype(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
181 {
182 (void)parent;
183 DEBUG_ASSERT(expr.Opnd(0) != nullptr, "nullptr check");
184 return cgFunc.SelectRetype(static_cast<TypeCvtNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)));
185 }
186
HandleCvt(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)187 static Operand *HandleCvt(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
188 {
189 return cgFunc.SelectCvt(parent, static_cast<TypeCvtNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)));
190 }
191
HandleTrunc(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)192 static Operand *HandleTrunc(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
193 {
194 DEBUG_ASSERT(expr.Opnd(0) != nullptr, "expr should not be nullptr");
195 return cgFunc.SelectTrunc(static_cast<TypeCvtNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)), parent);
196 }
197
HandleCmp(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)198 static Operand *HandleCmp(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
199 {
200 // fix opnd type before select insn
201 PrimType targetPtyp = parent.GetPrimType();
202 if (kOpcodeInfo.IsCompare(parent.GetOpCode())) {
203 targetPtyp = static_cast<const CompareNode &>(parent).GetOpndType();
204 } else if (kOpcodeInfo.IsTypeCvt(parent.GetOpCode())) {
205 targetPtyp = static_cast<const TypeCvtNode &>(parent).FromType();
206 }
207 if (IsPrimitiveInteger(targetPtyp) && targetPtyp != expr.GetPrimType()) {
208 expr.SetPrimType(targetPtyp);
209 }
210 return cgFunc.SelectCmpOp(static_cast<CompareNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)),
211 *cgFunc.HandleExpr(expr, *expr.Opnd(1)), parent);
212 }
213
HandleIntrinOp(const BaseNode & parent,BaseNode & expr,CGFunc & cgFunc)214 static Operand *HandleIntrinOp(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
215 {
216 auto &intrinsicopNode = static_cast<IntrinsicopNode &>(expr);
217 switch (intrinsicopNode.GetIntrinsic()) {
218 case INTRN_C_clz32:
219 case INTRN_C_clz64:
220 return cgFunc.SelectCclz(intrinsicopNode);
221 default:
222 DEBUG_ASSERT(false, "Should not reach here.");
223 return nullptr;
224 }
225 }
226
227 using HandleExprFactory = FunctionFactory<Opcode, maplebe::Operand *, const BaseNode &, BaseNode &, CGFunc &>;
InitHandleExprFactory()228 void InitHandleExprFactory()
229 {
230 RegisterFactoryFunction<HandleExprFactory>(OP_dread, HandleDread);
231 RegisterFactoryFunction<HandleExprFactory>(OP_regread, HandleRegread);
232 RegisterFactoryFunction<HandleExprFactory>(OP_constval, HandleConstVal);
233 RegisterFactoryFunction<HandleExprFactory>(OP_add, HandleAdd);
234 RegisterFactoryFunction<HandleExprFactory>(OP_ashr, HandleShift);
235 RegisterFactoryFunction<HandleExprFactory>(OP_lshr, HandleShift);
236 RegisterFactoryFunction<HandleExprFactory>(OP_shl, HandleShift);
237 RegisterFactoryFunction<HandleExprFactory>(OP_mul, HandleMpy);
238 RegisterFactoryFunction<HandleExprFactory>(OP_div, HandleDiv);
239 RegisterFactoryFunction<HandleExprFactory>(OP_rem, HandleRem);
240 RegisterFactoryFunction<HandleExprFactory>(OP_iread, HandleIread);
241 RegisterFactoryFunction<HandleExprFactory>(OP_sub, HandleSub);
242 RegisterFactoryFunction<HandleExprFactory>(OP_band, HandleBand);
243 RegisterFactoryFunction<HandleExprFactory>(OP_bior, HandleBior);
244 RegisterFactoryFunction<HandleExprFactory>(OP_bxor, HandleBxor);
245 RegisterFactoryFunction<HandleExprFactory>(OP_abs, HandleAbs);
246 RegisterFactoryFunction<HandleExprFactory>(OP_bnot, HandleBnot);
247 RegisterFactoryFunction<HandleExprFactory>(OP_sext, HandleExtractBits);
248 RegisterFactoryFunction<HandleExprFactory>(OP_zext, HandleExtractBits);
249 RegisterFactoryFunction<HandleExprFactory>(OP_lnot, HandleLnot);
250 RegisterFactoryFunction<HandleExprFactory>(OP_min, HandleMin);
251 RegisterFactoryFunction<HandleExprFactory>(OP_max, HandleMax);
252 RegisterFactoryFunction<HandleExprFactory>(OP_sqrt, HandleSqrt);
253 RegisterFactoryFunction<HandleExprFactory>(OP_ceil, HandleCeil);
254 RegisterFactoryFunction<HandleExprFactory>(OP_floor, HandleFloor);
255 RegisterFactoryFunction<HandleExprFactory>(OP_retype, HandleRetype);
256 RegisterFactoryFunction<HandleExprFactory>(OP_cvt, HandleCvt);
257 RegisterFactoryFunction<HandleExprFactory>(OP_trunc, HandleTrunc);
258 RegisterFactoryFunction<HandleExprFactory>(OP_le, HandleCmp);
259 RegisterFactoryFunction<HandleExprFactory>(OP_ge, HandleCmp);
260 RegisterFactoryFunction<HandleExprFactory>(OP_gt, HandleCmp);
261 RegisterFactoryFunction<HandleExprFactory>(OP_lt, HandleCmp);
262 RegisterFactoryFunction<HandleExprFactory>(OP_ne, HandleCmp);
263 RegisterFactoryFunction<HandleExprFactory>(OP_eq, HandleCmp);
264 RegisterFactoryFunction<HandleExprFactory>(OP_intrinsicop, HandleIntrinOp);
265 }
266
HandleLabel(StmtNode & stmt,CGFunc & cgFunc)267 static void HandleLabel(StmtNode &stmt, CGFunc &cgFunc)
268 {
269 DEBUG_ASSERT(stmt.GetOpCode() == OP_label, "error");
270 auto &label = static_cast<LabelNode &>(stmt);
271 BB *newBB = cgFunc.StartNewBBImpl(false, label);
272 newBB->AddLabel(label.GetLabelIdx());
273 if (newBB->GetId() == 1) {
274 newBB->SetFrequency(kFreqBase);
275 }
276 cgFunc.SetLab2BBMap(newBB->GetLabIdx(), *newBB);
277 cgFunc.SetCurBB(*newBB);
278 }
279
HandleGoto(StmtNode & stmt,CGFunc & cgFunc)280 static void HandleGoto(StmtNode &stmt, CGFunc &cgFunc)
281 {
282 auto &gotoNode = static_cast<GotoNode &>(stmt);
283 cgFunc.SetCurBBKind(BB::kBBGoto);
284 cgFunc.SelectGoto(gotoNode);
285 cgFunc.SetCurBB(*cgFunc.StartNewBB(gotoNode));
286 DEBUG_ASSERT(&stmt == &gotoNode, "stmt must be same as gotoNoe");
287
288 if ((gotoNode.GetNext() != nullptr) && (gotoNode.GetNext()->GetOpCode() != OP_label)) {
289 DEBUG_ASSERT(cgFunc.GetCurBB()->GetPrev()->GetLastStmt() == &stmt, "check the relation between BB and stmt");
290 }
291 }
292
HandleCondbr(StmtNode & stmt,CGFunc & cgFunc)293 static void HandleCondbr(StmtNode &stmt, CGFunc &cgFunc)
294 {
295 auto &condGotoNode = static_cast<CondGotoNode &>(stmt);
296 BaseNode *condNode = condGotoNode.Opnd(0);
297 DEBUG_ASSERT(condNode != nullptr, "expect first operand of cond br");
298 Opcode condOp = condGotoNode.GetOpCode();
299 if (condNode->GetOpCode() == OP_constval) {
300 auto *constValNode = static_cast<ConstvalNode *>(condNode);
301 if ((constValNode->GetConstVal()->IsZero() && (OP_brfalse == condOp)) ||
302 (!constValNode->GetConstVal()->IsZero() && (OP_brtrue == condOp))) {
303 auto *gotoStmt = cgFunc.GetMemoryPool()->New<GotoNode>(OP_goto);
304 gotoStmt->SetOffset(condGotoNode.GetOffset());
305 HandleGoto(*gotoStmt, cgFunc);
306 auto *labelStmt = cgFunc.GetMemoryPool()->New<LabelNode>();
307 labelStmt->SetLabelIdx(cgFunc.CreateLabel());
308 HandleLabel(*labelStmt, cgFunc);
309 }
310 return;
311 }
312 cgFunc.SetCurBBKind(BB::kBBIf);
313 /* if condNode is not a cmp node, cmp it with zero. */
314 if (!kOpcodeInfo.IsCompare(condNode->GetOpCode())) {
315 Operand *opnd0 = cgFunc.HandleExpr(condGotoNode, *condNode);
316 PrimType primType = condNode->GetPrimType();
317 Operand *zeroOpnd = nullptr;
318 if (IsPrimitiveInteger(primType)) {
319 zeroOpnd = &cgFunc.CreateImmOperand(primType, 0);
320 } else {
321 DEBUG_ASSERT(((PTY_f32 == primType) || (PTY_f64 == primType)),
322 "we don't support half-precision FP operands yet");
323 zeroOpnd = &cgFunc.CreateImmOperand(primType, 0);
324 }
325 cgFunc.SelectCondGoto(condGotoNode, *opnd0, *zeroOpnd);
326 cgFunc.SetCurBB(*cgFunc.StartNewBB(condGotoNode));
327 return;
328 }
329 /*
330 * Special case:
331 * bgt (cmp (op0, op1), 0) ==>
332 * bgt (op0, op1)
333 * but skip the case cmp(op0, 0)
334 */
335 BaseNode *op0 = condNode->Opnd(0);
336 DEBUG_ASSERT(op0 != nullptr, "get first opnd of a condNode failed");
337 BaseNode *op1 = condNode->Opnd(1);
338 DEBUG_ASSERT(op1 != nullptr, "get second opnd of a condNode failed");
339 if ((op0->GetOpCode() == OP_cmp) && (op1->GetOpCode() == OP_constval)) {
340 auto *constValNode = static_cast<ConstvalNode *>(op1);
341 MIRConst *mirConst = constValNode->GetConstVal();
342 auto *cmpNode = static_cast<CompareNode *>(op0);
343 bool skip = false;
344 if (cmpNode->Opnd(1)->GetOpCode() == OP_constval) {
345 auto *constVal = static_cast<ConstvalNode *>(cmpNode->Opnd(1))->GetConstVal();
346 if (constVal->IsZero()) {
347 skip = true;
348 }
349 }
350 if (!skip && mirConst->IsZero()) {
351 cgFunc.SelectCondSpecialCase1(condGotoNode, *op0);
352 cgFunc.SetCurBB(*cgFunc.StartNewBB(condGotoNode));
353 return;
354 }
355 }
356
357 Operand *opnd0 = cgFunc.HandleExpr(*condNode, *condNode->Opnd(0));
358 Operand *opnd1 = cgFunc.HandleExpr(*condNode, *condNode->Opnd(1));
359 cgFunc.SelectCondGoto(condGotoNode, *opnd0, *opnd1);
360 cgFunc.SetCurBB(*cgFunc.StartNewBB(condGotoNode));
361 }
362
HandleReturn(StmtNode & stmt,CGFunc & cgFunc)363 static void HandleReturn(StmtNode &stmt, CGFunc &cgFunc)
364 {
365 auto &retNode = static_cast<NaryStmtNode &>(stmt);
366 DEBUG_ASSERT(retNode.NumOpnds() <= 1, "NYI return nodes number > 1");
367 Operand *opnd = nullptr;
368 if (retNode.NumOpnds() != 0) {
369 opnd = cgFunc.HandleExpr(retNode, *retNode.Opnd(0));
370 }
371 cgFunc.SelectReturn(opnd);
372 cgFunc.SetCurBBKind(BB::kBBReturn);
373 cgFunc.SetCurBB(*cgFunc.StartNewBB(retNode));
374 }
375
HandleCall(StmtNode & stmt,CGFunc & cgFunc)376 static void HandleCall(StmtNode &stmt, CGFunc &cgFunc)
377 {
378 auto &callNode = static_cast<CallNode &>(stmt);
379 cgFunc.SelectCall(callNode);
380 }
381
HandleICall(StmtNode & stmt,CGFunc & cgFunc)382 static void HandleICall(StmtNode &stmt, CGFunc &cgFunc)
383 {
384 auto &icallNode = static_cast<IcallNode &>(stmt);
385 cgFunc.GetCurBB()->SetHasCall();
386 cgFunc.SelectIcall(icallNode);
387 }
388
HandleIntrinsicCall(StmtNode & stmt,CGFunc & cgFunc)389 static void HandleIntrinsicCall(StmtNode &stmt, CGFunc &cgFunc)
390 {
391 auto &call = static_cast<IntrinsiccallNode &>(stmt);
392 cgFunc.SelectIntrinsicCall(call);
393 }
394
HandleDassign(StmtNode & stmt,CGFunc & cgFunc)395 static void HandleDassign(StmtNode &stmt, CGFunc &cgFunc)
396 {
397 auto &dassignNode = static_cast<DassignNode &>(stmt);
398 DEBUG_ASSERT(dassignNode.GetOpCode() == OP_dassign, "expect dassign");
399 BaseNode *rhs = dassignNode.GetRHS();
400 DEBUG_ASSERT(rhs != nullptr, "get rhs of dassignNode failed");
401 bool isSaveRetvalToLocal = false;
402 if (rhs->GetOpCode() == OP_regread) {
403 isSaveRetvalToLocal = (static_cast<RegreadNode *>(rhs)->GetRegIdx() == -kSregRetval0);
404 }
405 Operand *opnd0 = cgFunc.HandleExpr(dassignNode, *rhs);
406 cgFunc.SelectDassign(dassignNode, *opnd0);
407 if (isSaveRetvalToLocal && cgFunc.GetCurBB() && cgFunc.GetCurBB()->GetLastMachineInsn()) {
408 cgFunc.GetCurBB()->GetLastMachineInsn()->MarkAsSaveRetValToLocal();
409 }
410 }
411
HandleRegassign(StmtNode & stmt,CGFunc & cgFunc)412 static void HandleRegassign(StmtNode &stmt, CGFunc &cgFunc)
413 {
414 DEBUG_ASSERT(stmt.GetOpCode() == OP_regassign, "expect regAssign");
415 auto ®AssignNode = static_cast<RegassignNode &>(stmt);
416 bool isSaveRetvalToLocal = false;
417 BaseNode *operand = regAssignNode.Opnd(0);
418 DEBUG_ASSERT(operand != nullptr, "get operand of regassignNode failed");
419 if (operand->GetOpCode() == OP_regread) {
420 isSaveRetvalToLocal = (static_cast<RegreadNode *>(operand)->GetRegIdx() == -kSregRetval0);
421 }
422 Operand *opnd0 = cgFunc.HandleExpr(regAssignNode, *operand);
423 cgFunc.SelectRegassign(regAssignNode, *opnd0);
424 if (isSaveRetvalToLocal && cgFunc.GetCurBB() && cgFunc.GetCurBB()->GetLastMachineInsn()) {
425 cgFunc.GetCurBB()->GetLastMachineInsn()->MarkAsSaveRetValToLocal();
426 }
427 }
428
HandleIassign(StmtNode & stmt,CGFunc & cgFunc)429 static void HandleIassign(StmtNode &stmt, CGFunc &cgFunc)
430 {
431 DEBUG_ASSERT(stmt.GetOpCode() == OP_iassign, "expect stmt");
432 auto &iassignNode = static_cast<IassignNode &>(stmt);
433 if ((iassignNode.GetRHS() != nullptr)) {
434 cgFunc.SelectIassign(iassignNode);
435 } else {
436 CHECK_FATAL(false, "NIY");
437 }
438 }
439
HandleRangeGoto(StmtNode & stmt,CGFunc & cgFunc)440 void HandleRangeGoto(StmtNode &stmt, CGFunc &cgFunc)
441 {
442 auto &rangeGotoNode = static_cast<RangeGotoNode &>(stmt);
443 cgFunc.SetCurBBKind(BB::kBBRangeGoto);
444 cgFunc.SelectRangeGoto(rangeGotoNode, *cgFunc.HandleExpr(rangeGotoNode, *rangeGotoNode.Opnd(0)));
445 cgFunc.SetCurBB(*cgFunc.StartNewBB(rangeGotoNode));
446 }
447
HandleComment(StmtNode & stmt,CGFunc & cgFunc)448 void HandleComment(StmtNode &stmt, CGFunc &cgFunc)
449 {
450 if (cgFunc.GetCG()->GenerateVerboseAsm() || cgFunc.GetCG()->GenerateVerboseCG()) {
451 cgFunc.SelectComment(static_cast<CommentNode &>(stmt));
452 }
453 }
454
455 using HandleStmtFactory = FunctionFactory<Opcode, void, StmtNode &, CGFunc &>;
InitHandleStmtFactory()456 static void InitHandleStmtFactory()
457 {
458 RegisterFactoryFunction<HandleStmtFactory>(OP_label, HandleLabel);
459 RegisterFactoryFunction<HandleStmtFactory>(OP_goto, HandleGoto);
460 RegisterFactoryFunction<HandleStmtFactory>(OP_brfalse, HandleCondbr);
461 RegisterFactoryFunction<HandleStmtFactory>(OP_brtrue, HandleCondbr);
462 RegisterFactoryFunction<HandleStmtFactory>(OP_return, HandleReturn);
463 RegisterFactoryFunction<HandleStmtFactory>(OP_call, HandleCall);
464 RegisterFactoryFunction<HandleStmtFactory>(OP_icall, HandleICall);
465 RegisterFactoryFunction<HandleStmtFactory>(OP_icallproto, HandleICall);
466 RegisterFactoryFunction<HandleStmtFactory>(OP_intrinsiccall, HandleIntrinsicCall);
467 RegisterFactoryFunction<HandleStmtFactory>(OP_intrinsiccallassigned, HandleIntrinsicCall);
468 RegisterFactoryFunction<HandleStmtFactory>(OP_intrinsiccallwithtype, HandleIntrinsicCall);
469 RegisterFactoryFunction<HandleStmtFactory>(OP_dassign, HandleDassign);
470 RegisterFactoryFunction<HandleStmtFactory>(OP_regassign, HandleRegassign);
471 RegisterFactoryFunction<HandleStmtFactory>(OP_iassign, HandleIassign);
472 RegisterFactoryFunction<HandleStmtFactory>(OP_rangegoto, HandleRangeGoto);
473 RegisterFactoryFunction<HandleStmtFactory>(OP_comment, HandleComment);
474 }
475
CGFunc(MIRModule & mod,CG & cg,MIRFunction & mirFunc,BECommon & beCommon,MemPool & memPool,StackMemPool & stackMp,MapleAllocator & allocator,uint32 funcId)476 CGFunc::CGFunc(MIRModule &mod, CG &cg, MIRFunction &mirFunc, BECommon &beCommon, MemPool &memPool,
477 StackMemPool &stackMp, MapleAllocator &allocator, uint32 funcId)
478 : bbVec(allocator.Adapter()),
479 referenceVirtualRegs(allocator.Adapter()),
480 pregIdx2Opnd(mirFunc.GetPregTab()->Size(), nullptr, allocator.Adapter()),
481 pRegSpillMemOperands(allocator.Adapter()),
482 spillRegMemOperands(allocator.Adapter()),
483 reuseSpillLocMem(allocator.Adapter()),
484 labelMap(std::less<LabelIdx>(), allocator.Adapter()),
485 vregsToPregsMap(std::less<regno_t>(), allocator.Adapter()),
486 stackMapInsns(allocator.Adapter()),
487 hasVLAOrAlloca(mirFunc.HasVlaOrAlloca()),
488 cg(&cg),
489 mirModule(mod),
490 memPool(&memPool),
491 stackMp(stackMp),
492 func(mirFunc),
493 exitBBVec(allocator.Adapter()),
494 noReturnCallBBVec(allocator.Adapter()),
495 extendSet(allocator.Adapter()),
496 lab2BBMap(allocator.Adapter()),
497 beCommon(beCommon),
498 funcScopeAllocator(&allocator),
499 emitStVec(allocator.Adapter()),
500 switchLabelCnt(allocator.Adapter()),
501 shortFuncName(mirFunc.GetName() + "." + std::to_string(funcId), &memPool)
502 {
503 mirModule.SetCurFunction(&func);
504 dummyBB = CreateNewBB();
505 vReg.SetCount(static_cast<uint32>(kBaseVirtualRegNO + func.GetPregTab()->Size()));
506 firstNonPregVRegNO = vReg.GetCount();
507 /* maximum register count initial be increased by 1024 */
508 SetMaxRegNum(vReg.GetCount() + 1024);
509
510 maplebe::VregInfo::vRegOperandTable.clear();
511
512 insnBuilder = memPool.New<InsnBuilder>(memPool);
513 opndBuilder = memPool.New<OperandBuilder>(memPool, func.GetPregTab()->Size());
514
515 vReg.VRegTableResize(GetMaxRegNum());
516 /* func.GetPregTab()->_preg_table[0] is nullptr, so skip it */
517 DEBUG_ASSERT(func.GetPregTab()->PregFromPregIdx(0) == nullptr, "PregFromPregIdx(0) must be nullptr");
518 for (size_t i = 1; i < func.GetPregTab()->Size(); ++i) {
519 PrimType primType = func.GetPregTab()->PregFromPregIdx(i)->GetPrimType();
520 uint32 byteLen = GetPrimTypeSize(primType);
521 if (byteLen < k4ByteSize) {
522 byteLen = k4ByteSize;
523 }
524 new (&GetVirtualRegNodeFromPseudoRegIdx(i)) VirtualRegNode(GetRegTyFromPrimTy(primType), byteLen);
525 }
526 lSymSize = 0;
527 if (func.GetSymTab()) {
528 lSymSize = func.GetSymTab()->GetSymbolTableSize();
529 }
530 callingConventionKind = CCImpl::GetCallConvKind(mirFunc);
531 }
532
~CGFunc()533 CGFunc::~CGFunc()
534 {
535 mirModule.SetCurFunction(nullptr);
536 }
537
HandleExpr(const BaseNode & parent,BaseNode & expr)538 Operand *CGFunc::HandleExpr(const BaseNode &parent, BaseNode &expr)
539 {
540 auto function = CreateProductFunction<HandleExprFactory>(expr.GetOpCode());
541 CHECK_FATAL(function != nullptr, "unsupported %d opCode in HandleExpr()", expr.GetOpCode());
542 return function(parent, expr, *this);
543 }
544
HandleFirstStmt()545 StmtNode *CGFunc::HandleFirstStmt()
546 {
547 BlockNode *block = func.GetBody();
548
549 DEBUG_ASSERT(block != nullptr, "get func body block failed in CGFunc::GenerateInstruction");
550 StmtNode *stmt = block->GetFirst();
551 if (stmt == nullptr) {
552 return nullptr;
553 }
554 DEBUG_ASSERT(stmt->GetOpCode() == OP_label, "The first statement should be a label");
555 HandleLabel(*stmt, *this);
556 firstBB = curBB;
557 stmt = stmt->GetNext();
558 if (stmt == nullptr) {
559 return nullptr;
560 }
561 curBB = StartNewBBImpl(false, *stmt);
562 return stmt;
563 }
564
RemoveUnreachableBB()565 void CGFunc::RemoveUnreachableBB()
566 {
567 OptimizationPattern *pattern = memPool->New<UnreachBBPattern>(*this);
568 for (BB *bb = firstBB; bb != nullptr; bb = bb->GetNext()) {
569 (void)pattern->Optimize(*bb);
570 }
571 }
572
GenerateInstruction()573 void CGFunc::GenerateInstruction()
574 {
575 InitHandleExprFactory();
576 InitHandleStmtFactory();
577 StmtNode *secondStmt = HandleFirstStmt();
578
579 std::set<uint32> bbFreqSet;
580 for (StmtNode *stmt = secondStmt; stmt != nullptr; stmt = stmt->GetNext()) {
581 GetInsnBuilder()->SetDebugComment(stmt->GetDebugComment());
582 auto function = CreateProductFunction<HandleStmtFactory>(stmt->GetOpCode());
583 CHECK_FATAL(function != nullptr, "unsupported opCode or has been lowered before");
584 function(*stmt, *this);
585 GetInsnBuilder()->ClearDebugComment();
586 }
587
588 /* Set lastbb's frequency */
589 BlockNode *block = func.GetBody();
590 DEBUG_ASSERT(block != nullptr, "get func body block failed in CGFunc::GenerateInstruction");
591 curBB->SetLastStmt(*block->GetLast());
592 lastBB = curBB;
593 }
594
CreateLabel()595 LabelIdx CGFunc::CreateLabel()
596 {
597 MIRSymbol *funcSt = GlobalTables::GetGsymTable().GetSymbolFromStidx(func.GetStIdx().Idx());
598 DEBUG_ASSERT(funcSt != nullptr, "Get func failed at CGFunc::CreateLabel");
599 std::string funcName = funcSt->GetName();
600 std::string labelStr = funcName += std::to_string(labelIdx++);
601 return func.GetOrCreateLableIdxFromName(labelStr);
602 }
603
ProcessExitBBVec()604 void CGFunc::ProcessExitBBVec()
605 {
606 if (exitBBVec.empty()) {
607 BB *retBB = CreateNewBB();
608 retBB->SetKind(BB::kBBReturn);
609 SetLab2BBMap(retBB->GetLabIdx(), *retBB);
610 GetLastBB()->PrependBB(*retBB);
611 exitBBVec.emplace_back(retBB);
612 return;
613 }
614 /* split an empty exitBB */
615 BB *bb = exitBBVec[0];
616 if (bb->NumInsn() > 0) {
617 BB *retBBPart = CreateNewBB(false, BB::kBBFallthru, bb->GetFrequency());
618 DEBUG_ASSERT(retBBPart != nullptr, "retBBPart should not be nullptr");
619 LabelIdx retBBPartLabelIdx = bb->GetLabIdx();
620 if (retBBPartLabelIdx != MIRLabelTable::GetDummyLabel()) {
621 retBBPart->AddLabel(retBBPartLabelIdx);
622 lab2BBMap[retBBPartLabelIdx] = retBBPart;
623 }
624 Insn *insn = bb->GetFirstInsn();
625 while (insn != nullptr) {
626 bb->RemoveInsn(*insn);
627 retBBPart->AppendInsn(*insn);
628 insn = bb->GetFirstInsn();
629 }
630 bb->PrependBB(*retBBPart);
631 LabelIdx newLabelIdx = CreateLabel();
632 bb->AddLabel(newLabelIdx);
633 lab2BBMap[newLabelIdx] = bb;
634 }
635 }
636
AddCommonExitBB()637 void CGFunc::AddCommonExitBB()
638 {
639 if (commonExitBB != nullptr) {
640 return;
641 }
642 // create fake commonExitBB
643 commonExitBB = CreateNewBB(true, BB::kBBFallthru, 0);
644 DEBUG_ASSERT(commonExitBB != nullptr, "cannot create fake commonExitBB");
645 for (BB *cgbb : exitBBVec) {
646 if (!cgbb->IsUnreachable()) {
647 commonExitBB->PushBackPreds(*cgbb);
648 }
649 }
650 }
651
HandleFunction()652 void CGFunc::HandleFunction()
653 {
654 /* select instruction */
655 GenerateInstruction();
656 /* merge multi return */
657 MergeReturn();
658 ProcessExitBBVec();
659 /* build control flow graph */
660 theCFG = memPool->New<CGCFG>(*this);
661 theCFG->BuildCFG();
662 RemoveUnreachableBB();
663 AddCommonExitBB();
664 theCFG->UnreachCodeAnalysis();
665 EraseUnreachableStackMapInsns();
666 }
667
DumpCFG() const668 void CGFunc::DumpCFG() const
669 {
670 #ifdef ARK_LITECG_DEBUG
671 MIRSymbol *funcSt = GlobalTables::GetGsymTable().GetSymbolFromStidx(func.GetStIdx().Idx());
672 DEBUG_ASSERT(funcSt != nullptr, "null ptr check");
673 LogInfo::MapleLogger() << "\n****** CFG built by CG for " << funcSt->GetName() << " *******\n";
674 FOR_ALL_BB_CONST(bb, this)
675 {
676 LogInfo::MapleLogger() << "=== BB ( " << std::hex << bb << std::dec << " ) <" << bb->GetKindName() << "> ===\n";
677 LogInfo::MapleLogger() << "BB id:" << bb->GetId() << "\n";
678 if (!bb->GetPreds().empty()) {
679 LogInfo::MapleLogger() << " pred [ ";
680 for (auto *pred : bb->GetPreds()) {
681 LogInfo::MapleLogger() << pred->GetId() << " ";
682 }
683 LogInfo::MapleLogger() << "]\n";
684 }
685 if (!bb->GetSuccs().empty()) {
686 LogInfo::MapleLogger() << " succ [ ";
687 for (auto *succ : bb->GetSuccs()) {
688 LogInfo::MapleLogger() << succ->GetId() << " ";
689 }
690 LogInfo::MapleLogger() << "]\n";
691 }
692 const StmtNode *stmt = bb->GetFirstStmt();
693 if (stmt != nullptr) {
694 bool done = false;
695 do {
696 done = stmt == bb->GetLastStmt();
697 stmt->Dump(1);
698 LogInfo::MapleLogger() << "\n";
699 stmt = stmt->GetNext();
700 } while (!done);
701 } else {
702 LogInfo::MapleLogger() << "<empty BB>\n";
703 }
704 }
705 #endif
706 }
707
DumpBBInfo(const BB * bb) const708 void CGFunc::DumpBBInfo(const BB *bb) const
709 {
710 #ifdef ARK_LITECG_DEBUG
711 LogInfo::MapleLogger() << "=== BB " << " <" << bb->GetKindName();
712 if (bb->GetLabIdx() != MIRLabelTable::GetDummyLabel()) {
713 LogInfo::MapleLogger() << "[labeled with " << bb->GetLabIdx();
714 LogInfo::MapleLogger() << " ==> @" << func.GetLabelName(bb->GetLabIdx()) << "]";
715 }
716
717 LogInfo::MapleLogger() << "> <" << bb->GetId() << "> ";
718 if (bb->IsCleanup()) {
719 LogInfo::MapleLogger() << "[is_cleanup] ";
720 }
721 if (bb->IsUnreachable()) {
722 LogInfo::MapleLogger() << "[unreachable] ";
723 }
724 if (!bb->GetSuccs().empty()) {
725 LogInfo::MapleLogger() << "succs: ";
726 for (auto *succBB : bb->GetSuccs()) {
727 LogInfo::MapleLogger() << succBB->GetId() << " ";
728 }
729 }
730 if (!bb->GetPreds().empty()) {
731 LogInfo::MapleLogger() << "preds: ";
732 for (auto *predBB : bb->GetPreds()) {
733 LogInfo::MapleLogger() << predBB->GetId() << " ";
734 }
735 }
736 LogInfo::MapleLogger() << "===\n";
737 LogInfo::MapleLogger() << "frequency:" << bb->GetFrequency() << "\n";
738 #endif
739 }
740
DumpCGIR() const741 void CGFunc::DumpCGIR() const
742 {
743 #ifdef ARK_LITECG_DEBUG
744 MIRSymbol *funcSt = GlobalTables::GetGsymTable().GetSymbolFromStidx(func.GetStIdx().Idx());
745 DEBUG_ASSERT(funcSt != nullptr, "null ptr check");
746 LogInfo::MapleLogger() << "\n****** CGIR for " << funcSt->GetName() << " *******\n";
747 FOR_ALL_BB_CONST(bb, this)
748 {
749 if (bb->IsUnreachable()) {
750 continue;
751 }
752 DumpBBInfo(bb);
753 FOR_BB_INSNS_CONST(insn, bb)
754 {
755 insn->Dump();
756 }
757 }
758 #endif
759 }
760
761 // Cgirverify phase function: all insns will be verified before cgemit.
VerifyAllInsn()762 void CGFunc::VerifyAllInsn()
763 {
764 #ifdef ARK_LITECG_DEBUG
765 FOR_ALL_BB(bb, this)
766 {
767 FOR_BB_INSNS(insn, bb)
768 {
769 if (VERIFY_INSN(insn) && insn->CheckMD()) {
770 continue;
771 }
772 LogInfo::MapleLogger() << "Illegal insn is:\n";
773 insn->Dump();
774 LogInfo::MapleLogger() << "Function name is:\n" << GetName() << "\n";
775 CHECK_FATAL_FALSE("The problem is illegal insn, info is above.");
776 }
777 }
778 #endif
779 }
780
PhaseRun(maplebe::CGFunc & f)781 bool CgHandleFunction::PhaseRun(maplebe::CGFunc &f)
782 {
783 f.HandleFunction();
784 return false;
785 }
MAPLE_TRANSFORM_PHASE_REGISTER(CgHandleFunction,handlefunction)786 MAPLE_TRANSFORM_PHASE_REGISTER(CgHandleFunction, handlefunction)
787
788 bool CgVerify::PhaseRun(maplebe::CGFunc &f)
789 {
790 #ifdef ARK_LITECG_DEBUG
791 f.VerifyAllInsn();
792 if (!f.GetCG()->GetCGOptions().DoEmitCode() || f.GetCG()->GetCGOptions().DoDumpCFG()) {
793 f.DumpCFG();
794 }
795 #endif
796 return false;
797 }
798 MAPLE_TRANSFORM_PHASE_REGISTER(CgVerify, cgirverify)
799 } /* namespace maplebe */
800