• 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 "aarch64_args.h"
17 #include <fstream>
18 #include "aarch64_cgfunc.h"
19 #include "aarch64_cg.h"
20 
21 namespace maplebe {
22 using namespace maple;
23 
Run()24 void AArch64MoveRegArgs::Run()
25 {
26     BB *formerCurBB = aarFunc->GetCurBB();
27     MoveVRegisterArgs();
28     MoveRegisterArgs();
29     aarFunc->SetCurBB(*formerCurBB);
30 }
31 
MoveRegisterArgs() const32 void AArch64MoveRegArgs::MoveRegisterArgs() const
33 {
34     aarFunc->GetDummyBB()->ClearInsns();
35     aarFunc->SetCurBB(*aarFunc->GetDummyBB());
36 
37     auto &mirFunc = aarFunc->GetFunction();
38     CCImpl &parmlocator =
39         *static_cast<AArch64CGFunc *>(cgFunc)->GetOrCreateLocator(CCImpl::GetCallConvKind(cgFunc->GetFunction()));
40     CCLocInfo ploc;
41     for (uint32 i = 0; i < mirFunc.GetFormalCount(); ++i) {
42         MIRType *ty = mirFunc.GetNthParamType(i);
43         parmlocator.LocateNextParm(*ty, ploc, i == 0, mirFunc.GetMIRFuncType());
44         if (ploc.reg0 == kRinvalid) {
45             continue;
46         }
47         auto *sym = mirFunc.GetFormal(i);
48         if (sym->IsPreg()) {
49             continue;
50         }
51         auto *symLoc = aarFunc->GetMemlayout()->GetSymAllocInfo(sym->GetStIndex());
52         auto *baseOpnd = aarFunc->GetBaseReg(*symLoc);
53         auto offset = aarFunc->GetBaseOffset(*symLoc);
54         auto generateStrInsn = [this, baseOpnd, &offset, sym, symLoc](AArch64reg reg, PrimType primType) {
55             RegOperand &regOpnd = aarFunc->GetOrCreatePhysicalRegisterOperand(reg, GetPrimTypeBitSize(primType),
56                                                                               aarFunc->GetRegTyFromPrimTy(primType));
57             OfstOperand &ofstOpnd =
58                 aarFunc->CreateOfstOpnd(static_cast<uint64>(static_cast<int64>(offset)), k32BitSize);
59             AArch64MemLayout *memLayout = static_cast<AArch64MemLayout *>(aarFunc->GetMemlayout());
60             if (memLayout->IsSegMentVaried(symLoc->GetMemSegment())) {
61                 ofstOpnd.SetVary(kUnAdjustVary);
62             }
63             auto *memOpnd = aarFunc->CreateMemOperand(GetPrimTypeBitSize(primType), *baseOpnd, ofstOpnd, false);
64 
65             MOperator mOp = aarFunc->PickStInsn(GetPrimTypeBitSize(primType), primType);
66             Insn &insn = aarFunc->GetInsnBuilder()->BuildInsn(mOp, regOpnd, *memOpnd);
67             if (aarFunc->GetCG()->GenerateVerboseCG()) {
68                 insn.SetComment(std::string("store param: ").append(sym->GetName()));
69             }
70             aarFunc->GetCurBB()->AppendInsn(insn);
71             offset += static_cast<int32>(GetPrimTypeSize(primType));
72         };
73         generateStrInsn(static_cast<AArch64reg>(ploc.GetReg0()), ploc.GetPrimTypeOfReg0());
74         if (ploc.GetReg1() != kRinvalid) {
75             generateStrInsn(static_cast<AArch64reg>(ploc.GetReg1()), ploc.GetPrimTypeOfReg1());
76         }
77         if (ploc.GetReg2() != kRinvalid) {
78             generateStrInsn(static_cast<AArch64reg>(ploc.GetReg2()), ploc.GetPrimTypeOfReg2());
79         }
80         if (ploc.GetReg3() != kRinvalid) {
81             generateStrInsn(static_cast<AArch64reg>(ploc.GetReg3()), ploc.GetPrimTypeOfReg3());
82         }
83     }
84 
85     if (cgFunc->GetCG()->IsLmbc() && (cgFunc->GetSpSaveReg() != 0)) {
86         /* lmbc uses vreg act as SP when alloca is present due to usage of FP for - offset */
87         aarFunc->GetFirstBB()->InsertAtEnd(*aarFunc->GetDummyBB());
88     } else {
89         aarFunc->GetFirstBB()->InsertAtBeginning(*aarFunc->GetDummyBB());
90     }
91 }
92 
MoveLocalRefVarToRefLocals(MIRSymbol & mirSym) const93 void AArch64MoveRegArgs::MoveLocalRefVarToRefLocals(MIRSymbol &mirSym) const
94 {
95     AArch64CGFunc *aarFunc = static_cast<AArch64CGFunc *>(cgFunc);
96     PrimType stype = mirSym.GetType()->GetPrimType();
97     uint32 byteSize = GetPrimTypeSize(stype);
98     uint32 bitSize = byteSize * kBitsPerByte;
99     MemOperand &memOpnd = aarFunc->GetOrCreateMemOpnd(mirSym, 0, bitSize, true);
100     RegOperand *regOpnd = nullptr;
101     if (mirSym.IsPreg()) {
102         PregIdx pregIdx = aarFunc->GetFunction().GetPregTab()->GetPregIdxFromPregno(
103             static_cast<uint32>(mirSym.GetPreg()->GetPregNo()));
104         regOpnd = &aarFunc->GetOrCreateVirtualRegisterOperand(aarFunc->GetVirtualRegNOFromPseudoRegIdx(pregIdx));
105     } else {
106         regOpnd = &aarFunc->GetOrCreateVirtualRegisterOperand(aarFunc->NewVReg(kRegTyInt, k8ByteSize));
107     }
108     Insn &insn =
109         aarFunc->GetInsnBuilder()->BuildInsn(aarFunc->PickLdInsn(GetPrimTypeBitSize(stype), stype), *regOpnd, memOpnd);
110     MemOperand &memOpnd1 = aarFunc->GetOrCreateMemOpnd(mirSym, 0, bitSize, false);
111     Insn &insn1 =
112         aarFunc->GetInsnBuilder()->BuildInsn(aarFunc->PickStInsn(GetPrimTypeBitSize(stype), stype), *regOpnd, memOpnd1);
113     aarFunc->GetCurBB()->InsertInsnBegin(insn1);
114     aarFunc->GetCurBB()->InsertInsnBegin(insn);
115 }
116 
LoadStackArgsToVReg(MIRSymbol & mirSym) const117 void AArch64MoveRegArgs::LoadStackArgsToVReg(MIRSymbol &mirSym) const
118 {
119     AArch64CGFunc *aarFunc = static_cast<AArch64CGFunc *>(cgFunc);
120     PrimType stype = mirSym.GetType()->GetPrimType();
121     uint32 byteSize = GetPrimTypeSize(stype);
122     uint32 bitSize = byteSize * kBitsPerByte;
123     MemOperand &memOpnd = aarFunc->GetOrCreateMemOpnd(mirSym, 0, bitSize);
124     PregIdx pregIdx =
125         aarFunc->GetFunction().GetPregTab()->GetPregIdxFromPregno(static_cast<uint32>(mirSym.GetPreg()->GetPregNo()));
126     RegOperand &dstRegOpnd =
127         aarFunc->GetOrCreateVirtualRegisterOperand(aarFunc->GetVirtualRegNOFromPseudoRegIdx(pregIdx));
128     Insn &insn = aarFunc->GetInsnBuilder()->BuildInsn(aarFunc->PickLdInsn(GetPrimTypeBitSize(stype), stype), dstRegOpnd,
129                                                       memOpnd);
130 
131     if (aarFunc->GetCG()->GenerateVerboseCG()) {
132         std::string key = "param: %%";
133         key += std::to_string(mirSym.GetPreg()->GetPregNo());
134         DEBUG_ASSERT(mirSym.GetStorageClass() == kScFormal, "vreg parameters should be kScFormal type.");
135         insn.SetComment(key);
136     }
137 
138     aarFunc->GetCurBB()->InsertInsnBegin(insn);
139 }
140 
MoveArgsToVReg(const CCLocInfo & ploc,MIRSymbol & mirSym) const141 void AArch64MoveRegArgs::MoveArgsToVReg(const CCLocInfo &ploc, MIRSymbol &mirSym) const
142 {
143     // when args parameter type i128, reg1 will be used.
144     // but, i128 is not supported in back-end
145     CHECK_FATAL(ploc.reg2 == kRinvalid, "NIY");
146     RegType regType = (ploc.reg0 < V0) ? kRegTyInt : kRegTyFloat;
147     PrimType sType = mirSym.GetType()->GetPrimType();
148     uint32 byteSize = GetPrimTypeSize(sType);
149     uint32 srcBitSize = ((byteSize < k4ByteSize) ? k4ByteSize : byteSize) * kBitsPerByte;
150     PregIdx pregIdx =
151         aarFunc->GetFunction().GetPregTab()->GetPregIdxFromPregno(static_cast<uint32>(mirSym.GetPreg()->GetPregNo()));
152     RegOperand &dstRegOpnd =
153         aarFunc->GetOrCreateVirtualRegisterOperand(aarFunc->GetVirtualRegNOFromPseudoRegIdx(pregIdx));
154     dstRegOpnd.SetSize(srcBitSize);
155     RegOperand &srcRegOpnd =
156         aarFunc->GetOrCreatePhysicalRegisterOperand(static_cast<AArch64reg>(ploc.reg0), srcBitSize, regType);
157     DEBUG_ASSERT(mirSym.GetStorageClass() == kScFormal, "should be args");
158     MOperator mOp = aarFunc->PickMovBetweenRegs(sType, sType);
159     if (mOp == MOP_vmovvv || mOp == MOP_vmovuu) {
160         auto &vInsn = aarFunc->GetInsnBuilder()->BuildVectorInsn(mOp, AArch64CG::kMd[mOp]);
161         (void)vInsn.AddOpndChain(dstRegOpnd).AddOpndChain(srcRegOpnd);
162         auto *vecSpec1 = aarFunc->GetMemoryPool()->New<VectorRegSpec>(srcBitSize >> k3ByteSize, k8BitSize);
163         auto *vecSpec2 = aarFunc->GetMemoryPool()->New<VectorRegSpec>(srcBitSize >> k3ByteSize, k8BitSize);
164         (void)vInsn.PushRegSpecEntry(vecSpec1).PushRegSpecEntry(vecSpec2);
165         aarFunc->GetCurBB()->InsertInsnBegin(vInsn);
166         return;
167     }
168     Insn &insn = CreateMoveArgsToVRegInsn(mOp, dstRegOpnd, srcRegOpnd, sType);
169     if (aarFunc->GetCG()->GenerateVerboseCG()) {
170         std::string str = "param: %%";
171         str += std::to_string(mirSym.GetPreg()->GetPregNo());
172         insn.SetComment(str);
173     }
174     aarFunc->GetCurBB()->InsertInsnBegin(insn);
175 }
176 
CreateMoveArgsToVRegInsn(MOperator mOp,RegOperand & destOpnd,RegOperand & srcOpnd,PrimType primType) const177 Insn &AArch64MoveRegArgs::CreateMoveArgsToVRegInsn(MOperator mOp, RegOperand &destOpnd, RegOperand &srcOpnd,
178                                                    PrimType primType) const
179 {
180     if (mOp == MOP_wmovrr || mOp == MOP_xmovrr) {
181         /* callee ensure the validbit of parameters of function */
182         switch (primType) {
183             case PTY_u1: {
184                 ImmOperand &lsbOpnd = aarFunc->CreateImmOperand(maplebe::k0BitSize, srcOpnd.GetSize(), false);
185                 ImmOperand &widthOpnd = aarFunc->CreateImmOperand(maplebe::k1BitSize, srcOpnd.GetSize(), false);
186                 bool is64Bit = (srcOpnd.GetSize() == maplebe::k64BitSize);
187                 return aarFunc->GetInsnBuilder()->BuildInsn(is64Bit ? MOP_xubfxrri6i6 : MOP_wubfxrri5i5, destOpnd,
188                                                             srcOpnd, lsbOpnd, widthOpnd);
189             }
190             case PTY_u8:
191             case PTY_i8:
192                 return aarFunc->GetInsnBuilder()->BuildInsn(MOP_xuxtb32, destOpnd, srcOpnd);
193             case PTY_u16:
194             case PTY_i16:
195                 return aarFunc->GetInsnBuilder()->BuildInsn(MOP_xuxth32, destOpnd, srcOpnd);
196             case PTY_u32:
197             case PTY_i32: {
198                 destOpnd.SetValidBitsNum(maplebe::k64BitSize);
199                 return aarFunc->GetInsnBuilder()->BuildInsn(MOP_xuxtw64, destOpnd, srcOpnd);
200             }
201             default:
202                 return aarFunc->GetInsnBuilder()->BuildInsn(mOp, destOpnd, srcOpnd);
203         }
204     } else {
205         return aarFunc->GetInsnBuilder()->BuildInsn(mOp, destOpnd, srcOpnd);
206     }
207 }
208 
MoveVRegisterArgs()209 void AArch64MoveRegArgs::MoveVRegisterArgs()
210 {
211     aarFunc->GetDummyBB()->ClearInsns();
212     aarFunc->SetCurBB(*aarFunc->GetDummyBB());
213     CCImpl &parmlocator =
214         *static_cast<AArch64CGFunc *>(cgFunc)->GetOrCreateLocator(CCImpl::GetCallConvKind(cgFunc->GetFunction()));
215     CCLocInfo ploc;
216 
217     auto &mirFunc = aarFunc->GetFunction();
218     for (size_t i = 0; i < mirFunc.GetFormalCount(); ++i) {
219         MIRType *ty = mirFunc.GetNthParamType(i);
220         parmlocator.LocateNextParm(*ty, ploc, (i == 0), mirFunc.GetMIRFuncType());
221         MIRSymbol *sym = mirFunc.GetFormal(i);
222 
223         /* load locarefvar formals to store in the reflocals. */
224         if (mirFunc.GetNthParamAttr(i).GetAttr(ATTR_localrefvar) && ploc.reg0 == kRinvalid) {
225             MoveLocalRefVarToRefLocals(*sym);
226         }
227 
228         if (!sym->IsPreg()) {
229             continue;
230         }
231 
232         if (ploc.reg0 == kRinvalid) {
233             /* load stack parameters to the vreg. */
234             LoadStackArgsToVReg(*sym);
235         } else {
236             MoveArgsToVReg(ploc, *sym);
237         }
238     }
239 
240     if (cgFunc->GetCG()->IsLmbc() && (cgFunc->GetSpSaveReg() != 0)) {
241         /* lmbc uses vreg act as SP when alloca is present due to usage of FP for - offset */
242         aarFunc->GetFirstBB()->InsertAtEnd(*aarFunc->GetDummyBB());
243     } else {
244         aarFunc->GetFirstBB()->InsertAtBeginning(*aarFunc->GetDummyBB());
245     }
246 }
247 } /* namespace maplebe */
248