From 40b603ed2b59db8ac5428216a1eee848be977a9b Mon Sep 17 00:00:00 2001 From: rhuanjl Date: Tue, 14 Feb 2023 17:32:23 +0000 Subject: [PATCH] Incomplete Backend support for Apple Silicon - Enables dynamic interpretor thunks on Apple Silicon - Remainder of the JIT will compile with these edits but not yet work --- lib/Backend/CMakeLists.txt | 82 ++++++++++++------ lib/Backend/InterpreterThunkEmitter.cpp | 17 ++++ lib/Backend/InterpreterThunkEmitter.h | 5 ++ lib/Backend/LinearScan.cpp | 4 +- lib/Backend/arm64/ARM64Encoder.h | 12 +++ lib/Backend/arm64/LinearScanMdA.S | 107 ++++++++++++++++++++++++ lib/Backend/arm64/LowerMD.h | 3 +- lib/Backend/arm64/Thunks.S | 46 ++++++++++ 8 files changed, 249 insertions(+), 27 deletions(-) create mode 100644 lib/Backend/arm64/LinearScanMdA.S create mode 100644 lib/Backend/arm64/Thunks.S diff --git a/lib/Backend/CMakeLists.txt b/lib/Backend/CMakeLists.txt index 6825144d4eb..f4b923b58d9 100644 --- a/lib/Backend/CMakeLists.txt +++ b/lib/Backend/CMakeLists.txt @@ -1,5 +1,59 @@ +if(CC_TARGETS_AMD64) + set (CC_BACKEND_ARCH_FOLDER amd64) + set (CC_BACKEND_ARCH_FILES + amd64/EncoderMD.cpp + amd64/LinearScanMD.cpp + amd64/LowererMDArch.cpp + amd64/PeepsMD.cpp + amd64/PrologEncoderMD.cpp + amd64/LinearScanMdA.S + amd64/Thunks.S + AgenPeeps.cpp + EhFrame.cpp + LowerMDShared.cpp + LowerMDSharedSimd128.cpp + PrologEncoder.cpp + ) +elseif(CC_TARGETS_X86) + set (CC_BACKEND_ARCH_FOLDER i386) + set (CC_BACKEND_ARCH_FILES + i386/EncoderMD.cpp + i386/LinearScanMD.cpp + i386/LowererMDArch.cpp + i386/PeepsMD.cpp + AgenPeeps.cpp + LowerMDShared.cpp + LowerMDSharedSimd128.cpp + ) +elseif(CC_TARGETS_ARM64) + set (CC_BACKEND_ARCH_FOLDER arm64) + set (CC_BACKEND_ARCH_FILES + arm64/ARM64LogicalImmediates.cpp + arm64/ARM64UnwindEncoder.cpp + arm64/EncoderMD.cpp + arm64/LegalizeMD.cpp + arm64/LinearScanMD.cpp + arm64/LinearScanMdA.S + arm64/LowerMD.cpp + arm64/PeepsMD.cpp + arm64/Thunks.S + arm64/UnwindInfoManager.cpp + ) +elseif(CC_TARGETS_ARM) + set (CC_BACKEND_ARCH_FOLDER arm) + set (CC_BACKEND_ARCH_FILES + arm/EncoderMD.cpp + arm/LegalizeMD.cpp + arm/LinearScanMD.cpp + arm/LinearScanMdA.asm + arm/LowerMD.cpp + arm/PeepsMD.cpp + arm/Thunks.asm + arm/UnwindInfoManager.cpp + ) +endif() + add_library (Chakra.Backend OBJECT - AgenPeeps.cpp AsmJsJITInfo.cpp Backend.cpp BackendApi.cpp @@ -12,7 +66,6 @@ add_library (Chakra.Backend OBJECT CodeGenWorkItem.cpp DbCheckPostLower.cpp Debug.cpp - EhFrame.cpp EmitBuffer.cpp Encoder.cpp EquivalentTypeSet.cpp @@ -57,8 +110,6 @@ add_library (Chakra.Backend OBJECT JnHelperMethod.cpp LinearScan.cpp Lower.cpp - LowerMDShared.cpp - LowerMDSharedSimd128.cpp NativeCodeData.cpp NativeCodeGenerator.cpp NativeEntryPointData.cpp @@ -68,7 +119,6 @@ add_library (Chakra.Backend OBJECT PageAllocatorPool.cpp Peeps.cpp PreLowerPeeps.cpp - PrologEncoder.cpp QueuedFullJitWorkItem.cpp Region.cpp SccLiveness.cpp @@ -83,30 +133,12 @@ add_library (Chakra.Backend OBJECT TempTracker.cpp ValueInfo.cpp ValueRelativeOffset.cpp - amd64/EncoderMD.cpp - amd64/LinearScanMD.cpp - amd64/LowererMDArch.cpp - amd64/PeepsMD.cpp - amd64/PrologEncoderMD.cpp - amd64/LinearScanMdA.S - amd64/Thunks.S -# arm64/EncoderMD.cpp -# arm64/LowerMD.cpp -# arm/EncoderMD.cpp -# arm/LegalizeMD.cpp -# arm/LinearScanMD.cpp -# arm/LowerMD.cpp -# arm/PeepsMD.cpp -# arm/UnwindInfoManager.cpp -# i386/EncoderMD.cpp -# i386/LinearScanMD.cpp -# i386/LowererMDArch.cpp -# i386/PeepsMD.cpp + ${CC_BACKEND_ARCH_FILES} ) target_include_directories ( Chakra.Backend PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} - amd64 + ${CC_BACKEND_ARCH_FOLDER} ../Common ../JITIDL ../Runtime diff --git a/lib/Backend/InterpreterThunkEmitter.cpp b/lib/Backend/InterpreterThunkEmitter.cpp index e7f9bcbcb03..7d459f47a5d 100644 --- a/lib/Backend/InterpreterThunkEmitter.cpp +++ b/lib/Backend/InterpreterThunkEmitter.cpp @@ -1,5 +1,6 @@ //------------------------------------------------------------------------------------------------------- // Copyright (C) Microsoft. All rights reserved. +// Copyright (c) ChakraCore Project Contributors. All rights reserved. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. //------------------------------------------------------------------------------------------------------- #include "Backend.h" @@ -157,19 +158,31 @@ constexpr BYTE Epilog[] = { }; #elif defined(_M_ARM64) +#ifdef _WIN32 constexpr BYTE FunctionInfoOffset = 24; constexpr BYTE FunctionProxyOffset = 28; constexpr BYTE DynamicThunkAddressOffset = 32; constexpr BYTE ThunkAddressOffset = 36; +#else +constexpr BYTE FunctionInfoOffset = 8; +constexpr BYTE FunctionProxyOffset = 12; +constexpr BYTE DynamicThunkAddressOffset = 16; +constexpr BYTE ThunkAddressOffset = 20; +#endif //TODO: saravind :Implement Range Check for ARM64 constexpr BYTE InterpreterThunk[InterpreterThunkEmitter::InterpreterThunkSize] = { +#ifdef _WIN32 0xFD, 0x7B, 0xBB, 0xA9, //stp fp, lr, [sp, #-80]! ;Prologue 0xFD, 0x03, 0x00, 0x91, //mov fp, sp ;update frame pointer to the stack pointer 0xE0, 0x07, 0x01, 0xA9, //stp x0, x1, [sp, #16] ;Prologue again; save all registers 0xE2, 0x0F, 0x02, 0xA9, //stp x2, x3, [sp, #32] 0xE4, 0x17, 0x03, 0xA9, //stp x4, x5, [sp, #48] 0xE6, 0x1F, 0x04, 0xA9, //stp x6, x7, [sp, #64] +#else + 0xFD, 0x7B, 0xBF, 0xA9, //stp fp, lr, [sp, #-16]! ;Prologue + 0xFD, 0x03, 0x00, 0x91, //mov fp, sp ;update frame pointer to the stack pointer +#endif 0x02, 0x00, 0x40, 0xF9, //ldr x2, [x0, #0x00] ;offset will be replaced with Offset of FunctionInfo 0x40, 0x00, 0x40, 0xF9, //ldr x0, [x2, #0x00] ;offset will be replaced with Offset of FunctionProxy 0x03, 0x00, 0x40, 0xF9, //ldr x3, [x0, #0x00] ;offset will be replaced with offset of DynamicInterpreterThunk @@ -191,7 +204,11 @@ constexpr BYTE Call[] = { }; constexpr BYTE Epilog[] = { +#ifdef _WIN32 0xfd, 0x7b, 0xc5, 0xa8, // ldp fp, lr, [sp], #80 +#else + 0xfd, 0x7b, 0xc1, 0xa8, // ldp fp, lr, [sp], #16 +#endif 0xc0, 0x03, 0x5f, 0xd6 // ret }; #else // x86 diff --git a/lib/Backend/InterpreterThunkEmitter.h b/lib/Backend/InterpreterThunkEmitter.h index 2420ca7a5b3..10c4fc4d769 100644 --- a/lib/Backend/InterpreterThunkEmitter.h +++ b/lib/Backend/InterpreterThunkEmitter.h @@ -1,5 +1,6 @@ //------------------------------------------------------------------------------------------------------- // Copyright (C) Microsoft. All rights reserved. +// Copyright (c) ChakraCore Project Contributors. All rights reserved. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. //------------------------------------------------------------------------------------------------------- #pragma once @@ -68,7 +69,11 @@ class InterpreterThunkEmitter #elif defined(_M_ARM) static constexpr size_t InterpreterThunkSize = 72; #elif defined(_M_ARM64) +#ifdef _WIN32 static constexpr size_t InterpreterThunkSize = 64; +#else + static constexpr size_t InterpreterThunkSize = 48; +#endif #else static constexpr size_t InterpreterThunkSize = 56; #endif diff --git a/lib/Backend/LinearScan.cpp b/lib/Backend/LinearScan.cpp index aa214b4f477..ed0c8026eb4 100644 --- a/lib/Backend/LinearScan.cpp +++ b/lib/Backend/LinearScan.cpp @@ -1,6 +1,6 @@ //------------------------------------------------------------------------------------------------------- // Copyright (C) Microsoft Corporation and contributors. All rights reserved. -// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved. +// Copyright (c) ChakraCore Project Contributors. All rights reserved. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. //------------------------------------------------------------------------------------------------------- @@ -4948,6 +4948,8 @@ LinearScan::GeneratorBailIn::GeneratorBailIn(Func* func, LinearScan* linearScan) RegRAX, RegRCX #elif defined(_M_IX86) RegEAX, RegECX +#elif defined(_M_ARM64) + RegR0, RegR1 #endif }, interpreterFrameRegOpnd { IR::RegOpnd::New(nullptr, regs[0], TyMachPtr, func) }, diff --git a/lib/Backend/arm64/ARM64Encoder.h b/lib/Backend/arm64/ARM64Encoder.h index cddc110283a..14e04821b23 100644 --- a/lib/Backend/arm64/ARM64Encoder.h +++ b/lib/Backend/arm64/ARM64Encoder.h @@ -1,5 +1,6 @@ //------------------------------------------------------------------------------------------------------- // Copyright (C) Microsoft. All rights reserved. +// Copyright (c) ChakraCore Project Contributors. All rights reserved. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. //------------------------------------------------------------------------------------------------------- #pragma once @@ -817,6 +818,17 @@ EmitDiv0Exception( // // MRS dest, systemreg // +#ifndef _WIN32 +#define ARM64_SYSREG(op0, op1, crn, crm, op2) \ + ( ((op0 & 1) << 14) | \ + ((op1 & 7) << 11) | \ + ((crn & 15) << 7) | \ + ((crm & 15) << 3) | \ + ((op2 & 7) << 0) ) + +#define ARM64_FPCR ARM64_SYSREG(3, 3, 4, 4, 0) // Floating point control register (EL0) +#define ARM64_FPSR ARM64_SYSREG(3, 3, 4, 4, 1) // Floating point status register (EL0) +#endif #define ARM64_NZCV ARM64_SYSREG(3,3, 4, 2,0) // Flags (EL0); arm64_x.h #define ARM64_CNTVCT ARM64_SYSREG(3,3,14, 0,2) // Generic Timer virtual count diff --git a/lib/Backend/arm64/LinearScanMdA.S b/lib/Backend/arm64/LinearScanMdA.S new file mode 100644 index 00000000000..c137a605b51 --- /dev/null +++ b/lib/Backend/arm64/LinearScanMdA.S @@ -0,0 +1,107 @@ +;------------------------------------------------------------------------------------------------------- +; Copyright (C) Microsoft. All rights reserved. +; Copyright (c) ChakraCore Project Contributors. All rights reserved. +; Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. +;------------------------------------------------------------------------------------------------------- + +#include "unixasmmacros.inc" + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; LinearScanMD::SaveAllRegistersAndBailOut(BailOutRecord *const bailOutRecord) + +NESTED_ENTRY _ZN12LinearScanMD26SaveAllRegistersAndBailOutEP13BailOutRecord, _TEXT, NoHandler + + ; x0 == bailOutRecord + ; lr == return address + + ; Save all registers except the above, which would have already been saved by jitted code if necessary + ldr x17, [x0] ; bailOutRecord->globalBailOutRecordDataTable + ldr x17, [x17] ; bailOutRecord->globalBailOutRecordDataTable->registerSaveSpace + str x1, [x17, #1*8] + stp x2, x3, [x17, #2*8] + stp x4, x5, [x17, #4*8] + stp x6, x7, [x17, #6*8] + stp x8, x9, [x17, #8*8] + stp x10, x11, [x17, #10*8] + stp x12, x13, [x17, #12*8] + stp x14, x15, [x17, #14*8] + str x16, [x17, #16*8] + ; skip x17/x18 + stp x19, x20, [x17, #19*8] + stp x21, x22, [x17, #21*8] + stp x23, x24, [x17, #23*8] + stp x25, x26, [x17, #25*8] + stp x27, x28, [x17, #27*8] + str fp, [x17, #29*8] + ; skip lr, sp, zr + add x17, x17, #33*8 + stp d0, d1, [x17, #0*8] + stp d2, d3, [x17, #2*8] + stp d4, d5, [x17, #4*8] + stp d6, d7, [x17, #6*8] + stp d8, d9, [x17, #8*8] + stp d10, d11, [x17, #10*8] + stp d12, d13, [x17, #12*8] + stp d14, d15, [x17, #14*8] + stp d16, d17, [x17, #16*8] + stp d18, d19, [x17, #18*8] + stp d20, d21, [x17, #20*8] + stp d22, d23, [x17, #22*8] + stp d24, d25, [x17, #24*8] + stp d26, d27, [x17, #26*8] + stp d28, d29, [x17, #28*8] + ;stp d30, d31, [x17, #30*8] + + b C_FUNC(_ZN13BailOutRecord7BailOutEPKS_) + +NESTED_END _ZN12LinearScanMD26SaveAllRegistersAndBailOutEP13BailOutRecord, _TEXT + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; LinearScanMD::SaveAllRegistersAndBranchBailOut(BranchBailOutRecord *const bailOutRecord, const BOOL condition) + +NESTED_ENTRY _ZN12LinearScanMD32SaveAllRegistersAndBranchBailOutEP19BranchBailOutRecordi, _TEXT, NoHandler + + ; x0 == bailOutRecord + ; x1 == condition + ; lr == return address + + ; Save all registers except the above, which would have already been saved by jitted code if necessary + ldr x17, [x0] ; bailOutRecord->globalBailOutRecordDataTable + ldr x17, [x17] ; bailOutRecord->globalBailOutRecordDataTable->registerSaveSpace + stp x2, x3, [x17, #2*8] + stp x4, x5, [x17, #4*8] + stp x6, x7, [x17, #6*8] + stp x8, x9, [x17, #8*8] + stp x10, x11, [x17, #10*8] + stp x12, x13, [x17, #12*8] + stp x14, x15, [x17, #14*8] + str x16, [x17, #16*8] + ; skip x17/x18 + stp x19, x20, [x17, #19*8] + stp x21, x22, [x17, #21*8] + stp x23, x24, [x17, #23*8] + stp x25, x26, [x17, #25*8] + stp x27, x28, [x17, #27*8] + str fp, [x17, #29*8] + ; skip lr, sp, zr + add x17, x17, #33*8 + stp d0, d1, [x17, #0*8] + stp d2, d3, [x17, #2*8] + stp d4, d5, [x17, #4*8] + stp d6, d7, [x17, #6*8] + stp d8, d9, [x17, #8*8] + stp d10, d11, [x17, #10*8] + stp d12, d13, [x17, #12*8] + stp d14, d15, [x17, #14*8] + stp d16, d17, [x17, #16*8] + stp d18, d19, [x17, #18*8] + stp d20, d21, [x17, #20*8] + stp d22, d23, [x17, #22*8] + stp d24, d25, [x17, #24*8] + stp d26, d27, [x17, #26*8] + stp d28, d29, [x17, #28*8] + ;stp d30, d31, [x17, #30*8] + + b C_FUNC(_ZN19BranchBailOutRecord7BailOutEPKS_i) + +NESTED_END _ZN12LinearScanMD32SaveAllRegistersAndBranchBailOutEP19BranchBailOutRecordi, _TEXT diff --git a/lib/Backend/arm64/LowerMD.h b/lib/Backend/arm64/LowerMD.h index 8a4ed209493..44822338795 100644 --- a/lib/Backend/arm64/LowerMD.h +++ b/lib/Backend/arm64/LowerMD.h @@ -1,5 +1,6 @@ //------------------------------------------------------------------------------------------------------- // Copyright (C) Microsoft Corporation and contributors. All rights reserved. +// Copyright (c) ChakraCore Project Contributors. All rights reserved. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. //------------------------------------------------------------------------------------------------------- #pragma once @@ -105,7 +106,7 @@ class LowererMD template void GenerateTruncWithCheck(IR::Instr * instr) { Assert(UNREACHED); } void GenerateFastDivByPow2(IR::Instr *instr); - bool GenerateFastDivAndRem(IR::Instr* instrDiv, IR::LabelInstr* bailOutLabel = false); + bool GenerateFastDivAndRem(IR::Instr* instrDiv, IR::LabelInstr* bailOutLabel = nullptr); bool GenerateFastAdd(IR::Instr * instrAdd); bool GenerateFastSub(IR::Instr * instrSub); bool GenerateFastMul(IR::Instr * instrMul); diff --git a/lib/Backend/arm64/Thunks.S b/lib/Backend/arm64/Thunks.S new file mode 100644 index 00000000000..dedc7c0cac4 --- /dev/null +++ b/lib/Backend/arm64/Thunks.S @@ -0,0 +1,46 @@ +;------------------------------------------------------------------------------------------------------- +; Copyright (C) Microsoft. All rights reserved. +; Copyright (c) ChakraCore Project Contributors. All rights reserved. +; Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. +;------------------------------------------------------------------------------------------------------- + +#include "unixasmmacros.inc" + +;;============================================================================================================ +; Fake __chkstk +;;============================================================================================================ +LEAF_ENTRY __chkstk, _TEXT + ret +LEAF_END __chkstk, _TEXT + +;;============================================================================================================ +; NativeCodeGenerator::CheckCodeGenThunk +;;============================================================================================================ + ;Js::Var NativeCodeGenerator::CheckCodeGenThunk(Js::RecyclableObject* function, Js::CallInfo callInfo, ...) +NESTED_ENTRY _ZN19NativeCodeGenerator17CheckCodeGenThunkEPN2Js16RecyclableObjectENS0_8CallInfoEz, _TEXT, NoHandler + + PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, -(16+16*8) ; establish stack frame + stp d0, d1, [sp, #16+0*8] + stp d2, d3, [sp, #16+2*8] + stp d4, d5, [sp, #16+4*8] + stp d6, d7, [sp, #16+6*8] + stp x0, x1, [sp, #16+8*8] + stp x2, x3, [sp, #16+10*8] + stp x4, x5, [sp, #16+12*8] + stp x6, x7, [sp, #16+14*8] + + bl C_FUNC(_ZN19NativeCodeGenerator12CheckCodeGenEPN2Js14ScriptFunctionE) ; call NativeCodeGenerator::CheckCodeGen + mov x15, x0 ; move entry point to x15 + + ldp d0, d1, [sp, #16+0*8] + ldp d2, d3, [sp, #16+2*8] + ldp d4, d5, [sp, #16+4*8] + ldp d6, d7, [sp, #16+6*8] + ldp x0, x1, [sp, #16+8*8] + ldp x2, x3, [sp, #16+10*8] + ldp x4, x5, [sp, #16+12*8] + ldp x6, x7, [sp, #16+14*8] + EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, (16+16*8) + br x15 ; jump (tail call) to new entryPoint + +NESTED_END _ZN19NativeCodeGenerator17CheckCodeGenThunkEPN2Js16RecyclableObjectENS0_8CallInfoEz, _TEXT