• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "cgfunc.h"
17 #if DEBUG
18 #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 &regReadNode = 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 &regAssignNode = 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