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