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 AssignSpillLocationsToPseudoRegisters()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 GetCalleeSaveBaseLoc() const override; 209 210 private: 211 MemSegment segRefLocals = MemSegment(kMsRefLocals); 212 /* callee saved register R19-R28 (10) */ 213 MemSegment segLocals = MemSegment(kMsLocals); /* these are accessed via Frame Pointer */ 214 MemSegment segGrSaveArea = MemSegment(kMsGrSaveArea); 215 MemSegment segVrSaveArea = MemSegment(kMsVrSaveArea); 216 int32 fixStackSize = 0; 217 void SetSizeAlignForTypeIdx(uint32 typeIdx, uint32 &size, uint32 &align) const; 218 void LayoutFormalParams(); 219 void LayoutActualParams(); 220 void LayoutLocalVariables(std::vector<MIRSymbol *> &tempVar, std::vector<MIRSymbol *> &returnDelays); 221 void LayoutEAVariales(std::vector<MIRSymbol *> &tempVar); 222 void LayoutReturnRef(std::vector<MIRSymbol *> &returnDelays, int32 &structCopySize, int32 &maxParmStackSize); 223 // layout small local near sp, otherwise, above spill region 224 void LayoutLocalsInSize(const MIRSymbol &mirSym); 225 CreateSymbolAlloc()226 SymbolAlloc *CreateSymbolAlloc() const override 227 { 228 return memAllocator->GetMemPool()->New<AArch64SymbolAlloc>(); 229 } 230 }; 231 } /* namespace maplebe */ 232 233 #endif /* MAPLEBE_INCLUDE_CG_AARCH64_AARCH64_MEMLAYOUT_H */ 234