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 "x64_memlayout.h"
17 #include "x64_call_conv.h"
18 #include "cg.h"
19
20 namespace maplebe {
21 using namespace maple;
22
ComputeStackSpaceRequirementForCall(StmtNode & stmt,int32 & aggCopySize,bool isIcall)23 uint32 X64MemLayout::ComputeStackSpaceRequirementForCall(StmtNode &stmt, int32 &aggCopySize, bool isIcall)
24 {
25 /* instantiate a parm locator */
26 X64CallConvImpl parmLocator(cgFunc->GetBecommon(), X64CallConvImpl::GetCallConvKind(stmt));
27 uint32 sizeOfArgsToStkPass = 0;
28 size_t i = 0;
29 /* An indirect call's first operand is the invocation target */
30 if (isIcall) {
31 ++i;
32 }
33
34 aggCopySize = 0;
35 for (uint32 anum = 0; i < stmt.NumOpnds(); ++i, ++anum) {
36 BaseNode *opnd = stmt.Opnd(i);
37 MIRType *ty = nullptr;
38 ty = GlobalTables::GetTypeTable().GetTypeTable()[static_cast<uint32>(opnd->GetPrimType())];
39 CCLocInfo ploc;
40 aggCopySize += parmLocator.LocateNextParm(*ty, ploc);
41 if (ploc.reg0 != 0) {
42 continue; /* passed in register, so no effect on actual area */
43 }
44 sizeOfArgsToStkPass = RoundUp(ploc.memOffset + ploc.memSize, GetPointerSize());
45 }
46
47 return sizeOfArgsToStkPass;
48 }
49
SetSizeAlignForTypeIdx(uint32 typeIdx,uint32 & size,uint32 & align) const50 void X64MemLayout::SetSizeAlignForTypeIdx(uint32 typeIdx, uint32 &size, uint32 &align) const
51 {
52 align = GlobalTables::GetTypeTable().GetTypeFromTyIdx(typeIdx)->GetAlign();
53 size = GlobalTables::GetTypeTable().GetTypeFromTyIdx(typeIdx)->GetSize();
54 }
55
LayoutFormalParams()56 void X64MemLayout::LayoutFormalParams()
57 {
58 X64CallConvImpl parmLocator(be);
59 CCLocInfo ploc;
60 for (size_t i = 0; i < mirFunction->GetFormalCount(); ++i) {
61 MIRSymbol *sym = mirFunction->GetFormal(i);
62 uint32 stIndex = sym->GetStIndex();
63 X64SymbolAlloc *symLoc = memAllocator->GetMemPool()->New<X64SymbolAlloc>();
64 SetSymAllocInfo(stIndex, *symLoc);
65 if (i == 0) {
66 // The function name here is not appropriate, it should be to determine
67 // whether the function returns a structure less than 16 bytes. At this
68 // time, the first parameter is a structure occupant, which has no
69 // practical significance.
70 if (be.HasFuncReturnType(*mirFunction)) {
71 symLoc->SetMemSegment(GetSegArgsRegPassed());
72 symLoc->SetOffset(GetSegArgsRegPassed().GetSize());
73 continue;
74 }
75 }
76
77 MIRType *ty = mirFunction->GetNthParamType(i);
78 uint32 ptyIdx = ty->GetTypeIndex();
79 parmLocator.LocateNextParm(*ty, ploc, i == 0, mirFunction);
80 uint32 size = 0;
81 uint32 align = 0;
82 if (ploc.reg0 != kRinvalid) {
83 if (!sym->IsPreg()) {
84 SetSizeAlignForTypeIdx(ptyIdx, size, align);
85 symLoc->SetMemSegment(GetSegArgsRegPassed());
86 segArgsRegPassed.SetSize(static_cast<uint32>(RoundUp(segArgsRegPassed.GetSize(), align)));
87 symLoc->SetOffset(segArgsRegPassed.GetSize());
88 segArgsRegPassed.SetSize(segArgsRegPassed.GetSize() + size);
89 }
90 } else {
91 SetSizeAlignForTypeIdx(ptyIdx, size, align);
92 symLoc->SetMemSegment(GetSegArgsStkPassed());
93 segArgsStkPassed.SetSize(static_cast<uint32>(RoundUp(segArgsStkPassed.GetSize(), align)));
94 symLoc->SetOffset(segArgsStkPassed.GetSize());
95 segArgsStkPassed.SetSize(segArgsStkPassed.GetSize() + size);
96 segArgsStkPassed.SetSize(static_cast<uint32>(RoundUp(segArgsStkPassed.GetSize(), GetPointerSize())));
97 }
98 }
99 }
100
LayoutLocalVariables()101 void X64MemLayout::LayoutLocalVariables()
102 {
103 uint32 symTabSize = mirFunction->GetSymTab()->GetSymbolTableSize();
104 for (uint32 i = 0; i < symTabSize; ++i) {
105 MIRSymbol *sym = mirFunction->GetSymTab()->GetSymbolFromStIdx(i);
106 if (sym == nullptr || sym->GetStorageClass() != kScAuto || sym->IsDeleted()) {
107 continue;
108 }
109 uint32 stIndex = sym->GetStIndex();
110 TyIdx tyIdx = sym->GetTyIdx();
111 X64SymbolAlloc *symLoc = memAllocator->GetMemPool()->New<X64SymbolAlloc>();
112 SetSymAllocInfo(stIndex, *symLoc);
113 CHECK_FATAL(!symLoc->IsRegister(), "expect not register");
114
115 symLoc->SetMemSegment(segLocals);
116 MIRType *ty = GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx);
117 uint32 align = ty->GetAlign();
118 segLocals.SetSize(static_cast<uint32>(RoundUp(segLocals.GetSize(), align)));
119 symLoc->SetOffset(segLocals.GetSize());
120 segLocals.SetSize(segLocals.GetSize() + GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx)->GetSize());
121 }
122 }
123
AssignSpillLocationsToPseudoRegisters()124 void X64MemLayout::AssignSpillLocationsToPseudoRegisters()
125 {
126 MIRPregTable *pregTab = cgFunc->GetFunction().GetPregTab();
127
128 /* BUG: n_regs include index 0 which is not a valid preg index. */
129 size_t nRegs = pregTab->Size();
130 spillLocTable.resize(nRegs);
131 for (size_t i = 1; i < nRegs; ++i) {
132 PrimType pType = pregTab->PregFromPregIdx(i)->GetPrimType();
133 X64SymbolAlloc *symLoc = memAllocator->GetMemPool()->New<X64SymbolAlloc>();
134 symLoc->SetMemSegment(segLocals);
135 segLocals.SetSize(RoundUp(segLocals.GetSize(), GetPrimTypeSize(pType)));
136 symLoc->SetOffset(segLocals.GetSize());
137 MIRType *mirTy = GlobalTables::GetTypeTable().GetTypeTable()[pType];
138 segLocals.SetSize(segLocals.GetSize() + mirTy->GetSize());
139 spillLocTable[i] = symLoc;
140 }
141 }
142
LayoutReturnRef(int32 & structCopySize,int32 & maxParmStackSize)143 void X64MemLayout::LayoutReturnRef(int32 &structCopySize, int32 &maxParmStackSize)
144 {
145 segArgsToStkPass.SetSize(FindLargestActualArea(structCopySize));
146 maxParmStackSize = static_cast<int32>(segArgsToStkPass.GetSize());
147 if (Globals::GetInstance()->GetOptimLevel() == CGOptions::kLevel0) {
148 AssignSpillLocationsToPseudoRegisters();
149 }
150 segLocals.SetSize(static_cast<uint32>(RoundUp(segLocals.GetSize(), GetPointerSize())));
151 }
152
LayoutStackFrame(int32 & structCopySize,int32 & maxParmStackSize)153 void X64MemLayout::LayoutStackFrame(int32 &structCopySize, int32 &maxParmStackSize)
154 {
155 LayoutFormalParams();
156
157 // Need to be aligned ?
158 segArgsRegPassed.SetSize(RoundUp(segArgsRegPassed.GetSize(), GetPointerSize()));
159 segArgsStkPassed.SetSize(RoundUp(segArgsStkPassed.GetSize(), GetPointerSize() + GetPointerSize()));
160
161 /* allocate the local variables in the stack */
162 LayoutLocalVariables();
163 LayoutReturnRef(structCopySize, maxParmStackSize);
164
165 // Need to adapt to the cc interface.
166 structCopySize = 0;
167 // Scenes with more than 6 parameters are not yet enabled.
168 maxParmStackSize = 0;
169
170 cgFunc->SetUseFP(cgFunc->UseFP() || static_cast<int32>(StackFrameSize()) > kMaxPimm32);
171 }
172
StackFrameSize() const173 uint64 X64MemLayout::StackFrameSize() const
174 {
175 uint64 total = Locals().GetSize() + segArgsRegPassed.GetSize() + segArgsToStkPass.GetSize() +
176 segGrSaveArea.GetSize() + segVrSaveArea.GetSize() + segSpillReg.GetSize() +
177 cgFunc->GetFunction().GetFrameReseverdSlot(); // frame reserved slot
178 return RoundUp(total, stackPtrAlignment);
179 }
180
GetGRSaveAreaBaseLoc()181 int32 X64MemLayout::GetGRSaveAreaBaseLoc()
182 {
183 int32 total = static_cast<int32>(RoundUp(GetSizeOfGRSaveArea(), stackPtrAlignment));
184 return total;
185 }
186
GetVRSaveAreaBaseLoc()187 int32 X64MemLayout::GetVRSaveAreaBaseLoc()
188 {
189 int32 total = static_cast<int32>(RoundUp(GetSizeOfGRSaveArea(), stackPtrAlignment) +
190 RoundUp(GetSizeOfVRSaveArea(), stackPtrAlignment));
191 return total;
192 }
193 } /* namespace maplebe */
194