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