1#!/usr/bin/env ruby 2 3# Copyright (c) 2021-2022 Huawei Device Co., Ltd. 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15 16$panda_regmap = Regmap.new({ 17 arm64: {tr: 28}, 18 arm32: {tr: 10}, 19 x86_64: {tr: 15} 20}) 21 22$arch_regmap = Regmap.new({ 23 arm64: {fp: 29, sp: 31, lr: 30}, 24 arm32: {fp: 11, sp: 13, lr: 14, pc: 15}, 25 x86_64: {fp: 9, sp: 10} 26}) 27 28$args_regmap = Regmap.new({ 29 arm64: {fp: 29, sp: 31, ret: 0, arg0: 0, arg1: 1, arg2: 2, arg3: 3, arg4: 4, arg5: 5, arg6: 6, arg7: 7}, 30 arm32: {fp: 11, sp: 13, ret: 0, arg0: 0, arg1: 1, arg2: 2, arg3: 3}, 31 x86_64: {fp: 9, sp: 10, ret: 0, arg0: 7, arg1: 6, arg2: 2, arg3: 1, arg4: 8, arg5: 5} 32}) 33 34# Regmap for temp registers 35$temps_regmap = Regmap.new(Options.arch_info.temp_regs.each_with_index.map { |x, i| ["tmp#{i}".to_sym, x] }.to_h, 36 direct: true) 37 38$callees_regmap = Regmap.new({ 39 arm64: (19..28).each_with_index.map { |x, i| ["callee#{i}".to_sym, x] }.to_h, 40 arm32: (4..10).each_with_index.map { |x, i| ["callee#{i}".to_sym, x] }.to_h, 41 x86_64: (11..15).each_with_index.map { |x, i| ["callee#{i}".to_sym, x] }.to_h, 42}) 43 44$callers_regmap = Regmap.new({ 45 arm64: (0..18).each_with_index.map { |x, i| ["caller#{i}".to_sym, x] }.to_h, 46 arm32: (0..3).each_with_index.map { |x, i| ["caller#{i}".to_sym, x] }.to_h, 47 x86_64: (0..8).each_with_index.map { |x, i| ["caller#{i}".to_sym, x] }.to_h, 48}) 49 50# Regmap that contains all defined regmap 51$full_regmap = $panda_regmap + $args_regmap + $arch_regmap + $temps_regmap + $callees_regmap + $callers_regmap 52 53# In default mask we use all registers, except temps and special arch registers(e.g. lr) 54$default_mask = ~RegMask.new($full_regmap, *(Options.arch_info.temp_regs)) - $arch_regmap 55 56# Panda mask is the mask intended to be used with Panda ABI. Currently, we just remove thread reg from the default mask. 57$panda_mask = $default_mask - :tr 58 59# Temporary registers mask 60$temps_mask = RegMask.new($full_regmap, :tmp0, :tmp1, :tmp2) 61 62# Mask of all callers regsiters, except temp registers 63$panda_callers_mask = RegMask.from_regmap($full_regmap, $callers_regmap) - $temps_mask 64 65# Mask of all callees regsiters, except temp registers 66$panda_callees_mask = RegMask.from_regmap($full_regmap, $callees_regmap) - $temps_mask 67 68# Remove even registers from regmask for ARM32, because compiler conservatively uses two physical registers for one 69# virtual register, e.g. for r0 we should also remove r1. 70if Options.arch == :arm32 71 $default_mask = RegMask.from_value($default_mask. regmap, $default_mask.value & 0x55555555) 72 # Some temps may have even values 73 $temps_mask.each { |x| $default_mask[x + 1] = false } 74end 75 76module Constants 77 TLAB_OFFSET = "cross_values::GetManagedThreadTlabOffset(GetArch())" 78 TLAB_CUR_FREE_POSITION_OFFSET = "cross_values::GetTlabCurFreePositionOffset(GetArch())" 79 TLAB_MEMORY_END_ADDR_OFFSET = "cross_values::GetTlabMemoryEndAddrOffset(GetArch())" 80 CREATE_OBJECT_BY_CLASS = "cross_values::GetManagedThreadEntrypointOffset(GetArch(), EntrypointId::CREATE_OBJECT_BY_CLASS_SLOW_PATH)" 81 OBJECT_CLASS_OFFSET = "cross_values::GetObjectHeaderClassPointerOffset(GetArch())" 82 WRITE_TLAB_STATS_NO_BRIDGE = "cross_values::GetManagedThreadEntrypointOffset(GetArch(), EntrypointId::WRITE_TLAB_STATS_NO_BRIDGE)" 83 WRITE_TLAB_STATS = "cross_values::GetManagedThreadEntrypointOffset(GetArch(), EntrypointId::WRITE_TLAB_STATS)" 84 ANNOTATE_SANITIZERS_NO_BRIDGE = "cross_values::GetManagedThreadEntrypointOffset(GetArch(), EntrypointId::ANNOTATE_SANITIZERS_NO_BRIDGE)" 85 CREATE_ARRAY_SLOW_PATH = "cross_values::GetManagedThreadEntrypointOffset(GetArch(), EntrypointId::CREATE_ARRAY_SLOW_PATH)" 86 GET_CALLEE_METHOD = "cross_values::GetManagedThreadEntrypointOffset(GetArch(), EntrypointId::GET_CALLEE_METHOD_DIRECT)" 87 INITIALIZE_CLASS_BY_ID = "cross_values::GetManagedThreadEntrypointOffset(GetArch(), EntrypointId::INITIALIZE_CLASS_BY_ID_DIRECT)" 88 RESOLVE_CLASS = "cross_values::GetManagedThreadEntrypointOffset(GetArch(), EntrypointId::RESOLVE_CLASS_DIRECT)" 89 GET_VTABLE_INDEX = "cross_values::GetMethodVTableIndexOffset(GetArch())" 90 CLASS_STATE_OFFSET = "cross_values::GetClassStateOffset(GetArch())" 91 ARRAY_LENGTH_OFFSET = "cross_values::GetCoretypesArrayLengthOffset(GetArch())" 92 VREGISTERS_NUM_OFFSET = "cross_values::GetFrameNumVregsOffset(GetArch())" 93 VREGISTERS_OFFSET = "cross_values::GetFrameVregsOffset(GetArch())" 94 VREGISTER_SIZE = "cross_values::GetFrameVregisterSize(GetArch())" 95 VREGISTER_VALUE_OFFSET = "cross_values::GetFrameVregisterValueOffset(GetArch())" 96 GET_ACC_OFFSET = "cross_values::GetFrameAccOffset(GetArch())" 97 GET_ACC_MIRROR_OFFSET = "cross_values::GetFrameAccMirrorOffset(GetArch())" 98 RESOLVE_VIRTUAL_CALL_AOT = "cross_values::GetManagedThreadEntrypointOffset(GetArch(), EntrypointId::RESOLVE_VIRTUAL_CALL_AOT)" 99 GET_CLASS_METHODS_OFFSET = "cross_values::GetClassMethodsOffset(GetArch())" 100 FRAME_METHOD_OFFSET = "Frame::GetMethodOffset()" 101 FRAME_INSTRUCTIONS_OFFSET = "Frame::GetInstructionsOffset()" 102 MARK_WORD_OFFSET = "cross_values::GetObjectHeaderMarkWordOffset(GetArch())" 103 INTERNAL_THREAD_ID_OFFSET = "cross_values::GetManagedThreadInternalIdOffset(GetArch())" 104 LOCAL_OBJECTS_LOCKED_ADDR_OFFSET = "cross_values::GetManagedThreadLocalObjectsLockedAddrOffset(GetArch())" 105 LOCKED_OBJECTS_CAPACITY_OFFSET = "cross_values::GetMtManagedThreadLockedObjectCapacityOffset(GetArch())" 106 LOCKED_OBJECTS_SIZE_OFFSET = "cross_values::GetMtManagedThreadLockedObjectSizeOffset(GetArch())" 107 LOCKED_OBJECTS_DATA_OFFSET = "cross_values::GetMtManagedThreadLockedObjectDataOffset(GetArch())" 108 LOCKED_OBJECT_INFO_MONITOR_OFFSET = "cross_values::GetLockedObjectInfoMonitorOffset(GetArch())" 109 LOCKED_OBJECT_INFO_FRAME_OFFSET = "cross_values::GetLockedObjectInfoStackOffset(GetArch())" 110 LOCKED_OBJECT_INFO_SIZE = "cross_values::GetLockedObjectInfoSize(GetArch())" 111 MONITOR_ENTER_SLOW_PATH = "cross_values::GetManagedThreadEntrypointOffset(GetArch(), EntrypointId::MONITOR_ENTER_SLOW_PATH)" 112 MONITOR_EXIT_SLOW_PATH = "cross_values::GetManagedThreadEntrypointOffset(GetArch(), EntrypointId::MONITOR_EXIT_SLOW_PATH)" 113 CHECK_CAST_SLOW_PATH = "cross_values::GetManagedThreadEntrypointOffset(GetArch(), EntrypointId::CHECK_CAST)" 114 MARK_WORD_STATUS_MASK = "static_cast<uint64_t>(MarkWord::STATUS_MASK)" 115 MARK_WORD_LWL_THREAD_ID_OFFSET = "static_cast<uint64_t>(MarkWord::LIGHT_LOCK_THREADID_SHIFT)" 116 MARK_WORD_LWL_THREAD_ID_MASK = "static_cast<uint64_t>(MarkWord::LIGHT_LOCK_THREADID_MASK_IN_PLACE)" 117 MARK_WORD_LWL_COUNTER_INC = "static_cast<uint64_t>(1 << MarkWord::LIGHT_LOCK_LOCK_COUNT_SHIFT)" 118 MARK_WORD_LWL_COUNTER_MASK = "static_cast<uint64_t>(MarkWord::LIGHT_LOCK_LOCK_COUNT_MASK_IN_PLACE)" 119 MARK_WORD_LWL_THREAD_ID_AND_COUNTER_MASK = "static_cast<uint64_t>(MarkWord::LIGHT_LOCK_THREADID_MASK_IN_PLACE | MarkWord::LIGHT_LOCK_LOCK_COUNT_MASK_IN_PLACE)" 120 MARK_WORD_STATUS_MASK_AND_LWL_THREAD_ID_MASK = "static_cast<uint64_t>(MarkWord::STATUS_MASK | MarkWord::LIGHT_LOCK_THREADID_MASK_IN_PLACE)" 121 CLASS_COMPONENT_OFFSET = "cross_values::GetClassComponentTypeOffset(GetArch())" 122 CLASS_TYPE_OFFSET = "cross_values::GetClassTypeOffset(GetArch())" 123 CLASS_ITABLE_ENTRIES_DATA_OFFSET = "CLASS_ITABLE_OFFSET + CLASS_ITABLE_ENTRIES_DATA_OFFSET" 124 CLASS_ITABLE_ENTRIES_SIZE_OFFSET = "CLASS_ITABLE_OFFSET + CLASS_ITABLE_ENTRIES_SIZE_OFFSET" 125 CLASS_ITABLE_ENTRY_SIZE = "cross_values::GetClassItableEntrySize(GetArch())" 126 CLASS_ITABLE_ENTRY_INTERFACE_OFFSET = "cross_values::GetClassItableEntryInterfaceOffset(GetArch())" 127 IS_INSTANCE_BY_BCID = "cross_values::GetManagedThreadEntrypointOffset(GetArch(), EntrypointId::IS_INSTANCE_BY_BCID)" 128 CHECK_CAST_BY_BCID = "cross_values::GetManagedThreadEntrypointOffset(GetArch(), EntrypointId::CHECK_CAST_BY_BCID)" 129 130 IC_HANDLER_KIND_BIT = "cross_values::GetIcHandlerKindBitStartBit(graph->GetArch())" 131 IC_HANDLER_KIND_MASK = "cross_values::GetIcHandlerKindBitMask(graph->GetArch())" 132 IC_HANDLER_OFFSET_BIT = "cross_values::GetIcHandlerOffsetBitStartBit(graph->GetArch())" 133 IC_HANDLER_OFFSET_MASK = "cross_values::GetIcHandlerOffsetBitMask(graph->GetArch())" 134 IC_HANDLER_INLINE_BIT = "cross_values::GetIcHandlerInlinedPropsBitStartBit(graph->GetArch())" 135 IC_HANDLER_INLINE_MASK = "cross_values::GetIcHandlerInlinedPropsBitMask(graph->GetArch())" 136 137 IC_HANDLER_KIND_FIELD = "cross_values::GetIcHandlerHandlerKindField(graph->GetArch())" 138 DYN_INT_TYPE = "AnyBaseType::UNDEFINED_TYPE" 139 DYN_DOUBLE_TYPE = "AnyBaseType::UNDEFINED_TYPE" 140 141end 142macro(:call_runtime) { |e, *args| 143 entry := LoadI(%tr).Imm(e).ptr 144 CallIndirect(entry, *args) 145} 146 147macro(:call_runtime_save_all) { |e, *args| 148 Intrinsic(:SAVE_REGISTERS_EP).void 149 ret = call_runtime(e, *args) 150 Intrinsic(:RESTORE_REGISTERS_EP).void 151 ret 152} 153