• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 COMPILER_OPTIMIZER_CODEGEN_CALLCONV_H_
17 #define COMPILER_OPTIMIZER_CODEGEN_CALLCONV_H_
18 /*
19     Codegen Hi-Level calling-convention interface
20     Also contains branches targets(labels)
21 
22     Responsible for
23         Branches and jump-encoding
24         Labels (points for jump)
25         Conditional instructions
26  */
27 
28 #include <functional>
29 #include "encode.h"
30 #include "compiler/optimizer/ir/datatype.h"
31 #include "compiler/optimizer/ir/locations.h"
32 #include "compiler/optimizer/code_generator/frame_info.h"
33 
34 namespace panda::compiler {
35 class ParameterInfo {
36 public:
37     using SlotID = uint8_t;
38     ParameterInfo() = default;
39     virtual ~ParameterInfo() = default;
40     // Get next native parameter, on condition, what previous list - in vector
41     // Push data in Reg
42     // Return register or stack_slot
43     virtual std::variant<Reg, SlotID> GetNativeParam(const TypeInfo &) = 0;
44 
45     virtual Location GetNextLocation([[maybe_unused]] DataType::Type type) = 0;
46 
Reset()47     void Reset()
48     {
49         current_scalar_number_ = 0;
50         current_vector_number_ = 0;
51         current_stack_offset_ = 0;
52     }
53 
54     NO_COPY_SEMANTIC(ParameterInfo);
55     NO_MOVE_SEMANTIC(ParameterInfo);
56 
57 protected:
58     uint32_t current_scalar_number_ {0};  // NOLINT(misc-non-private-member-variables-in-classes)
59     uint32_t current_vector_number_ {0};  // NOLINT(misc-non-private-member-variables-in-classes)
60     uint8_t current_stack_offset_ {0};    // NOLINT(misc-non-private-member-variables-in-classes)
61 };
62 
63 #ifdef PANDA_COMPILER_CFI
64 struct CfiOffsets {
65     size_t push_fplr {0};
66     size_t set_fp {0};
67     size_t push_callees {0};
68     size_t pop_callees {0};
69     size_t pop_fplr {0};
70 };
71 
72 struct CfiInfo {
73     CfiOffsets offsets;
74     RegMask callee_regs;
75     VRegMask callee_vregs;
76 };
77 
78 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
79 #define SET_CFI_OFFSET(field, value) GetCfiInfo().offsets.field = value
80 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
81 #define SET_CFI_CALLEE_REGS(value) GetCfiInfo().callee_regs = value
82 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
83 #define SET_CFI_CALLEE_VREGS(value) GetCfiInfo().callee_vregs = value
84 #else
85 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
86 #define SET_CFI_OFFSET(field, value)
87 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
88 #define SET_CFI_CALLEE_REGS(value)
89 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
90 #define SET_CFI_CALLEE_VREGS(value)
91 #endif
92 
93 /**
94  * Specifies CallingConvention mode.
95  */
96 class CallConvMode final {
97 public:
CallConvMode(uint32_t value)98     explicit CallConvMode(uint32_t value) : value_(value) {}
99 
100     DEFAULT_COPY_SEMANTIC(CallConvMode);
101     DEFAULT_MOVE_SEMANTIC(CallConvMode);
102 
103     ~CallConvMode() = default;
104 
105 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
106 #define DECLARE_CALLCONV_MODE(name)                    \
107     static CallConvMode name(bool set = true)          \
108     {                                                  \
109         return CallConvMode(Flag##name ::Encode(set)); \
110     }                                                  \
111     void Set##name(bool v)                             \
112     {                                                  \
113         Flag##name ::Set(v, &value_);                  \
114     }                                                  \
115     bool Is##name() const                              \
116     {                                                  \
117         return Flag##name ::Get(value_);               \
118     }
119 
120     // Panda ABI convention (native - otherwise)
121     DECLARE_CALLCONV_MODE(Panda);
122     // Compile for osr (jit - otherwise)
123     DECLARE_CALLCONV_MODE(Osr);
124     // The method from dynamic language
125     DECLARE_CALLCONV_MODE(Dyn);
126 
127 #undef DECLARE_CALLCONV_MODE
128 
129 private:
130     using FlagPanda = BitField<bool, 0, 1>;
131     using FlagOsr = FlagPanda::NextFlag;
132     using FlagDyn = FlagOsr::NextFlag;
133 
134     uint32_t value_ {0};
135 
136     friend CallConvMode operator|(CallConvMode a, CallConvMode b);
137 };
138 
139 inline CallConvMode operator|(CallConvMode a, CallConvMode b)
140 {
141     return CallConvMode(a.value_ | b.value_);
142 }
143 
144 /**
145  * CallConv - just holds information about calling convention in current architecture.
146  */
147 class CallingConvention {
148 public:
149     virtual ~CallingConvention() = default;
150 
151     // All possible reasons for call and return
152     enum Reason {
153         // Reason for save/restore registers
154         FUNCTION,  // Function inside programm
155         NATIVE,    // native function
156         PROGRAMM   // Enter/exit from programm (UNSUPPORTED)
157     };
158 
159     // Implemented in target.cpp
160     static CallingConvention *Create(ArenaAllocator *arena_allocator, Encoder *enc, RegistersDescription *descr,
161                                      Arch arch, bool is_panda_abi = false, bool is_osr = false, bool is_dyn = false,
162                                      bool print_asm = false);
163 
164 public:
CallingConvention(ArenaAllocator * allocator,Encoder * enc,RegistersDescription * descr,CallConvMode mode)165     CallingConvention(ArenaAllocator *allocator, Encoder *enc, RegistersDescription *descr, CallConvMode mode)
166         : allocator_(allocator), encoder_(enc), regfile_(descr), mode_(mode)
167     {
168     }
169 
GetAllocator()170     ArenaAllocator *GetAllocator() const
171     {
172         return allocator_;
173     }
174 
GetEncoder()175     Encoder *GetEncoder() const
176     {
177         return encoder_;
178     }
179 
SetEncoder(Encoder * enc)180     void SetEncoder(Encoder *enc)
181     {
182         encoder_ = enc;
183     }
184 
GetRegfile()185     RegistersDescription *GetRegfile() const
186     {
187         return regfile_;
188     }
189 
IsValid()190     virtual bool IsValid() const
191     {
192         return false;
193     }
194 
GetMode()195     CallConvMode GetMode() const
196     {
197         return mode_;
198     }
199 
IsPandaMode()200     bool IsPandaMode() const
201     {
202         return mode_.IsPanda();
203     }
204 
IsOsrMode()205     bool IsOsrMode() const
206     {
207         return mode_.IsOsr();
208     }
209 
IsDynMode()210     bool IsDynMode() const
211     {
212         return mode_.IsDyn();
213     }
214 
215 #ifdef PANDA_COMPILER_CFI
GetCfiInfo()216     CfiInfo &GetCfiInfo()
217     {
218         return cfi_info_;
219     }
220 
GetCfiInfo()221     const CfiInfo &GetCfiInfo() const
222     {
223         return cfi_info_;
224     }
ProvideCFI()225     static constexpr bool ProvideCFI()
226     {
227         return true;
228     }
229 #else
ProvideCFI()230     static constexpr bool ProvideCFI()
231     {
232         return false;
233     }
234 #endif
235 
236     // Prologue/Epilogue interfaces
237     virtual void GeneratePrologue(const FrameInfo &frame_info) = 0;
238     virtual void GenerateEpilogue(const FrameInfo &frame_info, std::function<void()> post_job) = 0;
239 
240     virtual void GenerateNativePrologue(const FrameInfo &frame_info) = 0;
241     virtual void GenerateNativeEpilogue(const FrameInfo &frame_info, std::function<void()> post_job) = 0;
242 
243     // Code generation completion interfaces
244     virtual void *GetCodeEntry() = 0;
245     virtual uint32_t GetCodeSize() = 0;
246 
247     // Calculating information about parameters and save regs_offset registers for special needs
248     virtual ParameterInfo *GetParameterInfo(uint8_t regs_offset) = 0;
249 
250     NO_COPY_SEMANTIC(CallingConvention);
251     NO_MOVE_SEMANTIC(CallingConvention);
252 
253 private:
254     // Must not use ExecModel!
255     ArenaAllocator *allocator_ {nullptr};
256     Encoder *encoder_ {nullptr};
257     RegistersDescription *regfile_ {nullptr};
258 #ifdef PANDA_COMPILER_CFI
259     CfiInfo cfi_info_;
260 #endif
261     CallConvMode mode_ {0};
262 };
263 }  // namespace panda::compiler
264 
265 #endif  // COMPILER_OPTIMIZER_CODEGEN_CALLCONV_H_
266