1 /* 2 * Copyright (c) 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 ECMASCRIPT_COMPILER_EXTENDED_ASSEMBLER_X64_H 17 #define ECMASCRIPT_COMPILER_EXTENDED_ASSEMBLER_X64_H 18 19 #include "ecmascript/compiler/assembler/x64/assembler_x64.h" 20 #include "ecmascript/compiler/assembler_module.h" 21 #include "ecmascript/compiler/bc_call_signature.h" 22 23 namespace panda::ecmascript::x64 { 24 // ExtendedAssembler implements frequently-used assembler macros with some extended usages. 25 class ExtendedAssembler : public AssemblerX64 { 26 public: 27 static constexpr int FRAME_SLOT_SIZE = 8; ExtendedAssembler(Chunk * chunk,kungfu::AssemblerModule * module)28 ExtendedAssembler(Chunk *chunk, kungfu::AssemblerModule *module) 29 : AssemblerX64(chunk), module_(module) 30 { 31 } 32 void CallAssemblerStub(int id, bool isTail); 33 void BindAssemblerStub(int id); 34 void PushAlignBytes(); 35 void PopAlignBytes(); 36 void PushCppCalleeSaveRegisters(); 37 void PopCppCalleeSaveRegisters(); 38 void UpdateCalleeSaveRegisters(); 39 void PushGhcCalleeSaveRegisters(); 40 void PopGhcCalleeSaveRegisters(); 41 void PushArgsWithArgv(Register argc, Register argv, Register operatorRegister); 42 void PushArgc(int32_t argc, Register tempArgcRegister); 43 void PushArgc(Register argcRegister, Register tempArgcRegister); 44 TempRegister()45 Register TempRegister() 46 { 47 if (tempInUse_) { 48 LOG_COMPILER(FATAL) << "temp register inuse."; 49 UNREACHABLE(); 50 } 51 tempInUse_ = true; 52 return rax; 53 } AvailableRegister1()54 Register AvailableRegister1() const 55 { 56 // r10 is neither callee saved reegister nor argument register 57 return r10; 58 } AvailableRegister2()59 Register AvailableRegister2() const 60 { 61 // r11 is neither callee saved reegister nor argument register 62 return r11; 63 } CppJSCallAvailableRegister1()64 Register CppJSCallAvailableRegister1() const 65 { 66 return r13; 67 } CppJSCallAvailableRegister2()68 Register CppJSCallAvailableRegister2() const 69 { 70 return r14; 71 } CallDispatcherArgument(kungfu::CallDispatchInputs index)72 Register CallDispatcherArgument(kungfu::CallDispatchInputs index) 73 { 74 size_t i = static_cast<size_t>(index); 75 Register ret = isGhcCallingConv_ ? ghcJSCallDispacherArgs_[i] : cppJSCallDispacherArgs_[i]; 76 if (ret == rInvalid) { 77 LOG_COMPILER(FATAL) << "x64 invalid call argument:" << i; 78 } 79 return ret; 80 } GlueRegister()81 Register GlueRegister() 82 { 83 return isGhcCallingConv_ ? r13 : rdi; 84 } 85 FromInterpreterHandler()86 bool FromInterpreterHandler() const 87 { 88 return isGhcCallingConv_; 89 } 90 91 private: 92 kungfu::AssemblerModule *module_; 93 bool isGhcCallingConv_ {false}; 94 bool tempInUse_ {false}; 95 friend class TempRegisterScope; 96 97 static constexpr size_t JS_CALL_DISPATCHER_ARGS_COUNT = 98 static_cast<size_t>(kungfu::CallDispatchInputs::NUM_OF_INPUTS); 99 static Register ghcJSCallDispacherArgs_[JS_CALL_DISPATCHER_ARGS_COUNT]; 100 static Register cppJSCallDispacherArgs_[JS_CALL_DISPATCHER_ARGS_COUNT]; 101 }; 102 103 class TempRegisterScope { 104 public: TempRegisterScope(ExtendedAssembler * assembler)105 explicit TempRegisterScope(ExtendedAssembler *assembler) : assembler_(assembler) {} ~TempRegisterScope()106 ~TempRegisterScope() 107 { 108 assembler_->tempInUse_ = false; 109 } 110 111 NO_COPY_SEMANTIC(TempRegisterScope); 112 NO_MOVE_SEMANTIC(TempRegisterScope); 113 private: 114 ExtendedAssembler *assembler_; 115 }; 116 } // panda::ecmascript::x64 117 #endif // ECMASCRIPT_COMPILER_EXTENDED_ASSEMBLER_X64_H