1 /*
2 * Copyright (c) 2021-2024 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 "codegen_native.h"
17 #include "optimizer/code_generator/method_properties.h"
18
19 namespace ark::compiler {
20
CreateFrameInfo()21 void CodegenNative::CreateFrameInfo()
22 {
23 auto &fl = GetFrameLayout();
24 auto frame = GetGraph()->GetLocalAllocator()->New<FrameInfo>(
25 FrameInfo::PositionedCallers::Encode(true) | FrameInfo::PositionedCallees::Encode(true) |
26 FrameInfo::CallersRelativeFp::Encode(false) | FrameInfo::CalleesRelativeFp::Encode(true));
27 frame->SetFrameSize(fl.GetFrameSize<CFrameLayout::OffsetUnit::BYTES>());
28 frame->SetSpillsCount(fl.GetSpillsCount());
29
30 frame->SetCallersOffset(fl.GetOffset<CFrameLayout::OffsetOrigin::SP, CFrameLayout::OffsetUnit::SLOTS>(
31 fl.GetStackStartSlot() + fl.GetCallerLastSlot(false)));
32 frame->SetFpCallersOffset(fl.GetOffset<CFrameLayout::OffsetOrigin::SP, CFrameLayout::OffsetUnit::SLOTS>(
33 fl.GetStackStartSlot() + fl.GetCallerLastSlot(true)));
34 frame->SetCalleesOffset(-fl.GetOffset<CFrameLayout::OffsetOrigin::FP, CFrameLayout::OffsetUnit::SLOTS>(
35 fl.GetStackStartSlot() + fl.GetCalleeLastSlot(false)));
36 frame->SetFpCalleesOffset(-fl.GetOffset<CFrameLayout::OffsetOrigin::FP, CFrameLayout::OffsetUnit::SLOTS>(
37 fl.GetStackStartSlot() + fl.GetCalleeLastSlot(true)));
38
39 ASSERT(!GetGraph()->GetMethodProperties().GetRequireFrameSetup());
40 // we don't need to setup frame in native mode
41 frame->SetSetupFrame(false);
42 // we don't need to save FP and LR registers only for leaf methods
43 frame->SetSaveFrameAndLinkRegs(!GetGraph()->GetMethodProperties().IsLeaf());
44 // we may use lr reg as temp only if we saved lr in the prologue
45 if (GetTarget().SupportLinkReg()) {
46 GetEncoder()->EnableLrAsTempReg(frame->GetSaveFrameAndLinkRegs());
47 }
48 // we never need to save unused registers in native mode
49 frame->SetSaveUnusedCalleeRegs(false);
50 // we have to sub/add SP in prologue/epilogue in the following cases:
51 // - non-leaf method
52 // - leaf method and there are spills or parameters on stack
53 frame->SetAdjustSpReg(!GetGraph()->GetMethodProperties().IsLeaf() || GetGraph()->GetStackSlotsCount() != 0 ||
54 GetGraph()->GetMethodProperties().GetHasParamsOnStack());
55 SetFrameInfo(frame);
56 }
57
GeneratePrologue()58 void CodegenNative::GeneratePrologue()
59 {
60 SCOPED_DISASM_STR(this, "Method Prologue");
61
62 GetCallingConvention()->GenerateNativePrologue(*GetFrameInfo());
63
64 #if defined(EVENT_METHOD_ENTER_ENABLED) && EVENT_METHOD_ENTER_ENABLED != 0
65 MakeTrace();
66 #endif
67 }
68
GenerateEpilogue()69 void CodegenNative::GenerateEpilogue()
70 {
71 ASSERT(GetGraph()->GetMethodProperties().IsLeaf());
72 SCOPED_DISASM_STR(this, "Method Epilogue");
73
74 #if defined(EVENT_METHOD_EXIT_ENABLED) && EVENT_METHOD_EXIT_ENABLED != 0
75 GetCallingConvention()->GenerateNativeEpilogue(*GetFrameInfo(), MakeTrace);
76 #else
77 GetCallingConvention()->GenerateNativeEpilogue(*GetFrameInfo(), []() {});
78 #endif
79 }
80 } // namespace ark::compiler
81