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 #include "aarch64_cfi_generator.h"
16 #include "aarch64_memlayout.h"
17 #include "aarch64_cgfunc.h"
18 namespace maplebe {
GenerateRegisterSaveDirective(BB & bb,Insn & stackDefInsn)19 void AArch64GenCfi::GenerateRegisterSaveDirective(BB &bb, Insn &stackDefInsn)
20 {
21 auto stackFrameSize =
22 static_cast<int32>(static_cast<AArch64MemLayout *>(cgFunc.GetMemlayout())->RealStackFrameSize());
23 auto argsToStkPassSize = static_cast<int32>(cgFunc.GetMemlayout()->SizeOfArgsToStackPass());
24 int32 cfiOffset = stackFrameSize;
25 auto *curInsn = InsertCFIDefCfaOffset(bb, stackDefInsn, cfiOffset);
26 cfiOffset = static_cast<int32>(GetOffsetFromCFA() - argsToStkPassSize);
27 auto &aarchCGFunc = static_cast<AArch64CGFunc &>(cgFunc);
28
29 if (useFP) {
30 curInsn = bb.InsertInsnAfter(*curInsn, aarchCGFunc.CreateCfiOffsetInsn(stackBaseReg, -cfiOffset, k64BitSize));
31 }
32 int32 RLROffset = static_cast<AArch64CGFunc &>(cgFunc).GetStoreFP() ? kOffset8MemPos : 0;
33 curInsn = bb.InsertInsnAfter(
34 *curInsn, aarchCGFunc.CreateCfiOffsetInsn(RLR, static_cast<int64>(-cfiOffset + RLROffset), k64BitSize));
35
36 /* change CFA register and offset */
37 if (useFP) {
38 bool isLmbc = cgFunc.GetMirModule().GetFlavor() == MIRFlavor::kFlavorLmbc;
39 if ((argsToStkPassSize > 0) || isLmbc) {
40 curInsn = bb.InsertInsnAfter(
41 *curInsn, aarchCGFunc.CreateCfiDefCfaInsn(stackBaseReg,
42 static_cast<AArch64MemLayout *>(cgFunc.GetMemlayout())->RealStackFrameSize() -
43 static_cast<uint32>(argsToStkPassSize) + cgFunc.GetFunction().GetFrameReseverdSlot(),
44 k64BitSize));
45 } else {
46 curInsn =
47 bb.InsertInsnAfter(*curInsn, cgFunc.GetInsnBuilder()
48 ->BuildCfiInsn(cfi::OP_CFI_def_cfa_register)
49 .AddOpndChain(cgFunc.CreateCfiRegOperand(stackBaseReg, k64BitSize)));
50 }
51 }
52
53 if (CGOptions::IsNoCalleeCFI()) {
54 return;
55 }
56
57 /* callee save register cfi offset */
58 auto ®sToSave = (aarchCGFunc.GetProEpilogSavedRegs().empty()) ? aarchCGFunc.GetCalleeSavedRegs()
59 : aarchCGFunc.GetProEpilogSavedRegs();
60 if (regsToSave.empty()) {
61 return;
62 }
63
64 auto it = regsToSave.begin();
65 // skip the RFP
66 if (*it == RFP) {
67 ++it;
68 }
69 CHECK_FATAL(*it == RLR, "The second callee saved reg is expected to be RLR");
70 ++it;
71 int32 offset = cgFunc.GetMemlayout()->GetCalleeSaveBaseLoc();
72 for (; it != regsToSave.end(); ++it) {
73 AArch64reg reg = *it;
74 stackFrameSize -= static_cast<int32>(cgFunc.GetMemlayout()->SizeOfArgsToStackPass());
75 cfiOffset = stackFrameSize - offset;
76 curInsn = bb.InsertInsnAfter(*curInsn, aarchCGFunc.CreateCfiOffsetInsn(reg, -cfiOffset, k64BitSize));
77 /* On AArch64, kIntregBytelen == 8 */
78 offset += static_cast<int32>(kAarch64IntregBytelen);
79 }
80 }
81
GenerateRegisterRestoreDirective(BB & bb,Insn & stackRevertInsn)82 void AArch64GenCfi::GenerateRegisterRestoreDirective(BB &bb, Insn &stackRevertInsn)
83 {
84 auto &aarchCGFunc = static_cast<AArch64CGFunc &>(cgFunc);
85 auto ®sToSave = (aarchCGFunc.GetProEpilogSavedRegs().empty()) ? aarchCGFunc.GetCalleeSavedRegs()
86 : aarchCGFunc.GetProEpilogSavedRegs();
87 auto *curInsn = &stackRevertInsn;
88
89 if (!regsToSave.empty()) {
90 auto it = regsToSave.begin();
91 // skip the RFP
92 if (*it == RFP) {
93 ++it;
94 }
95 CHECK_FATAL(*it == RLR, "The second callee saved reg is expected to be RLR");
96 ++it;
97
98 if (!CGOptions::IsNoCalleeCFI()) {
99 for (; it != regsToSave.end(); ++it) {
100 AArch64reg reg = *it;
101 curInsn = bb.InsertInsnAfter(*curInsn, aarchCGFunc.CreateCfiRestoreInsn(reg, k64BitSize));
102 }
103 }
104
105 if (useFP) {
106 curInsn = bb.InsertInsnAfter(*curInsn, aarchCGFunc.CreateCfiRestoreInsn(stackBaseReg, k64BitSize));
107 }
108 curInsn = bb.InsertInsnAfter(*curInsn, aarchCGFunc.CreateCfiRestoreInsn(RLR, k64BitSize));
109 }
110 // in aarch64 R31 is sp
111 bb.InsertInsnAfter(*curInsn, aarchCGFunc.CreateCfiDefCfaInsn(R31, 0, k64BitSize));
112 }
113 } // namespace maplebe
114