• 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 #ifndef MAPLEBE_INCLUDE_CG_AARCH64_AARCH64_MEMLAYOUT_H
17 #define MAPLEBE_INCLUDE_CG_AARCH64_AARCH64_MEMLAYOUT_H
18 
19 #include "memlayout.h"
20 #include "aarch64_abi.h"
21 
22 namespace maplebe {
23 class AArch64SymbolAlloc : public SymbolAlloc {
24 public:
25     AArch64SymbolAlloc() = default;
26 
27     ~AArch64SymbolAlloc() = default;
28 
SetRegisters(AArch64reg r0,AArch64reg r1,AArch64reg r2,AArch64reg r3)29     void SetRegisters(AArch64reg r0, AArch64reg r1, AArch64reg r2, AArch64reg r3)
30     {
31         reg0 = r0;
32         reg1 = r1;
33         reg2 = r2;
34         reg3 = r3;
35     }
36 
IsRegister()37     inline bool IsRegister() const
38     {
39         return reg0 != kRinvalid;
40     }
41 
42 private:
43     AArch64reg reg0 = kRinvalid;
44     AArch64reg reg1 = kRinvalid;
45     AArch64reg reg2 = kRinvalid;
46     AArch64reg reg3 = kRinvalid;
47 };
48 
49 /*
50  * On AArch64, stack frames are structured as follows:
51  *
52  * The stack grows downward -- full descending (SP points
53  * to a filled slot).
54  *
55  * Any of the parts of a frame is optional, i.e., it is
56  * possible to write a caller-callee pair in such a way
57  * that the particular part is absent in the frame.
58  *
59  * Before a call is made, the frame looks like:
60  * |                            |
61  * ||----------------------------|
62  * | args passed on the stack   | (we call them up-formals)
63  * ||----------------------------|<- Stack Pointer
64  * |                            |
65  *
66  * V1.
67  * Right after a call is made
68  * |                            |
69  * ||----------------------------|
70  * | args passed on the stack   |
71  * ||----------------------------|<- Stack Pointer
72  * | PREV_FP, PREV_LR           |
73  * ||----------------------------|<- Frame Pointer
74  *
75  * After the prologue has run,
76  * |                            |
77  * ||----------------------------|
78  * | args passed on the stack   |
79  * ||----------------------------|
80  * | PREV_FP, PREV_LR           |
81  * ||----------------------------|<- Frame Pointer
82  * | callee-saved registers     |
83  * ||----------------------------|
84  * | empty space. should have   |
85  * | at least 16-byte alignment |
86  * ||----------------------------|
87  * | local variables            |
88  * ||----------------------------|
89  * | variable-sized local vars  |
90  * | (VLAs)                     |
91  * ||----------------------------|<- Stack Pointer
92  *
93  * callee-saved registers include
94  *  1. R19-R28
95  *  2. R8 if return value needs to be returned
96  *     thru memory and callee wants to use R8
97  *  3. we don't need to save R19 if it is used
98  *     as base register for PIE.
99  *  4. V8-V15
100  *
101  * V2. (this way, we may be able to save
102  *     on SP modifying instruction)
103  * Right after a call is made
104  * |                            |
105  * ||----------------------------|
106  * | args passed on the stack   |
107  * ||----------------------------|<- Stack Pointer
108  * |                            |
109  * | empty space                |
110  * |                            |
111  * ||----------------------------|
112  * | PREV_FP, PREV_LR           |
113  * ||----------------------------|<- Frame Pointer
114  *
115  * After the prologue has run,
116  * |                            |
117  * ||----------------------------|
118  * | args passed on the stack   |
119  * ||----------------------------|
120  * | callee-saved registers     |
121  * | including those used for   |
122  * | parameter passing          |
123  * ||----------------------------|
124  * | empty space. should have   |
125  * | at least 16-byte alignment |
126  * ||----------------------------|
127  * | local variables            |
128  * ||----------------------------|
129  * | PREV_FP, PREV_LR           |
130  * ||----------------------------|<- Frame Pointer
131  * | variable-sized local vars  |
132  * | (VLAs)                     |
133  * ||----------------------------|
134  * | args to pass through stack |
135  * ||----------------------------|
136  */
137 class AArch64MemLayout : public MemLayout {
138 public:
AArch64MemLayout(BECommon & b,MIRFunction & f,MapleAllocator & mallocator)139     AArch64MemLayout(BECommon &b, MIRFunction &f, MapleAllocator &mallocator)
140         : MemLayout(b, f, mallocator, kAarch64StackPtrAlignment)
141     {
142     }
143 
144     ~AArch64MemLayout() override = default;
145 
146     /*
147      * Returns stack space required for a call
148      * which is used to pass arguments that cannot be
149      * passed through registers
150      */
151     uint32 ComputeStackSpaceRequirementForCall(StmtNode &stmt, int32 &aggCopySize, bool isIcall) override;
152 
153     void LayoutStackFrame(int32 &structCopySize, int32 &maxParmStackSize) override;
154 
155     void AssignSpillLocationsToPseudoRegisters() override;
156 
157     uint64 StackFrameSize() const;
158 
159     uint32 RealStackFrameSize() const;
160 
Locals()161     const MemSegment &Locals() const
162     {
163         return segLocals;
164     }
165 
GetSizeOfSpillReg()166     uint32 GetSizeOfSpillReg() const
167     {
168         return segSpillReg.GetSize();
169     }
170 
GetSizeOfLocals()171     uint32 GetSizeOfLocals() const
172     {
173         return segLocals.GetSize();
174     }
175 
GetSizeOfCold()176     uint32 GetSizeOfCold() const
177     {
178         return segCold.GetSize();
179     }
180 
SetSizeOfGRSaveArea(uint32 sz)181     void SetSizeOfGRSaveArea(uint32 sz)
182     {
183         segGrSaveArea.SetSize(sz);
184     }
185 
GetSizeOfGRSaveArea()186     uint32 GetSizeOfGRSaveArea() const
187     {
188         return segGrSaveArea.GetSize();
189     }
190 
SetSizeOfVRSaveArea(uint32 sz)191     inline void SetSizeOfVRSaveArea(uint32 sz)
192     {
193         segVrSaveArea.SetSize(sz);
194     }
195 
GetSizeOfVRSaveArea()196     uint32 GetSizeOfVRSaveArea() const
197     {
198         return segVrSaveArea.GetSize();
199     }
200 
GetSizeOfRefLocals()201     uint32 GetSizeOfRefLocals() const
202     {
203         return segRefLocals.GetSize();
204     }
205 
206     uint64 GetSizeOfColdToStk() const;
207     bool IsSegMentVaried(const MemSegment *seg) const;
208     int32 GetRefLocBaseLoc() const;
209     int32 GetGRSaveAreaBaseLoc() const;
210     int32 GetVRSaveAreaBaseLoc() const;
211     int32 GetCalleeSaveBaseLoc() const override;
212 
213 private:
214     MemSegment segRefLocals = MemSegment(kMsRefLocals);
215     /* callee saved register R19-R28 (10) */
216     MemSegment segLocals = MemSegment(kMsLocals); /* these are accessed via Frame Pointer */
217     MemSegment segGrSaveArea = MemSegment(kMsGrSaveArea);
218     MemSegment segVrSaveArea = MemSegment(kMsVrSaveArea);
219     int32 fixStackSize = 0;
220     void SetSizeAlignForTypeIdx(uint32 typeIdx, uint32 &size, uint32 &align) const;
221     void SetSegmentSize(AArch64SymbolAlloc &symbolAlloc, MemSegment &segment, uint32 typeIdx) const;
222     void LayoutVarargParams();
223     void LayoutFormalParams();
224     void LayoutActualParams();
225     void LayoutLocalVariables(std::vector<MIRSymbol *> &tempVar, std::vector<MIRSymbol *> &returnDelays);
226     void LayoutEAVariales(std::vector<MIRSymbol *> &tempVar);
227     void LayoutReturnRef(std::vector<MIRSymbol *> &returnDelays, int32 &structCopySize, int32 &maxParmStackSize);
228     // layout small local near sp, otherwise, above spill region
229     void LayoutLocalsInSize(const MIRSymbol &mirSym);
230 
CreateSymbolAlloc()231     SymbolAlloc *CreateSymbolAlloc() const override
232     {
233         return memAllocator->GetMemPool()->New<AArch64SymbolAlloc>();
234     }
235 };
236 } /* namespace maplebe */
237 
238 #endif /* MAPLEBE_INCLUDE_CG_AARCH64_AARCH64_MEMLAYOUT_H */
239