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