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