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 #ifndef PANDA_FRAME_INFO_H 17 #define PANDA_FRAME_INFO_H 18 19 #include "libpandabase/utils/cframe_layout.h" 20 #include "libpandabase/utils/bit_field.h" 21 #include "libpandabase/mem/mem.h" 22 23 namespace ark::compiler { 24 25 class Encoder; 26 class Graph; 27 28 /// This class describes layout of the frame being compiled. 29 class FrameInfo { 30 public: FrameInfo(uint32_t fields)31 explicit FrameInfo(uint32_t fields) : fields_(fields) {} 32 ~FrameInfo() = default; 33 NO_COPY_SEMANTIC(FrameInfo); 34 NO_MOVE_SEMANTIC(FrameInfo); 35 36 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 37 #define FRAME_INFO_GET_ATTR(name, var) \ 38 auto Get##name() const \ 39 { \ 40 /* CC-OFFNXT(G.PRE.05) function gen */ \ 41 return var; \ 42 } 43 44 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 45 #define FRAME_INFO_SET_ATTR(name, var) \ 46 void Set##name(ssize_t val) \ 47 { \ 48 ASSERT(val <= std::numeric_limits<decltype(var)>::max()); \ 49 ASSERT(val >= std::numeric_limits<decltype(var)>::min()); \ 50 var = val; \ 51 } 52 53 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 54 #define FRAME_INFO_ATTR(name, var) \ 55 FRAME_INFO_GET_ATTR(name, var) \ 56 FRAME_INFO_SET_ATTR(name, var) 57 58 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 59 #define FRAME_INFO_GET_FIELD(name, type) \ 60 type Get##name() const \ 61 { \ 62 /* CC-OFFNXT(G.PRE.02, G.PRE.05) function gen, namespace member */ \ 63 return name::Get(fields_); \ 64 } 65 66 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 67 #define FRAME_INFO_SET_FIELD(name, type) \ 68 void Set##name(type val) \ 69 { \ 70 /* CC-OFFNXT(G.PRE.02) namespace member */ \ 71 name::Set(val, &fields_); \ 72 } 73 74 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 75 #define FRAME_INFO_FIELD(name, type) \ 76 FRAME_INFO_GET_FIELD(name, type) \ 77 FRAME_INFO_SET_FIELD(name, type) 78 79 FRAME_INFO_ATTR(FrameSize, frameSize_); 80 FRAME_INFO_ATTR(SpillsCount, spillsCount_); 81 FRAME_INFO_ATTR(CallersOffset, callersOffset_); 82 FRAME_INFO_ATTR(CalleesOffset, calleesOffset_); 83 FRAME_INFO_ATTR(FpCallersOffset, fpCallersOffset_); 84 FRAME_INFO_ATTR(FpCalleesOffset, fpCalleesOffset_); 85 FRAME_INFO_FIELD(PositionedCallers, bool); 86 FRAME_INFO_FIELD(PositionedCallees, bool); 87 FRAME_INFO_FIELD(CallersRelativeFp, bool); 88 FRAME_INFO_FIELD(CalleesRelativeFp, bool); 89 // SaveFrameAndLinkRegs - save/restore FP and LR registers in prologue/epilogue. 90 FRAME_INFO_FIELD(SaveFrameAndLinkRegs, bool); 91 // SetupFrame - setup CFrame (aka. 'managed' frame). 92 // Namely, set FP reg, method and flags in prologue. 93 FRAME_INFO_FIELD(SetupFrame, bool); 94 // SaveUnusedCalleeRegs - save/restore used+unused callee-saved registers in prologue/epilogue. 95 FRAME_INFO_FIELD(SaveUnusedCalleeRegs, bool); 96 // AdjustSpReg - sub SP,#framesize in prologue and add SP,#framesize in epilogue. 97 FRAME_INFO_FIELD(AdjustSpReg, bool); 98 FRAME_INFO_FIELD(HasFloatRegs, bool); 99 FRAME_INFO_FIELD(PushCallers, bool); 100 101 using PositionedCallers = BitField<bool, 0, 1>; 102 using PositionedCallees = PositionedCallers::NextFlag; 103 using CallersRelativeFp = PositionedCallees::NextFlag; 104 using CalleesRelativeFp = CallersRelativeFp::NextFlag; 105 using SaveFrameAndLinkRegs = CalleesRelativeFp::NextFlag; 106 using SetupFrame = SaveFrameAndLinkRegs::NextFlag; 107 using SaveUnusedCalleeRegs = SetupFrame::NextFlag; 108 using AdjustSpReg = SaveUnusedCalleeRegs::NextFlag; 109 using HasFloatRegs = AdjustSpReg::NextFlag; 110 // Whether we need to push callers below stack during calls. Actually it is some kind of workaround, and we need 111 // to rework it and make better solution, e.g allocate size for callers in a frame and save them there. 112 using PushCallers = HasFloatRegs::NextFlag; 113 114 // The following static 'constructors' are for situations 115 // when we have to generate prologue/epilogue but there is 116 // no codegen at hand (some tests etc.) 117 // 'Leaf' means a prologue for a function which does not call 118 // any other functions (library, runtime etc.) LeafPrologue()119 static FrameInfo LeafPrologue() 120 { 121 return FrameInfo(AdjustSpReg::Encode(true)); 122 } 123 124 // 'Native' means just a regular prologue, that is used for native functions. 125 // 'Native' is also used for Irtoc. NativePrologue()126 static FrameInfo NativePrologue() 127 { 128 return FrameInfo(AdjustSpReg::Encode(true) | SaveFrameAndLinkRegs::Encode(true) | 129 SaveUnusedCalleeRegs::Encode(true)); 130 } 131 132 // 'Full' means NativePrologue + setting up frame (set FP, method and flags), 133 // i.e. a prologue for managed code. FullPrologue()134 static FrameInfo FullPrologue() 135 { 136 return FrameInfo(AdjustSpReg::Encode(true) | SaveFrameAndLinkRegs::Encode(true) | 137 SaveUnusedCalleeRegs::Encode(true) | SetupFrame::Encode(true)); 138 } 139 140 #undef FRAME_INFO_GET_ATTR 141 #undef FRAME_INFO_SET_ATTR 142 #undef FRAME_INFO_ATTR 143 #undef FRAME_INFO_GET_FIELD 144 #undef FRAME_INFO_SET_FIELD 145 #undef FRAME_INFO_FIELD 146 147 private: 148 uint32_t fields_ {0}; 149 int32_t frameSize_ {0}; 150 int16_t spillsCount_ {0}; 151 // Offset to caller registers storage (in words) 152 int16_t callersOffset_ {0}; 153 int16_t calleesOffset_ {0}; 154 int16_t fpCallersOffset_ {0}; 155 int16_t fpCalleesOffset_ {0}; 156 }; 157 } // namespace ark::compiler 158 159 #endif // PANDA_FRAME_INFO_H 160