1#!/usr/bin/env ruby 2 3# Copyright (c) 2021-2024 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 60if Options.arch == :arm64 61 $temps_mask = RegMask.new($full_regmap, :tmp0, :tmp1) 62else 63 $temps_mask = RegMask.new($full_regmap, :tmp0, :tmp1, :tmp2) 64end 65# Mask of all callers regsiters, except temp registers 66$panda_callers_mask = RegMask.from_regmap($full_regmap, $callers_regmap) - $temps_mask 67 68# Mask of all callees regsiters, except temp registers 69$panda_callees_mask = RegMask.from_regmap($full_regmap, $callees_regmap) - $temps_mask 70 71# Remove even registers from regmask for ARM32, because compiler conservatively uses two physical registers for one 72# virtual register, e.g. for r0 we should also remove r1. 73if Options.arch == :arm32 74 $default_mask = RegMask.from_value($default_mask. regmap, $default_mask.value & 0x55555555) 75 # Some temps may have even values 76 $temps_mask.each { |x| $default_mask[x + 1] = false } 77end 78 79module Constants 80 TLAB_OFFSET = "cross_values::GetManagedThreadTlabOffset(GetArch())" 81 TLAB_CUR_FREE_POSITION_OFFSET = "cross_values::GetTlabCurFreePositionOffset(GetArch())" 82 TLAB_MEMORY_END_ADDR_OFFSET = "cross_values::GetTlabMemoryEndAddrOffset(GetArch())" 83 OBJECT_CLASS_OFFSET = "cross_values::GetObjectHeaderClassPointerOffset(GetArch())" 84 WRITE_TLAB_STATS_NO_BRIDGE = "cross_values::GetManagedThreadEntrypointOffset(GetArch(), EntrypointId::WRITE_TLAB_STATS_NO_BRIDGE)" 85 ANNOTATE_SANITIZERS_NO_BRIDGE = "cross_values::GetManagedThreadEntrypointOffset(GetArch(), EntrypointId::ANNOTATE_SANITIZERS_NO_BRIDGE)" 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 ARRAY_DATA_OFFSET = "cross_values::GetCoretypesArrayDataOffset(GetArch())" 93 ARRAY_CLASS_SIZE_WITH_ALIGNMENT = "sizeof(coretypes::Array) + TLAB_ALIGNMENT - 1" 94 VREGISTERS_NUM_OFFSET = "cross_values::GetFrameNumVregsOffset(GetArch())" 95 VREGISTERS_OFFSET = "cross_values::GetFrameVregsOffset(GetArch())" 96 VREGISTER_SIZE = "cross_values::GetFrameVregisterSize(GetArch())" 97 FRAME_SIZE = "cross_values::GetFrameSize(GetArch())" 98 DEFAULT_FRAME_ALIGNMENT_IN_BYTES = "GetAlignmentInBytes(DEFAULT_FRAME_ALIGNMENT)" 99 VREGISTER_VALUE_OFFSET = "cross_values::GetFrameVregisterValueOffset(GetArch())" 100 OBJECT_TAG = "cross_values::GetFrameVregisterObjectTag(GetArch())" 101 PRIMITIVE_TAG = "cross_values::GetFrameVregisterPrimitiveTag(GetArch())" 102 GET_ACC_OFFSET = "cross_values::GetFrameAccOffset(GetArch())" 103 GET_ACC_MIRROR_OFFSET = "cross_values::GetFrameAccMirrorOffset(GetArch())" 104 GET_HOTNESS_COUNTER_OFFSET = "cross_values::GetMethodHotnessCounterOffset(GetArch())" 105 GET_FRAME_KIND_OFFSET = "cross_values::GetManagedThreadFrameKindOffset(GetArch())" 106 GET_CLASS_METHODS_OFFSET = "cross_values::GetClassMethodsOffset(GetArch())" 107 METHOD_NUM_ARGS_OFFSET = "cross_values::GetMethodNumArgsOffset(GetArch())" 108 METHOD_CLASS_OFFSET = "cross_values::GetMethodClassOffset(GetArch())" 109 METHOD_PANDA_FILE_OFFSET = "cross_values::GetMethodPandaFileOffset(GetArch())" 110 METHOD_CODE_ID_OFFSET = "cross_values::GetMethodCodeIdOffset(GetArch())" 111 METHOD_NATIVE_POINTER_OFFSET = "cross_values::GetMethodNativePointerOffset(GetArch())" 112 METHOD_COMPILED_ENTRY_POINT_OFFSET = "cross_values::GetMethodCompiledEntryPointOffset(GetArch())" 113 FRAME_NUM_VREGS_OFFSET = "cross_values::GetFrameNumVregsOffset(GetArch())" 114 FRAME_NUM_ACTUAL_ARGS_OFFSET = "cross_values::GetFrameNumActualArgsOffset(GetArch())" 115 FRAME_METHOD_OFFSET = "cross_values::GetFrameMethodOffset(GetArch())" 116 FRAME_PREV_FRAME_OFFSET = "cross_values::GetFramePrevFrameOffset(GetArch())" 117 FRAME_BYTECODE_OFFSET = "cross_values::GetFrameBytecodeOffset(GetArch())" 118 FRAME_FLAGS_OFFSET = "cross_values::GetFrameFlagsOffset(GetArch())" 119 FRAME_NEXT_INSTRUCTION_OFFSET = "cross_values::GetFrameNextInstructionOffset(GetArch())" 120 FRAME_INSTRUCTIONS_OFFSET = "cross_values::GetFrameInstructionsOffset(GetArch())" 121 FRAME_EXT_OFFSET = "cross_values::GetFrameExtOffset(GetArch())" 122 FIELD_ACCESS_FLAGS_OFFSET = "cross_values::GetFieldAccessFlagsOffset(GetArch())" 123 FIELD_OFFSET_OFFSET = "cross_values::GetFieldOffsetOffset(GetArch())" 124 FIELD_CLASS_OFFSET = "cross_values::GetFieldClassOffset(GetArch())" 125 THREAD_STACK_FRAME_ALLOCATOR_OFFSET = "cross_values::GetManagedThreadStackFrameAllocatorOffset(GetArch())" 126 THREAD_FRAME_OFFSET = "cross_values::GetManagedThreadFrameOffset(GetArch())" 127 THREAD_EXCEPTION_OFFSET = "cross_values::GetManagedThreadExceptionOffset(GetArch())" 128 THREAD_INTERPRETER_CACHE_OFFSET = "cross_values::GetManagedThreadInterpreterCacheOffset(GetArch())" 129 THREAD_FLAG_OFFSET = "cross_values::GetManagedThreadFlagOffset(GetArch())" 130 THREAD_VM_OFFSET = "cross_values::GetThreadVmOffset(GetArch())" 131 MARK_WORD_OFFSET = "cross_values::GetObjectHeaderMarkWordOffset(GetArch())" 132 BASE_CLASS_MANAGED_OBJECT_OFFSET = "cross_values::GetBaseClassManagedObjectOffset(GetArch())" 133 BASE_CLASS_FLAGS_OFFSET = "cross_values::GetBaseClassFlagsOffset(graph->GetArch())" 134 INTERNAL_THREAD_ID_OFFSET = "cross_values::GetManagedThreadInternalIdOffset(GetArch())" 135 LOCAL_OBJECTS_LOCKED_ADDR_OFFSET = "cross_values::GetManagedThreadLocalObjectsLockedAddrOffset(GetArch())" 136 LOCKED_OBJECTS_CAPACITY_OFFSET = "cross_values::GetMtManagedThreadLockedObjectCapacityOffset(GetArch())" 137 LOCKED_OBJECTS_SIZE_OFFSET = "cross_values::GetMtManagedThreadLockedObjectSizeOffset(GetArch())" 138 LOCKED_OBJECTS_DATA_OFFSET = "cross_values::GetMtManagedThreadLockedObjectDataOffset(GetArch())" 139 LOCKED_OBJECT_INFO_MONITOR_OFFSET = "cross_values::GetLockedObjectInfoMonitorOffset(GetArch())" 140 LOCKED_OBJECT_INFO_FRAME_OFFSET = "cross_values::GetLockedObjectInfoStackOffset(GetArch())" 141 LOCKED_OBJECT_INFO_SIZE = "cross_values::GetLockedObjectInfoSize(GetArch())" 142 MARK_WORD_STATUS_MASK = "static_cast<uint64_t>(MarkWord::STATUS_MASK)" 143 MARK_WORD_LWL_THREAD_ID_OFFSET = "static_cast<uint64_t>(MarkWord::LIGHT_LOCK_THREADID_SHIFT)" 144 MARK_WORD_LWL_THREAD_ID_MASK = "static_cast<uint64_t>(MarkWord::LIGHT_LOCK_THREADID_MASK_IN_PLACE)" 145 MARK_WORD_LWL_COUNTER_INC = "static_cast<uint64_t>(1 << MarkWord::LIGHT_LOCK_LOCK_COUNT_SHIFT)" 146 MARK_WORD_LWL_COUNTER_MASK = "static_cast<uint64_t>(MarkWord::LIGHT_LOCK_LOCK_COUNT_MASK_IN_PLACE)" 147 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)" 148 MARK_WORD_STATUS_MASK_AND_LWL_THREAD_ID_MASK = "static_cast<uint64_t>(MarkWord::STATUS_MASK | MarkWord::LIGHT_LOCK_THREADID_MASK_IN_PLACE)" 149 CLASS_COMPONENT_OFFSET = "cross_values::GetClassComponentTypeOffset(GetArch())" 150 CLASS_TYPE_OFFSET = "cross_values::GetClassTypeOffset(GetArch())" 151 CLASS_ITABLE_ENTRIES_DATA_OFFSET = "CLASS_ITABLE_OFFSET + CLASS_ITABLE_ENTRIES_DATA_OFFSET" 152 CLASS_ITABLE_ENTRIES_SIZE_OFFSET = "CLASS_ITABLE_OFFSET + CLASS_ITABLE_ENTRIES_SIZE_OFFSET" 153 CLASS_ITABLE_ENTRY_SIZE = "cross_values::GetClassItableEntrySize(GetArch())" 154 CLASS_ITABLE_ENTRY_INTERFACE_OFFSET = "cross_values::GetClassItableEntryInterfaceOffset(GetArch())" 155 METHOD_ACCESS_FLAGS_OFFSET = "cross_values::GetMethodAccessFlagsOffset(GetArch())" 156 157 IC_HANDLER_KIND_BIT = "cross_values::GetIcHandlerKindBitStartBit(graph->GetArch())" 158 IC_HANDLER_KIND_MASK = "cross_values::GetIcHandlerKindBitMask(graph->GetArch())" 159 IC_HANDLER_OFFSET_BIT = "cross_values::GetIcHandlerOffsetBitStartBit(graph->GetArch())" 160 IC_HANDLER_OFFSET_MASK = "cross_values::GetIcHandlerOffsetBitMask(graph->GetArch())" 161 IC_HANDLER_INLINE_BIT = "cross_values::GetIcHandlerInlinedPropsBitStartBit(graph->GetArch())" 162 IC_HANDLER_INLINE_MASK = "cross_values::GetIcHandlerInlinedPropsBitMask(graph->GetArch())" 163 IC_HANDLER_KIND_FIELD = "cross_values::GetIcHandlerHandlerKindField(graph->GetArch())" 164 165 REFERENCE_TYPE_SHIFT = "compiler::DataType::ShiftByType(compiler::DataType::REFERENCE, GetArch())" 166 REFERENCE_TYPE_SIZE = "1 << compiler::DataType::ShiftByType(compiler::DataType::REFERENCE, GetArch())" 167 REFERENCE_PAIR_ALIGNMENT_MASK = "(2 << compiler::DataType::ShiftByType(compiler::DataType::REFERENCE, GetArch())) - 1" 168 169 DYN_UNDEFINED = "AnyBaseType::UNDEFINED_TYPE" 170 TLS_CARD_TABLE_MIN_ADDR_OFFSET = "cross_values::GetManagedThreadCardTableMinAddrOffset(GetArch())" 171 TLS_CARD_TABLE_ADDR_OFFSET = "cross_values::GetManagedThreadCardTableAddrOffset(GetArch())" 172 173 REF_UINT = "DataType::GetIntTypeForReference(GetGraph()->GetArch())" 174 175 REGION_SIZE_BIT = "ark::helpers::math::GetIntLog2(mem::ObjectAllocatorG1<>::GetRegionSize())" 176 MANAGED_THREAD_G1_POST_BARRIER_BUFFER_OFFSET = "cross_values::GetManagedThreadG1PostBarrierBufferOffset(GetArch())" 177 G1_LOCK_BUFFER_DATA_OFFSET = "cross_values::GetG1LockBufferDataOffset(GetArch())" 178 G1_LOCK_BUFFER_TAIL_OFFSET = "cross_values::GetG1LockBufferTailOffset(GetArch())" 179 G1_LOCK_BUFFER_HEAD_OFFSET = "cross_values::GetG1LockBufferHeadOffset(GetArch())" 180 G1_LOCK_BUFFER_SIZE_MASK = "mem::GCG1BarrierSet::G1PostBarrierRingBufferType::RING_BUFFER_SIZE_MASK" 181 CARD_TABLE_CARD_BITS = "mem::CardTable::GetCardBits()" 182 CARD_VALUE_OFFSET = "cross_values::GetCardValueOffset(GetArch())" 183 CARD_CLEAR_VALUE = "mem::CardTable::Card::GetClearValue()" 184 CARD_MARKED_VALUE = "mem::CardTable::Card::GetMarkedValue()" 185 CARD_YOUNG_VALUE = "mem::CardTable::Card::GetYoungValue()" 186 CARD_DIRTY_VALUE = "mem::CardTable::GetCardDirtyValue()" 187 CARD_STATUS_MASK = "mem::CardTable::Card::GetStatusMask()" 188 CARD_HOT_FLAG = "mem::CardTable::Card::GetHotFlag()" 189 CARD_ALIGNMENT_MASK = "cross_values::GetCardAlignmentMask(GetArch())" 190 POINTER_LOG_SIZE = "cross_values::GetPointerLogSize(GetArch())" 191 192 COMPILER_REFERENCE = "compiler::DataType::REFERENCE" 193 COMPILER_BOOL = "compiler::DataType::BOOL" 194 COMPILER_UINT8 = "compiler::DataType::UINT8" 195 COMPILER_UINT16 = "compiler::DataType::UINT16" 196 COMPILER_UINT32 = "compiler::DataType::UINT32" 197 COMPILER_UINT64 = "compiler::DataType::UINT64" 198 COMPILER_INT32 = "compiler::DataType::INT32" 199 COMPILER_PTR = "compiler::DataType::POINTER" 200 201 STRING_CLASS_SIZE = "sizeof(coretypes::String)" 202 STRING_CLASS_SIZE_WITH_ALIGNMENT = "sizeof(coretypes::String) + TLAB_ALIGNMENT - 1" 203 STRING_MUTF8_1B_MAX = "0x7f" 204 STRING_LENGTH_OFFSET = "ark::coretypes::STRING_LENGTH_OFFSET" 205 STRING_HASHCODE_OFFSET = "ark::coretypes::STRING_HASHCODE_OFFSET" 206 STRING_DATA_OFFSET = "ark::coretypes::STRING_DATA_OFFSET" 207 ALIGNMENT_MASK = "~(TLAB_ALIGNMENT - 1)" 208 209 # shift one bit less to keep ACC_INTRINSIC bit 210 INTRINSIC_MASK_SHIFT = "INTRINSIC_SHIFT - VERIFICATION_STATUS_WIDTH - 1" 211 VERIFIED_OK = "static_cast<uint64_t>(Method::VerificationStage::VERIFIED_OK)" 212 end 213 214macro(:call_runtime) { |e, *args| 215 entry := LoadI(%tr).Imm(e).ptr 216 CallIndirect(entry, *args) 217} 218 219macro(:call_runtime_save_all) { |e, *args| 220 Intrinsic(:SAVE_REGISTERS_EP).void 221 ret = call_runtime(e, *args) 222 Intrinsic(:RESTORE_REGISTERS_EP).void 223 ret 224} 225 226macro(:i32tou32) do |arg| 227 Cast(arg).SrcType("DataType::INT32").u32 228end 229 230macro(:u32toi32) do |arg| 231 Cast(arg).SrcType("DataType::UINT32").i32 232end 233 234macro(:i32tof64) do |arg| 235 Cast(arg).SrcType("DataType::INT32").f64 236end 237 238macro(:u32tof64) do |arg| 239 Cast(arg).SrcType("DataType::UINT32").f64 240end 241 242macro(:f64tou32) do |arg| 243 Cast(arg).SrcType("DataType::FLOAT64").u32 244end 245 246macro(:f64toi64) do |arg| 247 Cast(arg).SrcType("DataType::FLOAT64").i64 248end 249 250macro(:u64tou32) do |arg| 251 Cast(arg).SrcType("DataType::UINT64").u32 252end 253 254macro(:i32toanychecked) do |arg| 255 If(arg, 0).LT.b { 256 cast_res0 := f64toany(i32tof64(arg)) 257 } Else { 258 cast_res1 := i32toany(arg) 259 } 260 Phi(cast_res0, cast_res1).any 261end 262 263macro(:anytoi32) do |arg| 264 CastAnyTypeValue(arg).AnyType("AnyBaseType::ECMASCRIPT_INT_TYPE").i32 265end 266 267macro(:anytof64) do |arg| 268 CastAnyTypeValue(arg).AnyType("AnyBaseType::ECMASCRIPT_DOUBLE_TYPE").f64 269end 270 271macro(:anytou32) do |arg| 272 i32tou32(CastAnyTypeValue(arg).AnyType("AnyBaseType::ECMASCRIPT_INT_TYPE").i32) 273end 274 275macro(:anytoheapobj) do |arg| 276 CastAnyTypeValue(arg) 277 .AnyType("AnyBaseType::ECMASCRIPT_HEAP_OBJECT_TYPE") 278 .SetFlag("ark::compiler::inst_flags::Flags::NO_CSE") 279 .SetFlag("ark::compiler::inst_flags::Flags::NO_HOIST") 280 .ref 281end 282 283macro(:heapobjtoany) do |arg| 284 CastValueToAnyType(arg).AnyType("AnyBaseType::ECMASCRIPT_HEAP_OBJECT_TYPE").any 285end 286 287['8', '16'].each do |from| 288 ['u32', 'u64'].each do |to| 289 macro(:"u#{from}to#{to}") do |arg| 290 Cast(arg).SrcType("DataType::UINT#{from}").send(:"#{to}") 291 end 292 end 293end 294 295['8', '16'].each do |from| 296 macro(:"i#{from}toi32") do |arg| 297 Cast(arg).SrcType("DataType::INT#{from}").i32 298 end 299end 300 301[['u32', 'UINT32'], ['i32', 'INT32']].each do |from, from_type| 302 ['b', 'i8', 'u8', 'i16', 'u16', 'i64', 'u64'].each do |to| 303 macro(:"#{from}to#{to}") do |arg| 304 Cast(arg).SrcType("DataType::#{from_type}").send(:"#{to}") 305 end 306 end 307end 308 309macro(:get_class) do |arg| 310 Intrinsic(:DYN_OBJECT_GET_CLASS, arg).ref 311end 312 313macro(:get_bits) do |data, offset, mask| 314 AndI(ShrI(data).Imm(offset).i32).Imm(mask).i32 315end 316 317macro(:set_bits) do |data, offset, mask, bits| 318 Or(data, ShlI(AndI(bits).Imm(mask).i32).Imm(offset).i32).i32 319end 320 321macro(:nullptr) do 322 src_type = Options.arch_64_bits? ? 'DataType::INT64' : 'DataType::INT32' 323 Bitcast(0).SrcType(src_type).ptr 324end 325 326macro(:get_entrypoint_offset) do |entrypoint_id| 327 "cross_values::GetManagedThreadEntrypointOffset(GetArch(), EntrypointId::#{entrypoint_id})" 328end 329