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