• 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_ENCODE_H_
17 #define COMPILER_OPTIMIZER_CODEGEN_ENCODE_H_
18 
19 /*
20     Hi-level interface for encoding
21     Wrapper for specialize concrete used encoding
22 
23     Responsible for
24         Primitive (not-branch) instruction encoding
25         Memory-instructions encoding
26         Immediate and Memory operands
27 */
28 
29 #include <variant>
30 
31 #include "operands.h"
32 #include "registers_description.h"
33 #include "utils/cframe_layout.h"
34 #include "target_info.h"
35 
36 namespace panda::compiler {
37 class Encoder;
38 class CompilerOptions;
39 class RelocationInfo;
40 
41 namespace MemoryOrder {
42 enum Order { Acquire, Release, Full };
43 }  // namespace MemoryOrder
44 
45 class LabelHolder {
46 public:
47     using LabelId = uintptr_t;
48     static constexpr LabelId INVALID_LABEL = static_cast<uintptr_t>(-1);
49 
LabelHolder(Encoder * enc)50     explicit LabelHolder(Encoder *enc) : enc_ {enc} {};
51     virtual ~LabelHolder() = default;
52 
53     // TODO (igorban) : hide all this methods in CallConv
54     virtual void CreateLabels(LabelId size) = 0;
55     virtual LabelId CreateLabel() = 0;
56     virtual LabelId Size() = 0;
57 
GetEncoder()58     Encoder *GetEncoder() const
59     {
60         return enc_;
61     }
62 
63     NO_COPY_SEMANTIC(LabelHolder);
64     NO_MOVE_SEMANTIC(LabelHolder);
65 
66 protected:
67     virtual void BindLabel(LabelId) = 0;
68 
69 private:
70     Encoder *enc_ {nullptr};
71     friend Encoder;
72 };
73 
74 class Encoder {
75 public:
76     // Main constructor
Encoder(ArenaAllocator * aa,Arch arch)77     explicit Encoder(ArenaAllocator *aa, Arch arch) : Encoder(aa, arch, false) {}
Encoder(ArenaAllocator * aa,Arch arch,bool js_number_cast)78     Encoder(ArenaAllocator *aa, Arch arch, bool js_number_cast)
79         : allocator_(aa), frame_layout_(arch, 0), target_(arch), js_number_cast_(js_number_cast)
80     {
81     }
82     virtual ~Encoder() = default;
83 
GetAllocator()84     ArenaAllocator *GetAllocator() const
85     {
86         return allocator_;
87     }
88 
IsLabelValid(LabelHolder::LabelId label)89     bool IsLabelValid(LabelHolder::LabelId label)
90     {
91         return label != LabelHolder::INVALID_LABEL;
92     }
93 
GetTarget()94     Target GetTarget() const
95     {
96         return target_;
97     }
98 
GetArch()99     Arch GetArch() const
100     {
101         return GetTarget().GetArch();
102     }
103 
IsJsNumberCast()104     bool IsJsNumberCast() const
105     {
106         return js_number_cast_;
107     }
108 
SetIsJsNumberCast(bool v)109     void SetIsJsNumberCast(bool v)
110     {
111         js_number_cast_ = v;
112     }
113 
114     /// Print instruction and return next pc
DisasmInstr(std::ostream & stream,size_t pc,ssize_t code_offset)115     virtual size_t DisasmInstr([[maybe_unused]] std::ostream &stream, [[maybe_unused]] size_t pc,
116                                [[maybe_unused]] ssize_t code_offset) const
117     {
118         return 0;
119     }
120 
BufferData()121     virtual void *BufferData() const
122     {
123         return nullptr;
124     }
125 
126     /// Size of used buffer
BufferSize()127     virtual size_t BufferSize() const
128     {
129         return 0;
130     }
131 
132     // Default behaviour - do nothing
InitMasm()133     virtual bool InitMasm()
134     {
135         return true;
136     }
137 
SetMaxAllocatedBytes(size_t size)138     virtual void SetMaxAllocatedBytes([[maybe_unused]] size_t size) {};
139 
140 // Define default math operations
141 // Encode (dst, src)
142 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
143 #define UnaryOperation(opc)            \
144     virtual void Encode##opc(Reg, Reg) \
145     {                                  \
146         SetFalseResult();              \
147     }
148 
149 // Encode (dst, src0, src1)
150 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
151 #define BinaryOperation(opc)                \
152     virtual void Encode##opc(Reg, Reg, Reg) \
153     {                                       \
154         SetFalseResult();                   \
155     }                                       \
156     virtual void Encode##opc(Reg, Reg, Imm) \
157     {                                       \
158         SetFalseResult();                   \
159     }
160 
161 // Encode (dst, src0, src1)
162 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
163 #define BinaryShiftedRegisterOperation(opc)   \
164     virtual void Encode##opc(Reg, Reg, Shift) \
165     {                                         \
166         SetFalseResult();                     \
167     }
168 
169 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
170 #define INST_DEF(OPCODE, TYPE) TYPE(OPCODE)
171 
172     ENCODE_MATH_LIST(INST_DEF)
173 
ENCODE_INST_WITH_SHIFTED_OPERAND(INST_DEF)174     ENCODE_INST_WITH_SHIFTED_OPERAND(INST_DEF)
175 
176 #undef UnaryOperation
177 #undef BinaryOperation
178 #undef BinaryShiftedRegisterOperation
179 #undef INST_DEF
180 
181     virtual void EncodeNop()
182     {
183         SetFalseResult();
184     }
185 
EncodeAddOverflow(compiler::LabelHolder::LabelId id,Reg dst,Reg src0,Reg src1,Condition cc)186     virtual void EncodeAddOverflow([[maybe_unused]] compiler::LabelHolder::LabelId id, [[maybe_unused]] Reg dst,
187                                    [[maybe_unused]] Reg src0, [[maybe_unused]] Reg src1, [[maybe_unused]] Condition cc)
188     {
189         SetFalseResult();
190     }
191 
EncodeSubOverflow(compiler::LabelHolder::LabelId id,Reg dst,Reg src0,Reg src1,Condition cc)192     virtual void EncodeSubOverflow([[maybe_unused]] compiler::LabelHolder::LabelId id, [[maybe_unused]] Reg dst,
193                                    [[maybe_unused]] Reg src0, [[maybe_unused]] Reg src1, [[maybe_unused]] Condition cc)
194     {
195         SetFalseResult();
196     }
197 
EncodeMulOverflow(compiler::LabelHolder::LabelId id,Reg dst,Reg src0,Reg src1,Condition cc)198     virtual void EncodeMulOverflow([[maybe_unused]] compiler::LabelHolder::LabelId id, [[maybe_unused]] Reg dst,
199                                    [[maybe_unused]] Reg src0, [[maybe_unused]] Reg src1, [[maybe_unused]] Condition cc)
200     {
201         SetFalseResult();
202     }
203 
EncodeCast(Reg dst,bool dst_signed,Reg src,bool src_signed)204     virtual void EncodeCast([[maybe_unused]] Reg dst, [[maybe_unused]] bool dst_signed, [[maybe_unused]] Reg src,
205                             [[maybe_unused]] bool src_signed)
206     {
207         SetFalseResult();
208     }
EncodeCastToBool(Reg dst,Reg src)209     virtual void EncodeCastToBool([[maybe_unused]] Reg dst, [[maybe_unused]] Reg src)
210     {
211         SetFalseResult();
212     }
EncodeMin(Reg dst,bool dst_signed,Reg src0,Reg src1)213     virtual void EncodeMin([[maybe_unused]] Reg dst, [[maybe_unused]] bool dst_signed, [[maybe_unused]] Reg src0,
214                            [[maybe_unused]] Reg src1)
215     {
216         SetFalseResult();
217     }
EncodeDiv(Reg dst,bool dst_signed,Reg src0,Reg src1)218     virtual void EncodeDiv([[maybe_unused]] Reg dst, [[maybe_unused]] bool dst_signed, [[maybe_unused]] Reg src0,
219                            [[maybe_unused]] Reg src1)
220     {
221         SetFalseResult();
222     }
EncodeMod(Reg dst,bool dst_signed,Reg src0,Reg src1)223     virtual void EncodeMod([[maybe_unused]] Reg dst, [[maybe_unused]] bool dst_signed, [[maybe_unused]] Reg src0,
224                            [[maybe_unused]] Reg src1)
225     {
226         SetFalseResult();
227     }
EncodeMax(Reg dst,bool dst_signed,Reg src0,Reg src1)228     virtual void EncodeMax([[maybe_unused]] Reg dst, [[maybe_unused]] bool dst_signed, [[maybe_unused]] Reg src0,
229                            [[maybe_unused]] Reg src1)
230     {
231         SetFalseResult();
232     }
EncodeMov(Reg dst,Imm src)233     virtual void EncodeMov([[maybe_unused]] Reg dst, [[maybe_unused]] Imm src)
234     {
235         SetFalseResult();
236     }
237 
EncodeLdr(Reg dst,bool dst_signed,MemRef mem)238     virtual void EncodeLdr([[maybe_unused]] Reg dst, [[maybe_unused]] bool dst_signed, [[maybe_unused]] MemRef mem)
239     {
240         SetFalseResult();
241     }
EncodeLdrAcquire(Reg dst,bool dst_signed,MemRef mem)242     virtual void EncodeLdrAcquire([[maybe_unused]] Reg dst, [[maybe_unused]] bool dst_signed,
243                                   [[maybe_unused]] MemRef mem)
244     {
245         SetFalseResult();
246     }
EncodeStr(Reg src,MemRef mem)247     virtual void EncodeStr([[maybe_unused]] Reg src, [[maybe_unused]] MemRef mem)
248     {
249         SetFalseResult();
250     }
EncodeStrRelease(Reg src,MemRef mem)251     virtual void EncodeStrRelease([[maybe_unused]] Reg src, [[maybe_unused]] MemRef mem)
252     {
253         SetFalseResult();
254     }
EncodeLdrExclusive(Reg dst,Reg addr,bool acquire)255     virtual void EncodeLdrExclusive([[maybe_unused]] Reg dst, [[maybe_unused]] Reg addr, [[maybe_unused]] bool acquire)
256     {
257         SetFalseResult();
258     }
EncodeStrExclusive(Reg dst,Reg src,Reg addr,bool release)259     virtual void EncodeStrExclusive([[maybe_unused]] Reg dst, [[maybe_unused]] Reg src, [[maybe_unused]] Reg addr,
260                                     [[maybe_unused]] bool release)
261     {
262         SetFalseResult();
263     }
264 
265     // zerod high part: [reg.size, 64)
EncodeStrz(Reg src,MemRef mem)266     virtual void EncodeStrz([[maybe_unused]] Reg src, [[maybe_unused]] MemRef mem)
267     {
268         SetFalseResult();
269     }
Push(Reg src,MemRef mem)270     virtual void Push([[maybe_unused]] Reg src, [[maybe_unused]] MemRef mem)
271     {
272         SetFalseResult();
273     }
EncodeSti(Imm src,MemRef mem)274     virtual void EncodeSti([[maybe_unused]] Imm src, [[maybe_unused]] MemRef mem)
275     {
276         SetFalseResult();
277     }
278     // size must be 8, 16,32 or 64
EncodeMemCopy(MemRef mem_from,MemRef mem_to,size_t size)279     virtual void EncodeMemCopy([[maybe_unused]] MemRef mem_from, [[maybe_unused]] MemRef mem_to,
280                                [[maybe_unused]] size_t size)
281     {
282         SetFalseResult();
283     }
284     // size must be 8, 16,32 or 64
285     // zerod high part: [size, 64)
EncodeMemCopyz(MemRef mem_from,MemRef mem_to,size_t size)286     virtual void EncodeMemCopyz([[maybe_unused]] MemRef mem_from, [[maybe_unused]] MemRef mem_to,
287                                 [[maybe_unused]] size_t size)
288     {
289         SetFalseResult();
290     }
291 
EncodeCmp(Reg dst,Reg src0,Reg src1,Condition cc)292     virtual void EncodeCmp([[maybe_unused]] Reg dst, [[maybe_unused]] Reg src0, [[maybe_unused]] Reg src1,
293                            [[maybe_unused]] Condition cc)
294     {
295         SetFalseResult();
296     }
297 
298     // Additional check for isnan-comparison
EncodeCompare(Reg dst,Reg src0,Reg src1,Condition cc)299     virtual void EncodeCompare([[maybe_unused]] Reg dst, [[maybe_unused]] Reg src0, [[maybe_unused]] Reg src1,
300                                [[maybe_unused]] Condition cc)
301     {
302         SetFalseResult();
303     }
304 
EncodeCompareTest(Reg dst,Reg src0,Reg src1,Condition cc)305     virtual void EncodeCompareTest([[maybe_unused]] Reg dst, [[maybe_unused]] Reg src0, [[maybe_unused]] Reg src1,
306                                    [[maybe_unused]] Condition cc)
307     {
308         SetFalseResult();
309     }
310 
EncodeCompressedStringCharAt(Reg dst,Reg str,Reg idx,Reg length,Reg tmp,size_t data_offset,uint32_t shift)311     virtual void EncodeCompressedStringCharAt([[maybe_unused]] Reg dst, [[maybe_unused]] Reg str,
312                                               [[maybe_unused]] Reg idx, [[maybe_unused]] Reg length,
313                                               [[maybe_unused]] Reg tmp, [[maybe_unused]] size_t data_offset,
314                                               [[maybe_unused]] uint32_t shift)
315     {
316         SetFalseResult();
317     }
318 
EncodeCompressedStringCharAtI(Reg dst,Reg str,Reg length,size_t data_offset,uint32_t index,uint32_t shift)319     virtual void EncodeCompressedStringCharAtI([[maybe_unused]] Reg dst, [[maybe_unused]] Reg str,
320                                                [[maybe_unused]] Reg length, [[maybe_unused]] size_t data_offset,
321                                                [[maybe_unused]] uint32_t index, [[maybe_unused]] uint32_t shift)
322     {
323         SetFalseResult();
324     }
325 
EncodeSelect(Reg dst,Reg src0,Reg src1,Reg src2,Reg src3,Condition cc)326     virtual void EncodeSelect([[maybe_unused]] Reg dst, [[maybe_unused]] Reg src0, [[maybe_unused]] Reg src1,
327                               [[maybe_unused]] Reg src2, [[maybe_unused]] Reg src3, [[maybe_unused]] Condition cc)
328     {
329         SetFalseResult();
330     }
331 
EncodeSelectTest(Reg dst,Reg src0,Reg src1,Reg src2,Reg src3,Condition cc)332     virtual void EncodeSelectTest([[maybe_unused]] Reg dst, [[maybe_unused]] Reg src0, [[maybe_unused]] Reg src1,
333                                   [[maybe_unused]] Reg src2, [[maybe_unused]] Reg src3, [[maybe_unused]] Condition cc)
334     {
335         SetFalseResult();
336     }
337 
EncodeIsInf(Reg dst,Reg src0)338     virtual void EncodeIsInf([[maybe_unused]] Reg dst, [[maybe_unused]] Reg src0)
339     {
340         SetFalseResult();
341     }
342 
EncodeReverseBytes(Reg dst,Reg src)343     virtual void EncodeReverseBytes([[maybe_unused]] Reg dst, [[maybe_unused]] Reg src)
344     {
345         SetFalseResult();
346     }
347 
EncodeReverseBits(Reg dst,Reg src)348     virtual void EncodeReverseBits([[maybe_unused]] Reg dst, [[maybe_unused]] Reg src)
349     {
350         SetFalseResult();
351     }
352 
EncodeBitCount(Reg dst,Reg src)353     virtual void EncodeBitCount([[maybe_unused]] Reg dst, [[maybe_unused]] Reg src)
354     {
355         SetFalseResult();
356     }
357 
EncodeRotate(Reg dst,Reg src1,Reg src2,bool is_ror)358     virtual void EncodeRotate([[maybe_unused]] Reg dst, [[maybe_unused]] Reg src1, [[maybe_unused]] Reg src2,
359                               [[maybe_unused]] bool is_ror)
360     {
361         SetFalseResult();
362     }
363 
EncodeSignum(Reg dst,Reg src)364     virtual void EncodeSignum([[maybe_unused]] Reg dst, [[maybe_unused]] Reg src)
365     {
366         SetFalseResult();
367     }
368 
EncodeCountLeadingZeroBits(Reg dst,Reg src)369     virtual void EncodeCountLeadingZeroBits([[maybe_unused]] Reg dst, [[maybe_unused]] Reg src)
370     {
371         SetFalseResult();
372     }
373 
EncodeCountTrailingZeroBits(Reg dst,Reg src)374     virtual void EncodeCountTrailingZeroBits([[maybe_unused]] Reg dst, [[maybe_unused]] Reg src)
375     {
376         SetFalseResult();
377     }
378 
EncodeCeil(Reg dst,Reg src)379     virtual void EncodeCeil([[maybe_unused]] Reg dst, [[maybe_unused]] Reg src)
380     {
381         SetFalseResult();
382     }
383 
EncodeFloor(Reg dst,Reg src)384     virtual void EncodeFloor([[maybe_unused]] Reg dst, [[maybe_unused]] Reg src)
385     {
386         SetFalseResult();
387     }
388 
EncodeRint(Reg dst,Reg src)389     virtual void EncodeRint([[maybe_unused]] Reg dst, [[maybe_unused]] Reg src)
390     {
391         SetFalseResult();
392     }
393 
EncodeRound(Reg dst,Reg src)394     virtual void EncodeRound([[maybe_unused]] Reg dst, [[maybe_unused]] Reg src)
395     {
396         SetFalseResult();
397     }
398 
EncodeStringEquals(Reg dst,Reg str1,Reg str2,bool compression,uint32_t length_offset,uint32_t data_offset)399     virtual void EncodeStringEquals([[maybe_unused]] Reg dst, [[maybe_unused]] Reg str1, [[maybe_unused]] Reg str2,
400                                     [[maybe_unused]] bool compression, [[maybe_unused]] uint32_t length_offset,
401                                     [[maybe_unused]] uint32_t data_offset)
402     {
403         SetFalseResult();
404     }
405 
EncodeStringIndexOfAfter(Reg dst,Reg str,Reg character,Reg idx,Reg tmp,bool compression,uint32_t length_offset,uint32_t data_offset,int32_t char_const_value)406     virtual void EncodeStringIndexOfAfter([[maybe_unused]] Reg dst, [[maybe_unused]] Reg str,
407                                           [[maybe_unused]] Reg character, [[maybe_unused]] Reg idx,
408                                           [[maybe_unused]] Reg tmp, [[maybe_unused]] bool compression,
409                                           [[maybe_unused]] uint32_t length_offset,
410                                           [[maybe_unused]] uint32_t data_offset,
411                                           [[maybe_unused]] int32_t char_const_value)
412     {
413         SetFalseResult();
414     }
415 
EncodeSelect(Reg dst,Reg src0,Reg src1,Reg src2,Imm imm,Condition cc)416     virtual void EncodeSelect([[maybe_unused]] Reg dst, [[maybe_unused]] Reg src0, [[maybe_unused]] Reg src1,
417                               [[maybe_unused]] Reg src2, [[maybe_unused]] Imm imm, [[maybe_unused]] Condition cc)
418     {
419         SetFalseResult();
420     }
421 
EncodeSelectTest(Reg dst,Reg src0,Reg src1,Reg src2,Imm imm,Condition cc)422     virtual void EncodeSelectTest([[maybe_unused]] Reg dst, [[maybe_unused]] Reg src0, [[maybe_unused]] Reg src1,
423                                   [[maybe_unused]] Reg src2, [[maybe_unused]] Imm imm, [[maybe_unused]] Condition cc)
424     {
425         SetFalseResult();
426     }
427 
EncodeGetTypeSize(Reg size,Reg type)428     virtual void EncodeGetTypeSize([[maybe_unused]] Reg size, [[maybe_unused]] Reg type)
429     {
430         SetFalseResult();
431     }
432 
EncodeLdp(Reg dst0,Reg dst1,bool dst_signed,MemRef mem)433     virtual void EncodeLdp([[maybe_unused]] Reg dst0, [[maybe_unused]] Reg dst1, [[maybe_unused]] bool dst_signed,
434                            [[maybe_unused]] MemRef mem)
435     {
436         SetFalseResult();
437     }
438 
EncodeStp(Reg src0,Reg src1,MemRef mem)439     virtual void EncodeStp([[maybe_unused]] Reg src0, [[maybe_unused]] Reg src1, [[maybe_unused]] MemRef mem)
440     {
441         SetFalseResult();
442     }
443 
EncodeMAdd(Reg dst,Reg src0,Reg src1,Reg src2)444     virtual void EncodeMAdd([[maybe_unused]] Reg dst, [[maybe_unused]] Reg src0, [[maybe_unused]] Reg src1,
445                             [[maybe_unused]] Reg src2)
446     {
447         SetFalseResult();
448     }
449 
EncodeMSub(Reg dst,Reg src0,Reg src1,Reg src2)450     virtual void EncodeMSub([[maybe_unused]] Reg dst, [[maybe_unused]] Reg src0, [[maybe_unused]] Reg src1,
451                             [[maybe_unused]] Reg src2)
452     {
453         SetFalseResult();
454     }
455 
EncodeMNeg(Reg dst,Reg src0,Reg src1)456     virtual void EncodeMNeg([[maybe_unused]] Reg dst, [[maybe_unused]] Reg src0, [[maybe_unused]] Reg src1)
457     {
458         SetFalseResult();
459     }
460 
EncodeOrNot(Reg dst,Reg src0,Reg src1)461     virtual void EncodeOrNot([[maybe_unused]] Reg dst, [[maybe_unused]] Reg src0, [[maybe_unused]] Reg src1)
462     {
463         SetFalseResult();
464     }
465 
EncodeAndNot(Reg dst,Reg src0,Reg src1)466     virtual void EncodeAndNot([[maybe_unused]] Reg dst, [[maybe_unused]] Reg src0, [[maybe_unused]] Reg src1)
467     {
468         SetFalseResult();
469     }
470 
EncodeXorNot(Reg dst,Reg src0,Reg src1)471     virtual void EncodeXorNot([[maybe_unused]] Reg dst, [[maybe_unused]] Reg src0, [[maybe_unused]] Reg src1)
472     {
473         SetFalseResult();
474     }
475 
EncodeNeg(Reg dst,Shift src)476     virtual void EncodeNeg([[maybe_unused]] Reg dst, [[maybe_unused]] Shift src)
477     {
478         SetFalseResult();
479     }
480 
EncodeFpToBits(Reg dst,Reg src)481     virtual void EncodeFpToBits([[maybe_unused]] Reg dst, [[maybe_unused]] Reg src)
482     {
483         SetFalseResult();
484     }
485 
EncodeMoveBitsRaw(Reg dst,Reg src)486     virtual void EncodeMoveBitsRaw([[maybe_unused]] Reg dst, [[maybe_unused]] Reg src)
487     {
488         SetFalseResult();
489     }
490 
EncodeExtractBits(Reg dst,Reg src,Imm imm1,Imm imm2)491     virtual void EncodeExtractBits([[maybe_unused]] Reg dst, [[maybe_unused]] Reg src, [[maybe_unused]] Imm imm1,
492                                    [[maybe_unused]] Imm imm2)
493     {
494         success_ = false;
495     }
496 
EncodeCrc32Update(Reg dst,Reg crc_reg,Reg val_reg)497     virtual void EncodeCrc32Update([[maybe_unused]] Reg dst, [[maybe_unused]] Reg crc_reg, [[maybe_unused]] Reg val_reg)
498     {
499         SetFalseResult();
500     }
501 
502     /**
503      * Encode dummy load from the address [sp + offset].
504      * @param offset offset from the stack pointer register
505      */
EncodeStackOverflowCheck(ssize_t offset)506     virtual void EncodeStackOverflowCheck([[maybe_unused]] ssize_t offset)
507     {
508         SetFalseResult();
509     }
510 
IsValid()511     virtual bool IsValid() const
512     {
513         return false;
514     }
515 
GetResult()516     virtual bool GetResult() const
517     {
518         return success_;
519     }
520 
SetFalseResult()521     void SetFalseResult()
522     {
523         success_ = false;
524     }
525 
526     // Encoder builder - implement in target.cpp
527     static Encoder *Create(ArenaAllocator *arena_allocator, Arch arch, bool print_asm, bool js_number_cast = false);
528 
529     // For now it is one function for Add/Sub and Cmp, it suits all considered targets (x86, amd64, arm32, arm64).
530     // We probably should revisit this if we add new targets, like Thumb-2 or others.
CanEncodeImmAddSubCmp(int64_t imm,uint32_t size,bool signed_compare)531     virtual bool CanEncodeImmAddSubCmp([[maybe_unused]] int64_t imm, [[maybe_unused]] uint32_t size,
532                                        [[maybe_unused]] bool signed_compare)
533     {
534         return false;
535     }
536 
CanEncodeImmMulDivMod(uint64_t imm,uint32_t size)537     virtual bool CanEncodeImmMulDivMod([[maybe_unused]] uint64_t imm, [[maybe_unused]] uint32_t size)
538     {
539         return false;
540     }
541 
CanEncodeImmLogical(uint64_t imm,uint32_t size)542     virtual bool CanEncodeImmLogical([[maybe_unused]] uint64_t imm, [[maybe_unused]] uint32_t size)
543     {
544         return false;
545     }
546 
CanEncodeScale(uint64_t imm,uint32_t size)547     virtual bool CanEncodeScale([[maybe_unused]] uint64_t imm, [[maybe_unused]] uint32_t size)
548     {
549         return false;
550     }
551 
CanEncodeShift(uint32_t size)552     virtual bool CanEncodeShift([[maybe_unused]] uint32_t size)
553     {
554         return true;
555     }
556 
CanEncodeBitCount()557     virtual bool CanEncodeBitCount()
558     {
559         return false;
560     }
561 
CanEncodeMAdd()562     virtual bool CanEncodeMAdd()
563     {
564         return false;
565     }
566 
CanEncodeMSub()567     virtual bool CanEncodeMSub()
568     {
569         return false;
570     }
571 
CanEncodeMNeg()572     virtual bool CanEncodeMNeg()
573     {
574         return false;
575     }
576 
CanEncodeOrNot()577     virtual bool CanEncodeOrNot()
578     {
579         return false;
580     }
581 
CanEncodeAndNot()582     virtual bool CanEncodeAndNot()
583     {
584         return false;
585     }
586 
CanEncodeXorNot()587     virtual bool CanEncodeXorNot()
588     {
589         return false;
590     }
591 
592     // Check if encoder is capable of encoding operations where an operand is a register with
593     // a value shifted by shift operation with specified type by some immediate value.
CanEncodeShiftedOperand(ShiftOpcode opcode,ShiftType shift_type)594     virtual bool CanEncodeShiftedOperand([[maybe_unused]] ShiftOpcode opcode, [[maybe_unused]] ShiftType shift_type)
595     {
596         return false;
597     }
598 
CanEncodeCompressedStringCharAt()599     virtual bool CanEncodeCompressedStringCharAt()
600     {
601         return false;
602     }
603 
CanEncodeCompressedStringCharAtI()604     virtual bool CanEncodeCompressedStringCharAtI()
605     {
606         return false;
607     }
608 
EncodeCompareAndSwap(Reg dst,Reg obj,Reg offset,Reg val,Reg newval)609     virtual void EncodeCompareAndSwap([[maybe_unused]] Reg dst, [[maybe_unused]] Reg obj, [[maybe_unused]] Reg offset,
610                                       [[maybe_unused]] Reg val, [[maybe_unused]] Reg newval)
611     {
612         SetFalseResult();
613     }
614 
EncodeCompareAndSwap(Reg dst,Reg addr,Reg val,Reg newval)615     virtual void EncodeCompareAndSwap([[maybe_unused]] Reg dst, [[maybe_unused]] Reg addr, [[maybe_unused]] Reg val,
616                                       [[maybe_unused]] Reg newval)
617     {
618         SetFalseResult();
619     }
620 
EncodeUnsafeGetAndSet(Reg dst,Reg obj,Reg offset,Reg val)621     virtual void EncodeUnsafeGetAndSet([[maybe_unused]] Reg dst, [[maybe_unused]] Reg obj, [[maybe_unused]] Reg offset,
622                                        [[maybe_unused]] Reg val)
623     {
624         SetFalseResult();
625     }
626 
EncodeUnsafeGetAndAdd(Reg dst,Reg obj,Reg offset,Reg val,Reg tmp)627     virtual void EncodeUnsafeGetAndAdd([[maybe_unused]] Reg dst, [[maybe_unused]] Reg obj, [[maybe_unused]] Reg offset,
628                                        [[maybe_unused]] Reg val, [[maybe_unused]] Reg tmp)
629     {
630         SetFalseResult();
631     }
632 
EncodeMemoryBarrier(MemoryOrder::Order order)633     virtual void EncodeMemoryBarrier([[maybe_unused]] MemoryOrder::Order order)
634     {
635         SetFalseResult();
636     }
637 
GetCursorOffset()638     virtual size_t GetCursorOffset() const
639     {
640         return 0;
641     }
642 
SetCursorOffset(size_t offset)643     virtual void SetCursorOffset([[maybe_unused]] size_t offset) {}
644 
SaveRegisters(RegMask registers,ssize_t slot,size_t start_reg,bool is_fp)645     virtual void SaveRegisters([[maybe_unused]] RegMask registers, [[maybe_unused]] ssize_t slot,
646                                [[maybe_unused]] size_t start_reg, [[maybe_unused]] bool is_fp)
647     {
648         SetFalseResult();
649     }
LoadRegisters(RegMask registers,ssize_t slot,size_t start_reg,bool is_fp)650     virtual void LoadRegisters([[maybe_unused]] RegMask registers, [[maybe_unused]] ssize_t slot,
651                                [[maybe_unused]] size_t start_reg, [[maybe_unused]] bool is_fp)
652     {
653         SetFalseResult();
654     }
655 
656     /**
657      * Save/load registers to/from the memory.
658      *
659      * If `mask` is empty (all bits are zero), then registers will be saved densely, otherwise place for each register
660      * will be determined according to this mask.
661      * Example: registers' bits = [1, 3, 10], mask's bits = [0, 1, 2, 3, 8, 9, 10, 11]
662      * We can see that mask has the gap in 4-7 bits. So, registers will be saved in the following slots:
663      *      slots: 0   1   2   3   4   5   6   7
664      *      regs :     1       3          10
665      * If the mask would be zero, then the following layout will be used:
666      *      slots: 0   1   2
667      *      regs : 1   3  10
668      *
669      * @param registers mask of registers to be saved
670      * @param is_fp if true, registers are floating point registers
671      * @param slot offset from the `base` register to the destination address (in words)
672      * @param base base register
673      * @param mask determine memory layout for the registers
674      */
SaveRegisters(RegMask registers,bool is_fp,ssize_t slot,Reg base,RegMask mask)675     virtual void SaveRegisters([[maybe_unused]] RegMask registers, [[maybe_unused]] bool is_fp,
676                                [[maybe_unused]] ssize_t slot, [[maybe_unused]] Reg base, [[maybe_unused]] RegMask mask)
677     {
678         SetFalseResult();
679     }
LoadRegisters(RegMask registers,bool is_fp,ssize_t slot,Reg base,RegMask mask)680     virtual void LoadRegisters([[maybe_unused]] RegMask registers, [[maybe_unused]] bool is_fp,
681                                [[maybe_unused]] ssize_t slot, [[maybe_unused]] Reg base, [[maybe_unused]] RegMask mask)
682     {
683         SetFalseResult();
684     }
PushRegisters(RegMask registers,bool is_fp,bool align)685     virtual void PushRegisters([[maybe_unused]] RegMask registers, [[maybe_unused]] bool is_fp,
686                                [[maybe_unused]] bool align)
687     {
688         SetFalseResult();
689     }
690 
PopRegisters(RegMask registers,bool is_fp,bool align)691     virtual void PopRegisters([[maybe_unused]] RegMask registers, [[maybe_unused]] bool is_fp,
692                               [[maybe_unused]] bool align)
693     {
694         SetFalseResult();
695     }
696 
GetRegfile()697     RegistersDescription *GetRegfile() const
698     {
699         ASSERT(regfile_ != nullptr);
700         return regfile_;
701     }
702 
SetRegfile(RegistersDescription * regfile)703     void SetRegfile(RegistersDescription *regfile)
704     {
705         regfile_ = regfile;
706     }
707 
AcquireScratchRegister(compiler::TypeInfo type)708     virtual compiler::Reg AcquireScratchRegister([[maybe_unused]] compiler::TypeInfo type)
709     {
710         return compiler::Reg();
711     }
712 
AcquireScratchRegister(compiler::Reg reg)713     virtual void AcquireScratchRegister([[maybe_unused]] compiler::Reg reg)
714     {
715         SetFalseResult();
716     }
717 
ReleaseScratchRegister(compiler::Reg reg)718     virtual void ReleaseScratchRegister([[maybe_unused]] compiler::Reg reg)
719     {
720         SetFalseResult();
721     }
722 
IsScratchRegisterReleased(compiler::Reg reg)723     virtual bool IsScratchRegisterReleased([[maybe_unused]] compiler::Reg reg)
724     {
725         return false;
726     }
727 
GetScratchRegistersCount()728     size_t GetScratchRegistersCount() const
729     {
730         return GetScratchRegistersMask().Count();
731     }
732 
GetScratchRegistersMask()733     virtual RegMask GetScratchRegistersMask() const
734     {
735         return 0;
736     }
737 
GetScratchFPRegistersCount()738     size_t GetScratchFPRegistersCount() const
739     {
740         return GetScratchFpRegistersMask().Count();
741     }
742 
GetScratchFpRegistersMask()743     virtual RegMask GetScratchFpRegistersMask() const
744     {
745         return 0;
746     }
747 
748     // Get Scratch registers, that currently are not allocated
GetAvailableScratchRegisters()749     virtual RegMask GetAvailableScratchRegisters() const
750     {
751         return 0;
752     }
753 
754     // Get Floating Point Scratch registers, that currently are not allocated
GetAvailableScratchFpRegisters()755     virtual VRegMask GetAvailableScratchFpRegisters() const
756     {
757         return 0;
758     }
759 
MaxArchInstPerEncoded()760     virtual size_t MaxArchInstPerEncoded()
761     {
762         static constexpr size_t MAX_ARCH_INST_PER_ENCODE = 32;
763         return MAX_ARCH_INST_PER_ENCODE;
764     }
765 
SetRegister(RegMask * mask,VRegMask * vmask,Reg reg)766     virtual void SetRegister(RegMask *mask, VRegMask *vmask, Reg reg)
767     {
768         SetRegister(mask, vmask, reg, true);
769     }
770 
SetRegister(RegMask * mask,VRegMask * vmask,Reg reg,bool val)771     virtual void SetRegister(RegMask *mask, VRegMask *vmask, Reg reg, bool val) const
772     {
773         if (!reg.IsValid()) {
774             return;
775         }
776         if (reg.IsScalar()) {
777             ASSERT(mask != nullptr);
778             mask->set(reg.GetId(), val);
779         } else {
780             ASSERT(vmask != nullptr);
781             ASSERT(reg.IsFloat());
782             if (vmask != nullptr) {
783                 vmask->set(reg.GetId(), val);
784             }
785         }
786     }
787 
GetRefType()788     virtual compiler::TypeInfo GetRefType()
789     {
790         return compiler::TypeInfo();
791     }
792 
793     virtual void Finalize() = 0;
794 
795 public:
796     /**
797      *   Label-holder interfaces
798      */
CreateLabel()799     LabelHolder::LabelId CreateLabel()
800     {
801         auto labels = GetLabels();
802         ASSERT(labels != nullptr);
803         return labels->CreateLabel();
804     }
805 
BindLabel(LabelHolder::LabelId id)806     void BindLabel(LabelHolder::LabelId id)
807     {
808         auto labels = GetLabels();
809         ASSERT(labels != nullptr);
810         ASSERT(labels->Size() > id);
811         labels->BindLabel(id);
812     }
813 
GetLabels()814     virtual LabelHolder *GetLabels() const
815     {
816         return nullptr;
817     }
818     virtual size_t GetLabelAddress(LabelHolder::LabelId label) = 0;
819 
820     virtual bool LabelHasLinks(LabelHolder::LabelId label) = 0;
821 
822 public:
MakeCall(compiler::RelocationInfo * relocation)823     virtual void MakeCall([[maybe_unused]] compiler::RelocationInfo *relocation)
824     {
825         SetFalseResult();
826     }
827 
MakeCall(compiler::LabelHolder::LabelId id)828     virtual void MakeCall([[maybe_unused]] compiler::LabelHolder::LabelId id)
829     {
830         SetFalseResult();
831     }
832 
MakeCall(const void * entry_point)833     virtual void MakeCall([[maybe_unused]] const void *entry_point)
834     {
835         SetFalseResult();
836     }
837 
MakeCall(Reg reg)838     virtual void MakeCall([[maybe_unused]] Reg reg)
839     {
840         SetFalseResult();
841     }
842 
MakeCall(compiler::MemRef entry_point)843     virtual void MakeCall([[maybe_unused]] compiler::MemRef entry_point)
844     {
845         SetFalseResult();
846     }
847 
MakeCallAot(intptr_t offset)848     virtual void MakeCallAot([[maybe_unused]] intptr_t offset)
849     {
850         SetFalseResult();
851     }
852 
CanMakeCallByOffset(intptr_t offset)853     virtual bool CanMakeCallByOffset([[maybe_unused]] intptr_t offset)
854     {
855         return false;
856     }
857 
MakeCallByOffset(intptr_t offset)858     virtual void MakeCallByOffset([[maybe_unused]] intptr_t offset)
859     {
860         SetFalseResult();
861     }
862 
MakeLoadAotTable(intptr_t offset,compiler::Reg reg)863     virtual void MakeLoadAotTable([[maybe_unused]] intptr_t offset, [[maybe_unused]] compiler::Reg reg)
864     {
865         SetFalseResult();
866     }
867 
MakeLoadAotTableAddr(intptr_t offset,compiler::Reg addr,compiler::Reg val)868     virtual void MakeLoadAotTableAddr([[maybe_unused]] intptr_t offset, [[maybe_unused]] compiler::Reg addr,
869                                       [[maybe_unused]] compiler::Reg val)
870     {
871         SetFalseResult();
872     }
873 
874     // Encode unconditional branch
EncodeJump(compiler::LabelHolder::LabelId id)875     virtual void EncodeJump([[maybe_unused]] compiler::LabelHolder::LabelId id)
876     {
877         SetFalseResult();
878     }
879 
880     // Encode jump with compare to zero
EncodeJump(compiler::LabelHolder::LabelId id,compiler::Reg reg,compiler::Condition cond)881     virtual void EncodeJump([[maybe_unused]] compiler::LabelHolder::LabelId id, [[maybe_unused]] compiler::Reg reg,
882                             [[maybe_unused]] compiler::Condition cond)
883     {
884         SetFalseResult();
885     }
886 
887     // Compare reg and immediate and branch
EncodeJump(compiler::LabelHolder::LabelId id,compiler::Reg reg,compiler::Imm imm,compiler::Condition c)888     virtual void EncodeJump([[maybe_unused]] compiler::LabelHolder::LabelId id, [[maybe_unused]] compiler::Reg reg,
889                             [[maybe_unused]] compiler::Imm imm, [[maybe_unused]] compiler::Condition c)
890     {
891         SetFalseResult();
892     }
893 
894     // Compare two regs and branch
EncodeJump(compiler::LabelHolder::LabelId id,compiler::Reg r,compiler::Reg reg,compiler::Condition c)895     virtual void EncodeJump([[maybe_unused]] compiler::LabelHolder::LabelId id, [[maybe_unused]] compiler::Reg r,
896                             [[maybe_unused]] compiler::Reg reg, [[maybe_unused]] compiler::Condition c)
897     {
898         SetFalseResult();
899     }
900 
901     // Compare reg and immediate and branch
EncodeJumpTest(compiler::LabelHolder::LabelId id,compiler::Reg reg,compiler::Imm imm,compiler::Condition c)902     virtual void EncodeJumpTest([[maybe_unused]] compiler::LabelHolder::LabelId id, [[maybe_unused]] compiler::Reg reg,
903                                 [[maybe_unused]] compiler::Imm imm, [[maybe_unused]] compiler::Condition c)
904     {
905         SetFalseResult();
906     }
907 
908     // Compare two regs and branch
EncodeJumpTest(compiler::LabelHolder::LabelId id,compiler::Reg r,compiler::Reg reg,compiler::Condition c)909     virtual void EncodeJumpTest([[maybe_unused]] compiler::LabelHolder::LabelId id, [[maybe_unused]] compiler::Reg r,
910                                 [[maybe_unused]] compiler::Reg reg, [[maybe_unused]] compiler::Condition c)
911     {
912         SetFalseResult();
913     }
914 
915     // Encode jump by register value
EncodeJump(compiler::Reg reg)916     virtual void EncodeJump([[maybe_unused]] compiler::Reg reg)
917     {
918         SetFalseResult();
919     }
920 
EncodeJump(RelocationInfo * relocation)921     virtual void EncodeJump([[maybe_unused]] RelocationInfo *relocation)
922     {
923         SetFalseResult();
924     }
925 
EncodeBitTestAndBranch(compiler::LabelHolder::LabelId id,compiler::Reg reg,uint32_t bit_pos,bool bit_value)926     virtual void EncodeBitTestAndBranch([[maybe_unused]] compiler::LabelHolder::LabelId id,
927                                         [[maybe_unused]] compiler::Reg reg, [[maybe_unused]] uint32_t bit_pos,
928                                         [[maybe_unused]] bool bit_value)
929     {
930         SetFalseResult();
931     }
932 
EncodeAbort()933     virtual void EncodeAbort()
934     {
935         SetFalseResult();
936     }
937 
EncodeReturn()938     virtual void EncodeReturn()
939     {
940         SetFalseResult();
941     }
942 
SetFrameLayout(CFrameLayout fl)943     void SetFrameLayout(CFrameLayout fl)
944     {
945         frame_layout_ = fl;
946     }
947 
GetFrameLayout()948     const CFrameLayout &GetFrameLayout() const
949     {
950         return frame_layout_;
951     }
952 
GetLiveTmpRegMask()953     RegMask GetLiveTmpRegMask()
954     {
955         return live_tmp_regs_;
956     }
957 
GetLiveTmpFpRegMask()958     VRegMask GetLiveTmpFpRegMask()
959     {
960         return live_tmp_fp_regs_;
961     }
962 
AddRegInLiveMask(Reg reg)963     void AddRegInLiveMask(Reg reg)
964     {
965         if (!reg.IsValid()) {
966             return;
967         }
968         if (reg.IsScalar()) {
969             live_tmp_regs_.set(reg.GetId(), true);
970         } else {
971             ASSERT(reg.IsFloat());
972             live_tmp_fp_regs_.set(reg.GetId(), true);
973         }
974     }
975 
RemoveRegFromLiveMask(Reg reg)976     void RemoveRegFromLiveMask(Reg reg)
977     {
978         if (!reg.IsValid()) {
979             return;
980         }
981         if (reg.IsScalar()) {
982             live_tmp_regs_.set(reg.GetId(), false);
983         } else {
984             ASSERT(reg.IsFloat());
985             live_tmp_fp_regs_.set(reg.GetId(), false);
986         }
987     }
988 
SetCodeOffset(size_t offset)989     void SetCodeOffset(size_t offset)
990     {
991         code_offset_ = offset;
992     }
993 
GetCodeOffset()994     size_t GetCodeOffset() const
995     {
996         return code_offset_;
997     }
998 
EnableLrAsTempReg(bool value)999     void EnableLrAsTempReg(bool value)
1000     {
1001         enable_lr_as_temp_reg_ = value;
1002     }
1003 
IsLrAsTempRegEnabled()1004     bool IsLrAsTempRegEnabled() const
1005     {
1006         return enable_lr_as_temp_reg_;
1007     }
1008 
1009     NO_COPY_SEMANTIC(Encoder);
1010     NO_MOVE_SEMANTIC(Encoder);
1011 
1012 protected:
SetFrameSize(size_t size)1013     void SetFrameSize(size_t size)
1014     {
1015         frame_size_ = size;
1016     }
1017 
GetFrameSize()1018     size_t GetFrameSize() const
1019     {
1020         return frame_size_;
1021     }
1022 
1023     static constexpr size_t INVALID_OFFSET = std::numeric_limits<size_t>::max();
1024 
1025 private:
1026     ArenaAllocator *allocator_;
1027     RegistersDescription *regfile_ {nullptr};
1028     size_t frame_size_ {0};
1029 
1030     CFrameLayout frame_layout_;
1031 
1032     RegMask live_tmp_regs_;
1033     VRegMask live_tmp_fp_regs_;
1034 
1035     // In case of AOT compilation, this variable specifies offset from the start of the AOT file.
1036     // It is needed for accessing to the entrypoints table and AOT table, that lie right before code.
1037     size_t code_offset_ {INVALID_OFFSET};
1038 
1039     Target target_ {Arch::NONE};
1040 
1041     bool success_ {true};
1042     bool js_number_cast_ {false};
1043     // If true, then ScopedTmpReg can use LR as a temp register.
1044     bool enable_lr_as_temp_reg_ {false};
1045 };  // Encoder
1046 
1047 /**
1048  * This class is using to acquire/release temp register using RAII technique.
1049  *
1050  * @tparam lazy if true, temp register will be acquired in the constructor, otherwise user should acquire it explicitly.
1051  */
1052 template <bool lazy>
1053 class ScopedTmpRegImpl {
1054 public:
ScopedTmpRegImpl(Encoder * encoder)1055     explicit ScopedTmpRegImpl(Encoder *encoder) : ScopedTmpRegImpl(encoder, false) {}
ScopedTmpRegImpl(Encoder * encoder,bool with_lr)1056     ScopedTmpRegImpl(Encoder *encoder, bool with_lr) : encoder_(encoder)
1057     {
1058         if constexpr (!lazy) {  // NOLINT
1059             auto link_reg = encoder->GetTarget().GetLinkReg();
1060             with_lr &= encoder->IsLrAsTempRegEnabled();
1061             if (with_lr && encoder->IsScratchRegisterReleased(link_reg)) {
1062                 reg_ = link_reg;
1063                 encoder->AcquireScratchRegister(link_reg);
1064             } else {
1065                 reg_ = encoder->AcquireScratchRegister(Is64BitsArch(encoder->GetArch()) ? INT64_TYPE : INT32_TYPE);
1066             }
1067         }
1068     }
1069 
ScopedTmpRegImpl(Encoder * encoder,TypeInfo type)1070     ScopedTmpRegImpl(Encoder *encoder, TypeInfo type) : encoder_(encoder), reg_(encoder->AcquireScratchRegister(type))
1071     {
1072         static_assert(!lazy);
1073     }
1074 
ScopedTmpRegImpl(Encoder * encoder,Reg reg)1075     ScopedTmpRegImpl(Encoder *encoder, Reg reg) : encoder_(encoder), reg_(reg)
1076     {
1077         static_assert(!lazy);
1078         encoder->AcquireScratchRegister(reg);
1079     }
1080 
ScopedTmpRegImpl(ScopedTmpRegImpl && other)1081     ScopedTmpRegImpl(ScopedTmpRegImpl &&other) noexcept
1082     {
1083         reg_ = other.reg_;
1084         other.reg_ = Reg();
1085         ASSERT(!other.reg_.IsValid());
1086     }
1087 
~ScopedTmpRegImpl()1088     virtual ~ScopedTmpRegImpl()
1089     {
1090         if (reg_.IsValid()) {
1091             encoder_->ReleaseScratchRegister(reg_);
1092         }
1093     }
1094 
1095     NO_COPY_SEMANTIC(ScopedTmpRegImpl);
1096     NO_MOVE_OPERATOR(ScopedTmpRegImpl);
1097 
GetReg()1098     Reg GetReg() const
1099     {
1100         return reg_;
1101     }
1102 
1103     // NOLINTNEXTLINE(google-explicit-constructor)
Reg()1104     operator Reg() const
1105     {
1106         return reg_;
1107     }
1108 
ChangeType(TypeInfo tp)1109     void ChangeType(TypeInfo tp)
1110     {
1111         ASSERT(tp.IsScalar() == reg_.IsScalar());
1112         reg_ = Reg(reg_.GetId(), tp);
1113     }
1114 
Release()1115     void Release()
1116     {
1117         if (reg_.IsValid()) {
1118             encoder_->ReleaseScratchRegister(reg_);
1119             reg_ = INVALID_REGISTER;
1120         }
1121     }
1122 
Acquire()1123     void Acquire()
1124     {
1125         ASSERT(!reg_.IsValid());
1126         reg_ = encoder_->AcquireScratchRegister(Is64BitsArch(encoder_->GetArch()) ? INT64_TYPE : INT32_TYPE);
1127         ASSERT(reg_.IsValid());
1128     }
1129 
AcquireIfInvalid()1130     void AcquireIfInvalid()
1131     {
1132         if (!reg_.IsValid()) {
1133             reg_ = encoder_->AcquireScratchRegister(Is64BitsArch(encoder_->GetArch()) ? INT64_TYPE : INT32_TYPE);
1134             ASSERT(reg_.IsValid());
1135         }
1136     }
1137 
1138 protected:
GetEncoder()1139     Encoder *GetEncoder()
1140     {
1141         return encoder_;
1142     }
1143 
1144 private:
1145     Encoder *encoder_ {nullptr};
1146     Reg reg_;
1147 };
1148 
1149 struct ScopedTmpReg : public ScopedTmpRegImpl<false> {
1150     using ScopedTmpRegImpl<false>::ScopedTmpRegImpl;
1151 };
1152 
1153 struct ScopedTmpRegLazy : public ScopedTmpRegImpl<true> {
1154     using ScopedTmpRegImpl<true>::ScopedTmpRegImpl;
1155 };
1156 
1157 struct ScopedTmpRegU16 : public ScopedTmpReg {
ScopedTmpRegU16ScopedTmpRegU161158     explicit ScopedTmpRegU16(Encoder *encoder) : ScopedTmpReg(encoder, INT16_TYPE) {}
1159 };
1160 
1161 struct ScopedTmpRegU32 : public ScopedTmpReg {
ScopedTmpRegU32ScopedTmpRegU321162     explicit ScopedTmpRegU32(Encoder *encoder) : ScopedTmpReg(encoder, INT32_TYPE) {}
1163 };
1164 
1165 struct ScopedTmpRegU64 : public ScopedTmpReg {
ScopedTmpRegU64ScopedTmpRegU641166     explicit ScopedTmpRegU64(Encoder *encoder) : ScopedTmpReg(encoder, INT64_TYPE) {}
1167 };
1168 
1169 struct ScopedTmpRegF32 : public ScopedTmpReg {
ScopedTmpRegF32ScopedTmpRegF321170     explicit ScopedTmpRegF32(Encoder *encoder) : ScopedTmpReg(encoder, FLOAT32_TYPE) {}
1171 };
1172 
1173 struct ScopedTmpRegF64 : public ScopedTmpReg {
ScopedTmpRegF64ScopedTmpRegF641174     explicit ScopedTmpRegF64(Encoder *encoder) : ScopedTmpReg(encoder, FLOAT64_TYPE) {}
1175 };
1176 
1177 struct ScopedTmpRegRef : public ScopedTmpReg {
ScopedTmpRegRefScopedTmpRegRef1178     explicit ScopedTmpRegRef(Encoder *encoder) : ScopedTmpReg(encoder, encoder->GetRefType()) {}
1179 };
1180 
1181 class ScopedLiveTmpReg : public ScopedTmpReg {
1182 public:
ScopedLiveTmpReg(Encoder * encoder)1183     explicit ScopedLiveTmpReg(Encoder *encoder) : ScopedTmpReg(encoder)
1184     {
1185         encoder->AddRegInLiveMask(GetReg());
1186     }
ScopedLiveTmpReg(Encoder * encoder,TypeInfo type)1187     ScopedLiveTmpReg(Encoder *encoder, TypeInfo type) : ScopedTmpReg(encoder, type)
1188     {
1189         encoder->AddRegInLiveMask(GetReg());
1190     }
~ScopedLiveTmpReg()1191     ~ScopedLiveTmpReg() override
1192     {
1193         GetEncoder()->RemoveRegFromLiveMask(GetReg());
1194     }
1195     NO_COPY_SEMANTIC(ScopedLiveTmpReg);
1196     NO_MOVE_SEMANTIC(ScopedLiveTmpReg);
1197 };
1198 
1199 }  // namespace panda::compiler
1200 
1201 #endif  // COMPILER_OPTIMIZER_CODEGEN_ENCODE_H_
1202