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