diff options
author | Kyungwoo Lee <kyulee@microsoft.com> | 2016-04-29 10:29:28 -0700 |
---|---|---|
committer | Kyungwoo Lee <kyulee@microsoft.com> | 2016-04-29 14:52:46 -0700 |
commit | 45798f661f8c8c042f3582cde8b611d1c9c7343f (patch) | |
tree | 0d75dad9935f95c5bf4bd309899a37456e4478bd | |
parent | 601b1051c1022d5f764224e35be59f02a6074ad0 (diff) | |
download | coreclr-45798f661f8c8c042f3582cde8b611d1c9c7343f.tar.gz coreclr-45798f661f8c8c042f3582cde8b611d1c9c7343f.tar.bz2 coreclr-45798f661f8c8c042f3582cde8b611d1c9c7343f.zip |
ARM64: Enabling Crossgen End-to-End Mscorlib
Fixes https://github.com/dotnet/coreclr/issues/4350
Fixes https://github.com/dotnet/coreclr/issues/4615
This is a bit large change across VM/Zap/JIT to properly support crossgen
scenario.
1. Fix incorrect `ldr` encoding with size.
2. Enforce JIT data following JIT code per method by allocating them together.
This guarantees correct PC-relative encoding for such constant data access
without fix-up.
3. For the general fix-up data acceess, use `adrp/add` instruction pairs with fix-ups.
Two more relocations types are implemented in all sides.
4. Interface dispatch stub is now implemented which is needed for
interface call for crossgen.
I've verified hello world runs with mscorlib.ni.dll.
-rw-r--r-- | src/inc/clrnt.h | 8 | ||||
-rw-r--r-- | src/inc/utilcode.h | 36 | ||||
-rw-r--r-- | src/jit/codegenarm64.cpp | 9 | ||||
-rw-r--r-- | src/jit/emit.cpp | 20 | ||||
-rw-r--r-- | src/jit/emit.h | 1 | ||||
-rw-r--r-- | src/jit/emitarm64.cpp | 120 | ||||
-rw-r--r-- | src/jit/emitfmtsarm64.h | 2 | ||||
-rw-r--r-- | src/jit/instrsarm64.h | 2 | ||||
-rw-r--r-- | src/utilcode/util.cpp | 81 | ||||
-rw-r--r-- | src/vm/arm64/asmhelpers.asm | 25 | ||||
-rw-r--r-- | src/vm/arm64/stubs.cpp | 7 | ||||
-rw-r--r-- | src/vm/jitinterface.cpp | 26 | ||||
-rw-r--r-- | src/zap/zapinfo.cpp | 13 | ||||
-rw-r--r-- | src/zap/zaprelocs.cpp | 27 |
14 files changed, 340 insertions, 37 deletions
diff --git a/src/inc/clrnt.h b/src/inc/clrnt.h index 9adae3770f..c15bd48fa8 100644 --- a/src/inc/clrnt.h +++ b/src/inc/clrnt.h @@ -985,6 +985,14 @@ RtlVirtualUnwind( #define IMAGE_REL_ARM64_BRANCH26 0x0003 // 26 bit offset << 2 & sign ext. for B & BL #endif +#ifndef IMAGE_REL_ARM64_PAGEBASE_REL21 +#define IMAGE_REL_ARM64_PAGEBASE_REL21 0x0004 // ADRP 21 bit PC-relative page address +#endif + +#ifndef IMAGE_REL_ARM64_PAGEOFFSET_12A +#define IMAGE_REL_ARM64_PAGEOFFSET_12A 0x0006 // ADD 12 bit page offset +#endif + #endif #endif // CLRNT_H_ diff --git a/src/inc/utilcode.h b/src/inc/utilcode.h index bb7c8bad81..fc3af0ecd5 100644 --- a/src/inc/utilcode.h +++ b/src/inc/utilcode.h @@ -4526,11 +4526,31 @@ void PutThumb2BlRel24(UINT16 * p, INT32 imm24); INT32 GetArm64Rel28(UINT32 * pCode); //***************************************************************************** +// Extract the PC-Relative page address from an adrp instruction +//***************************************************************************** +INT32 GetArm64Rel21(UINT32 * pCode); + +//***************************************************************************** +// Extract the page offset from an add instruction +//***************************************************************************** +INT32 GetArm64Rel12(UINT32 * pCode); + +//***************************************************************************** // Deposit the PC-Relative offset 'imm28' into a b or bl instruction //***************************************************************************** void PutArm64Rel28(UINT32 * pCode, INT32 imm28); //***************************************************************************** +// Deposit the PC-Relative page address 'imm21' into an adrp instruction +//***************************************************************************** +void PutArm64Rel21(UINT32 * pCode, INT32 imm21); + +//***************************************************************************** +// Deposit the page offset 'imm12' into an add instruction +//***************************************************************************** +void PutArm64Rel12(UINT32 * pCode, INT32 imm12); + +//***************************************************************************** // Returns whether the offset fits into bl instruction //***************************************************************************** inline bool FitsInThumb2BlRel24(INT32 imm24) @@ -4547,6 +4567,22 @@ inline bool FitsInRel28(INT32 val32) } //***************************************************************************** +// Returns whether the offset fits into an Arm64 adrp instruction +//***************************************************************************** +inline bool FitsInRel21(INT32 val32) +{ + return (val32 >= 0) && (val32 <= 0x001FFFFF); +} + +//***************************************************************************** +// Returns whether the offset fits into an Arm64 add instruction +//***************************************************************************** +inline bool FitsInRel12(INT32 val32) +{ + return (val32 >= 0) && (val32 <= 0x00000FFF); +} + +//***************************************************************************** // Returns whether the offset fits into an Arm64 b or bl instruction //***************************************************************************** inline bool FitsInRel28(INT64 val64) diff --git a/src/jit/codegenarm64.cpp b/src/jit/codegenarm64.cpp index 7b1b2fa92b..bbc46db678 100644 --- a/src/jit/codegenarm64.cpp +++ b/src/jit/codegenarm64.cpp @@ -2157,12 +2157,11 @@ void CodeGen::instGen_Set_Reg_To_Imm(emitAttr size, { size = EA_SIZE(size); // Strip any Reloc flags from size if we aren't doing relocs } - + if (EA_IS_RELOC(size)) { - // Emit a data section constant for a relocatable integer constant. - CORINFO_FIELD_HANDLE hnd = getEmitter()->emitLiteralConst(imm); - getEmitter()->emitIns_R_C(INS_ldr, size, reg, hnd, 0); + // This emits a pair of adrp/add (two instructions) with fix-ups. + getEmitter()->emitIns_R_AI(INS_adrp, size, reg, imm); } else if (imm == 0) { @@ -2252,7 +2251,7 @@ void CodeGen::genSetRegToConst(regNumber targetReg, var_types tar // We must load the FP constant from the constant pool // Emit a data section constant for the float or double constant. CORINFO_FIELD_HANDLE hnd = emit->emitFltOrDblConst(dblConst); - emit->emitIns_R_C(INS_ldr, size, targetReg, hnd, 0); + emit->emitIns_R_C(INS_ldr, size, targetReg, hnd, 0); } } break; diff --git a/src/jit/emit.cpp b/src/jit/emit.cpp index b9787fa7d6..a4a20693a4 100644 --- a/src/jit/emit.cpp +++ b/src/jit/emit.cpp @@ -4497,12 +4497,32 @@ unsigned emitter::emitEndCodeGen(Compiler *comp, } #endif +#ifdef _TARGET_ARM64_ + // For arm64, we want to allocate JIT data always adjacent to code similar to what native compiler does. + // This way allows us to use a single `ldr` to access such data like float constant/jmp table. + if (emitTotalColdCodeSize > 0) + { + // JIT data might be far away from the cold code. + NYI_ARM64("Need to handle fix-up to data from cold code."); + } + + emitCmpHandle->allocMem(emitTotalHotCodeSize + emitConsDsc.dsdOffs, emitTotalColdCodeSize, + 0, + xcptnsCount, + allocMemFlag, + (void**)&codeBlock, (void**)&coldCodeBlock, + (void**)&consBlock); + + consBlock = codeBlock + emitTotalHotCodeSize; + +#else emitCmpHandle->allocMem( emitTotalHotCodeSize, emitTotalColdCodeSize, emitConsDsc.dsdOffs, xcptnsCount, allocMemFlag, (void**)&codeBlock, (void**)&coldCodeBlock, (void**)&consBlock); +#endif // if (emitConsDsc.dsdOffs) printf("Cons=%08X\n", consBlock); diff --git a/src/jit/emit.h b/src/jit/emit.h index 95dac33536..67adcdf731 100644 --- a/src/jit/emit.h +++ b/src/jit/emit.h @@ -1131,6 +1131,7 @@ protected: bool idIsDspReloc() const { assert(!idIsTiny()); return _idDspReloc != 0; } void idSetIsDspReloc(bool val = true) { assert(!idIsTiny()); _idDspReloc = val; } + bool idIsReloc() { return idIsDspReloc() || idIsCnsReloc(); } #endif diff --git a/src/jit/emitarm64.cpp b/src/jit/emitarm64.cpp index e4ad5c77b8..2a0bf954b6 100644 --- a/src/jit/emitarm64.cpp +++ b/src/jit/emitarm64.cpp @@ -814,7 +814,7 @@ bool emitter::emitInsMayWriteToGCReg(instrDesc *id) // These are the load/store formats with "target" registers: - case IF_LS_1A: // LS_1A .X......iiiiiiii iiiiiiiiiiittttt Rt PC imm(1MB) + case IF_LS_1A: // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt PC imm(1MB) case IF_LS_2A: // LS_2A .X.......X...... ......nnnnnttttt Rt Rn case IF_LS_2B: // LS_2B .X.......Xiiiiii iiiiiinnnnnttttt Rt Rn imm(0-4095) case IF_LS_2C: // LS_2C .X.......X.iiiii iiiiP.nnnnnttttt Rt Rn imm(-256..+255) pre/post inc @@ -6314,6 +6314,9 @@ void emitter::emitIns_S_I (instruction ins, /***************************************************************************** * * Add an instruction with a register + static member operands. + * Constant is stored into JIT data which is adjacent to code. + * No relocation is needed. PC-relative offset will be encoded directly into instruction. + * */ void emitter::emitIns_R_C (instruction ins, emitAttr attr, @@ -6321,11 +6324,6 @@ void emitter::emitIns_R_C (instruction ins, CORINFO_FIELD_HANDLE fldHnd, int offs) { -#if RELOC_SUPPORT - // Static always need relocs - if (!jitStaticFldIsGlobAddr(fldHnd)) - attr = EA_SET_FLG(attr, EA_DSP_RELOC_FLG); -#endif assert(offs >= 0); assert(instrDesc::fitsInSmallCns(offs)); @@ -6350,7 +6348,6 @@ void emitter::emitIns_R_C (instruction ins, } fmt = IF_LS_1A; break; - default: break; } @@ -6369,7 +6366,6 @@ void emitter::emitIns_R_C (instruction ins, dispIns(id); appendToCurIG(id); - } @@ -6413,12 +6409,61 @@ void emitter::emitIns_R_AR (instruction ins, NYI("emitIns_R_AR"); } -void emitter::emitIns_R_AI (instruction ins, - emitAttr attr, - regNumber ireg, - ssize_t disp) +// This computes address from the immediate which is relocatable. +void emitter::emitIns_R_AI(instruction ins, + emitAttr attr, + regNumber ireg, + ssize_t addr) { - NYI("emitIns_R_AI"); + assert(EA_IS_RELOC(attr)); + emitAttr size = EA_SIZE(attr); + insFormat fmt = IF_DI_1E; + bool needAdd = false; + instrDescJmp* id = emitNewInstrJmp(); + + switch (ins) + { + case INS_adrp: + // This computes page address. + // page offset is needed using add. + needAdd = true; + break; + case INS_adr: + break; + default: + unreached(); + } + + id->idIns(ins); + id->idInsFmt(fmt); + id->idInsOpt(INS_OPTS_NONE); + id->idOpSize(size); + id->idAddr()->iiaAddr = (BYTE*)addr; + id->idReg1(ireg); + id->idSetIsDspReloc(); + + dispIns(id); + appendToCurIG(id); + + if (needAdd) + { + // add reg, reg, imm + ins = INS_add; + fmt = IF_DI_2A; + instrDesc* id = emitAllocInstr(attr); + assert(id->idIsReloc()); + + id->idIns(ins); + id->idInsFmt(fmt); + id->idInsOpt(INS_OPTS_NONE); + id->idOpSize(size); + id->idAddr()->iiaAddr = (BYTE*)addr; + id->idReg1(ireg); + id->idReg2(ireg); + + dispIns(id); + appendToCurIG(id); + } } void emitter::emitIns_AR_R (instruction ins, @@ -7849,6 +7894,12 @@ BYTE* emitter::emitOutputLJ(insGroup *ig, BYTE *dst, instrDesc *i dstAddr = emitDataOffsetToPtr(dataOffs); dstOffs = (unsigned) ((ssize_t) (dstAddr - srcAddr) + srcOffs); assert((dstOffs & 3) == 0); + + // Failing the following assertion means the corresponding JIT data is not within +/-1MB range + // from the current code reference. This could happen for a large method or extremely large + // amount of JIT data for the method, or access it from cold method. + // Ideally, we should detect such case earlier to expand the code sequence using a fix-up + // similar to emitIns_R_AI. assert(isValidSimm19(dstOffs)); } else @@ -7991,19 +8042,27 @@ BYTE* emitter::emitOutputLJ(insGroup *ig, BYTE *dst, instrDesc *i } else if (loadLabel) { - if (fmt == IF_LS_1A) // LS_1A XX......iiiiiiii iiiiiiiiiiittttt Rt simm21 + if (fmt == IF_LS_1A) // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt simm21 { // INS_ldr or INS_ldrsw (PC-Relative) // Is the target a vector register? if (isVectorRegister(id->idReg1())) - { - code &= 0x3FFFFFFF; // clear the size bits - code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX + { + code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX V code |= insEncodeReg_Vt(id->idReg1()); // ttttt } else { + assert(isGeneralRegister(id->idReg1())); + // insEncodeDatasizeLS is not quite right for this case. + // So just specialize it. + if ((ins == INS_ldr) && (id->idOpSize() == EA_8BYTE)) + { + // set the operation size in bit 30 + code |= 0x40000000; + } + code |= insEncodeReg_Rt(id->idReg1()); // ttttt } @@ -8235,7 +8294,7 @@ size_t emitter::emitOutputInstr(insGroup *ig, dst += emitOutputCall(ig, dst, id, code); break; - case IF_LS_1A: // LS_1A XX......iiiiiiii iiiiiiiiiiittttt Rt PC imm(1MB) + case IF_LS_1A: // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt PC imm(1MB) assert(insOptsNone(id->idInsOpt())); assert(id->idIsBound()); @@ -8428,9 +8487,19 @@ size_t emitter::emitOutputInstr(insGroup *ig, case IF_DI_1E: // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21 assert(insOptsNone(id->idInsOpt())); - assert(id->idIsBound()); - - dst = emitOutputLJ(ig, dst, id); + if (id->idIsReloc()) + { + code = emitInsCode(ins, fmt); + code |= insEncodeReg_Rd(id->idReg1()); // ddddd + dst += emitOutput_Instr(dst, code); + emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_PAGEBASE_REL21); + } + else + { + // Local jmp/load case which does not need a relocation. + assert(id->idIsBound()); + dst = emitOutputLJ(ig, dst, id); + } sz = sizeof(instrDescJmp); break; @@ -8461,6 +8530,13 @@ size_t emitter::emitOutputInstr(insGroup *ig, code |= insEncodeReg_Rd(id->idReg1()); // ddddd code |= insEncodeReg_Rn(id->idReg2()); // nnnnn dst += emitOutput_Instr(dst, code); + + if (id->idIsReloc()) + { + assert(sz == sizeof(instrDesc)); + assert(id->idAddr()->iiaAddr != nullptr); + emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_PAGEOFFSET_12A); + } break; case IF_DI_2B: // DI_2B X.........Xnnnnn ssssssnnnnnddddd Rd Rn imm(0-63) @@ -9920,7 +9996,7 @@ void emitter::emitDispIns(instrDesc * id, emitDispReg(id->idReg3(), size, false); break; - case IF_LS_1A: // LS_1A XX......iiiiiiii iiiiiiiiiiittttt Rt PC imm(1MB) + case IF_LS_1A: // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt PC imm(1MB) assert(insOptsNone(id->idInsOpt())); emitDispReg(id->idReg1(), size, true); imm = emitGetInsSC(id); diff --git a/src/jit/emitfmtsarm64.h b/src/jit/emitfmtsarm64.h index 722e48c580..06cde03f8c 100644 --- a/src/jit/emitfmtsarm64.h +++ b/src/jit/emitfmtsarm64.h @@ -121,7 +121,7 @@ IF_DEF(BI_1B, IS_NONE, JMP) // BI_1B B.......bbbbbiii IF_DEF(BR_1A, IS_NONE, CALL) // BR_1A ................ ......nnnnn..... Rn ret IF_DEF(BR_1B, IS_NONE, CALL) // BR_1B ................ ......nnnnn..... Rn br blr -IF_DEF(LS_1A, IS_NONE, JMP) // LS_1A .X......iiiiiiii iiiiiiiiiiittttt Rt PC imm(1MB) +IF_DEF(LS_1A, IS_NONE, JMP) // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt PC imm(1MB) IF_DEF(LS_2A, IS_NONE, NONE) // LS_2A .X.......X...... ......nnnnnttttt Rt Rn IF_DEF(LS_2B, IS_NONE, NONE) // LS_2B .X.......Xiiiiii iiiiiinnnnnttttt Rt Rn imm(0-4095) IF_DEF(LS_2C, IS_NONE, NONE) // LS_2C .X.......X.iiiii iiiiP.nnnnnttttt Rt Rn imm(-256..+255) pre/post inc diff --git a/src/jit/instrsarm64.h b/src/jit/instrsarm64.h index 21fddc5fe7..51ec30e0db 100644 --- a/src/jit/instrsarm64.h +++ b/src/jit/instrsarm64.h @@ -91,7 +91,7 @@ INST5(ldr, "ldr", 0,LD, IF_EN5A, 0xB9400000, 0xB9400000, 0xB8400000, // ldr Rt,[Xn+pimm12] LS_2B 1X11100101iiiiii iiiiiinnnnnttttt B940 0000 imm(0-4095<<{2,3}) // ldr Rt,[Xn+simm9] LS_2C 1X111000010iiiii iiiiPPnnnnnttttt B840 0000 [Xn imm(-256..+255) pre/post/no inc] // ldr Rt,[Xn,(Rm,ext,shl)] LS_3A 1X111000011mmmmm oooS10nnnnnttttt B860 0800 [Xn, ext(Rm) LSL {0,2,3}] - // ldr Vt/Rt,[PC+simm19<<2] LS_1A XX011000iiiiiiii iiiiiiiiiiittttt 1800 0000 [PC +- imm(1MB)] + // ldr Vt/Rt,[PC+simm19<<2] LS_1A XX011V00iiiiiiii iiiiiiiiiiittttt 1800 0000 [PC +- imm(1MB)] INST5(ldrsw, "ldrsw", 0,LD, IF_EN5A, 0xB9800000, 0xB9800000, 0xB8800000, 0xB8A00800, 0x98000000) // ldrsw Rt,[Xn] LS_2A 1011100110000000 000000nnnnnttttt B980 0000 diff --git a/src/utilcode/util.cpp b/src/utilcode/util.cpp index f801f94b60..50643d4a7e 100644 --- a/src/utilcode/util.cpp +++ b/src/utilcode/util.cpp @@ -2684,6 +2684,41 @@ INT32 GetArm64Rel28(UINT32 * pCode) } //***************************************************************************** +// Extract the PC-Relative offset from an adrp instruction +//***************************************************************************** +INT32 GetArm64Rel21(UINT32 * pCode) +{ + LIMITED_METHOD_CONTRACT; + + UINT32 addInstr = *pCode; + + // 23-5 bits for the high part. Shift it by 5. + INT32 immhi = (((INT32)(addInstr & 0xFFFFE0))) >> 5; + // 30,29 bits for the lower part. Shift it by 29. + INT32 immlo = ((INT32)(addInstr & 0x60000000)) >> 29; + + // Merge them + INT32 imm21 = (immhi << 2) | immlo; + + return imm21; +} + +//***************************************************************************** +// Extract the PC-Relative offset from an add instruction +//***************************************************************************** +INT32 GetArm64Rel12(UINT32 * pCode) +{ + LIMITED_METHOD_CONTRACT; + + UINT32 addInstr = *pCode; + + // 21-10 contains value. Mask 12 bits and shift by 10 bits. + INT32 imm12 = (INT32)(addInstr & 0x003FFC00) >> 10; + + return imm12; +} + +//***************************************************************************** // Deposit the PC-Relative offset 'imm28' into a b or bl instruction //***************************************************************************** void PutArm64Rel28(UINT32 * pCode, INT32 imm28) @@ -2706,6 +2741,52 @@ void PutArm64Rel28(UINT32 * pCode, INT32 imm28) _ASSERTE(GetArm64Rel28(pCode) == imm28); } +//***************************************************************************** +// Deposit the PC-Relative offset 'imm21' into an adrp instruction +//***************************************************************************** +void PutArm64Rel21(UINT32 * pCode, INT32 imm21) +{ + LIMITED_METHOD_CONTRACT; + + // Verify that we got a valid offset + _ASSERTE(FitsInRel21(imm21)); + + UINT32 adrpInstr = *pCode; + // Check adrp opcode 1ii1 0000 ... + _ASSERTE((adrpInstr & 0x9F000000) == 0x90000000); + + adrpInstr &= 0x9F00001F; // keep bits 31, 28-24, 4-0. + INT32 immlo = imm21 & 0x03; // Extract low 2 bits which will occupy 30-29 bits. + INT32 immhi = (imm21 & 0x1FFFFC) >> 2; // Extract high 19 bits which will occupy 23-5 bits. + adrpInstr |= ((immlo << 29) | (immhi << 5)); + + *pCode = adrpInstr; // write the assembled instruction + + _ASSERTE(GetArm64Rel21(pCode) == imm21); +} + +//***************************************************************************** +// Deposit the PC-Relative offset 'imm12' into an add instruction +//***************************************************************************** +void PutArm64Rel12(UINT32 * pCode, INT32 imm12) +{ + LIMITED_METHOD_CONTRACT; + + // Verify that we got a valid offset + _ASSERTE(FitsInRel12(imm12)); + + UINT32 addInstr = *pCode; + // Check add opcode 1001 0001 00... + _ASSERTE((addInstr & 0xFFC00000) == 0x91000000); + + addInstr &= 0xFFC003FF; // keep bits 31-22, 9-0 + addInstr |= (imm12 << 10); // Occupy 21-10. + + *pCode = addInstr; // write the assembled instruction + + _ASSERTE(GetArm64Rel12(pCode) == imm12); +} + //--------------------------------------------------------------------- // Splits a command line into argc/argv lists, using the VC7 parsing rules. // diff --git a/src/vm/arm64/asmhelpers.asm b/src/vm/arm64/asmhelpers.asm index 7c89f0f897..8bf4da6710 100644 --- a/src/vm/arm64/asmhelpers.asm +++ b/src/vm/arm64/asmhelpers.asm @@ -16,6 +16,7 @@ IMPORT PreStubWorker IMPORT NDirectImportWorker IMPORT VSD_ResolveWorker + IMPORT StubDispatchFixupWorker IMPORT JIT_InternalThrow IMPORT ComPreStubWorker IMPORT COMToCLRWorker @@ -1175,7 +1176,6 @@ Fail NESTED_END - #ifdef FEATURE_READYTORUN NESTED_ENTRY DelayLoad_MethodCall @@ -1221,5 +1221,28 @@ Fail DynamicHelper DynamicHelperFrameFlags_ObjectArg | DynamicHelperFrameFlags_ObjectArg2, _ObjObj #endif // FEATURE_READYTORUN +#ifdef FEATURE_PREJIT +;; ------------------------------------------------------------------ +;; void StubDispatchFixupStub(args in regs x0-x7 & stack, x11:IndirectionCellAndFlags, x12:DispatchToken) +;; +;; The stub dispatch thunk which transfers control to StubDispatchFixupWorker. + NESTED_ENTRY StubDispatchFixupStub + + PROLOG_WITH_TRANSITION_BLOCK + + add x0, sp, #__PWTB_TransitionBlock ; pTransitionBlock + and x1, x11, #-4 ; Indirection cell + mov x2, #0 ; sectionIndex + mov x3, #0 ; pModule + bl StubDispatchFixupWorker + mov x9, x0 + + EPILOG_WITH_TRANSITION_BLOCK_TAILCALL + + EPILOG_BRANCH_REG x9 + + NESTED_END +#endif + ; Must be at very end of file END
\ No newline at end of file diff --git a/src/vm/arm64/stubs.cpp b/src/vm/arm64/stubs.cpp index c50fdca7f7..e1b8768e83 100644 --- a/src/vm/arm64/stubs.cpp +++ b/src/vm/arm64/stubs.cpp @@ -1046,13 +1046,6 @@ extern "C" void GenericComPlusCallStub(void) } #endif // FEATURE_COMINTEROP -#ifdef FEATURE_PREJIT -extern "C" void StubDispatchFixupStub() -{ - _ASSERTE(!"ARM64:NYI"); -} -#endif - //ARM64TODO: check if this should be amd64 and win64 #ifdef _WIN64 extern "C" void PInvokeStubForHostInner(DWORD dwStackSize, LPVOID pStackFrame, LPVOID pTarget) diff --git a/src/vm/jitinterface.cpp b/src/vm/jitinterface.cpp index cf0e456140..7b7c0713f5 100644 --- a/src/vm/jitinterface.cpp +++ b/src/vm/jitinterface.cpp @@ -10762,6 +10762,32 @@ void CEEJitInfo::recordRelocation(void * location, PutArm64Rel28((UINT32*) fixupLocation, (INT32)delta); } break; + + case IMAGE_REL_ARM64_PAGEBASE_REL21: + { + _ASSERTE(slot == 0); + _ASSERTE(addlDelta == 0); + + // Write the 21 bits pc-relative page address into location. + INT64 targetPage = (INT64)target & 0xFFFFFFFFFFFFF000LL; + INT64 lcoationPage = (INT64)location & 0xFFFFFFFFFFFFF000LL; + INT64 relPage = (INT64)(targetPage - lcoationPage); + INT32 imm21 = (INT32)(relPage >> 12) & 0x1FFFFF; + PutArm64Rel21((UINT32 *)location, imm21); + } + break; + + case IMAGE_REL_ARM64_PAGEOFFSET_12A: + { + _ASSERTE(slot == 0); + _ASSERTE(addlDelta == 0); + + // Write the 12 bits page offset into location. + INT32 imm12 = (INT32)target & 0xFFFLL; + PutArm64Rel12((UINT32 *)location, imm12); + } + break; + #endif // _TARGET_ARM64_ default: diff --git a/src/zap/zapinfo.cpp b/src/zap/zapinfo.cpp index 345a920902..2e0ddb569a 100644 --- a/src/zap/zapinfo.cpp +++ b/src/zap/zapinfo.cpp @@ -2469,6 +2469,8 @@ void ZapInfo::recordRelocation(void *location, void *target, #if defined(_TARGET_ARM64_) case IMAGE_REL_ARM64_BRANCH26: + case IMAGE_REL_ARM64_PAGEBASE_REL21: + case IMAGE_REL_ARM64_PAGEOFFSET_12A: break; #endif @@ -2583,6 +2585,17 @@ void ZapInfo::recordRelocation(void *location, void *target, ThrowHR(COR_E_OVERFLOW); PutArm64Rel28((UINT32 *)location, targetOffset); break; + case IMAGE_REL_ARM64_PAGEBASE_REL21: + if (!FitsInRel21(targetOffset)) + ThrowHR(COR_E_OVERFLOW); + PutArm64Rel21((UINT32 *)location, targetOffset); + break; + + case IMAGE_REL_ARM64_PAGEOFFSET_12A: + if (!FitsInRel12(targetOffset)) + ThrowHR(COR_E_OVERFLOW); + PutArm64Rel12((UINT32 *)location, targetOffset); + break; #endif default: diff --git a/src/zap/zaprelocs.cpp b/src/zap/zaprelocs.cpp index dd21b09632..04708c2adb 100644 --- a/src/zap/zaprelocs.cpp +++ b/src/zap/zaprelocs.cpp @@ -120,6 +120,24 @@ void ZapBaseRelocs::WriteReloc(PVOID pSrc, int offset, ZapNode * pTarget, int ta PutArm64Rel28((UINT32 *)pLocation,relOffset); } return; + + case IMAGE_REL_ARM64_PAGEBASE_REL21: + { + TADDR pSitePage = ((TADDR)m_pImage->GetBaseAddress() + rva) & 0xFFFFFFFFFFFFF000LL; + TADDR pActualTargetPage = pActualTarget & 0xFFFFFFFFFFFFF000LL; + + INT64 relPage = (INT64)(pActualTargetPage - pSitePage); + INT32 imm21 = (INT32)(relPage >> 12) & 0x1FFFFF; + PutArm64Rel21((UINT32 *)pLocation, imm21); + } + return; + + case IMAGE_REL_ARM64_PAGEOFFSET_12A: + { + INT32 imm12 = (INT32)(pActualTarget & 0xFFFLL); + PutArm64Rel12((UINT32 *)pLocation, imm12); + } + return; #endif default: @@ -276,6 +294,15 @@ void ZapBlobWithRelocs::Save(ZapWriter * pZapWriter) case IMAGE_REL_ARM64_BRANCH26: targetOffset = (int)GetArm64Rel28((UINT32*)pLocation); break; + + case IMAGE_REL_ARM64_PAGEBASE_REL21: + targetOffset = (int)GetArm64Rel21((UINT32*)pLocation); + break; + + case IMAGE_REL_ARM64_PAGEOFFSET_12A: + targetOffset = (int)GetArm64Rel12((UINT32*)pLocation); + break; + #endif // defined(_TARGET_ARM64_) default: |