From 469a324391dc49f92a411c5169145606fd50659b Mon Sep 17 00:00:00 2001 From: Kyungwoo Lee Date: Mon, 14 Mar 2016 11:06:11 -0700 Subject: [PATCH] ARM64: Fix GC hole in indirect call site This fixes dotnet#3663. Indirect call (```br``` or ```blr```) target is encoded with a register which the first operand internally represents. Unfortunately, call sites use the first two operands to hold GC callee-save registers. So, this GC register information was overridden by the call target operand in the indirect(virtual) call sites. The fix is to use 3rd/4th operands instead of 1st/2nd operands to hold GC info. Ideally we should use different field name and also ensure constness when we set up the operand so that it's never written more than once. https://github.com/dotnet/coreclr/issues/3693 is filed. --- src/jit/emit.cpp | 4 ++-- src/jit/emit.h | 2 +- src/jit/emitinl.h | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/jit/emit.cpp b/src/jit/emit.cpp index 539d6e4..b9787fa 100644 --- a/src/jit/emit.cpp +++ b/src/jit/emit.cpp @@ -3056,7 +3056,7 @@ emitter::instrDesc * emitter::emitNewInstrCallInd(int id->idAddr()->iiaAddrMode.amDisp = disp; assert(id->idAddr()->iiaAddrMode.amDisp == disp); - /* Save the the live GC registers in the unused 'idReg/idRg2' fields */ + /* Save the the live GC registers in the unused register fields */ emitEncodeCallGCregs(gcrefRegs, id); return id; @@ -3128,7 +3128,7 @@ emitter::instrDesc *emitter::emitNewInstrCallDir(int /* Make sure we didn't waste space unexpectedly */ assert(!id->idIsLargeCns()); - /* Save the the live GC registers in the unused 'idReg/idRg2' fields */ + /* Save the the live GC registers in the unused register fields */ emitEncodeCallGCregs(gcrefRegs, id); return id; diff --git a/src/jit/emit.h b/src/jit/emit.h index c03e902..c355322 100644 --- a/src/jit/emit.h +++ b/src/jit/emit.h @@ -943,7 +943,7 @@ protected: } // Note that we use the _idReg3 and _idReg4 fields to hold - // the live gcrefReg mask for the call instructions on arm + // the live gcrefReg mask for the call instructions on arm64 // struct { diff --git a/src/jit/emitinl.h b/src/jit/emitinl.h index 7bbbf06..bb561fe 100644 --- a/src/jit/emitinl.h +++ b/src/jit/emitinl.h @@ -332,7 +332,7 @@ ssize_t emitter::emitGetInsAmdAny(instrDesc *id) if ((regmask & RBM_R23) != RBM_NONE) encodeMask |= 0x10; - id->idReg1((regNumber)encodeMask); // Save in idReg1 + id->idReg3((regNumber)encodeMask); // Save in idReg3 encodeMask = 0; @@ -347,7 +347,7 @@ ssize_t emitter::emitGetInsAmdAny(instrDesc *id) if ((regmask & RBM_R28) != RBM_NONE) encodeMask |= 0x10; - id->idReg2((regNumber)encodeMask); // Save in idReg2 + id->idReg4((regNumber)encodeMask); // Save in idReg4 #else NYI("unknown target"); @@ -419,7 +419,7 @@ ssize_t emitter::emitGetInsAmdAny(instrDesc *id) #elif defined(_TARGET_ARM64_) assert(REGNUM_BITS >= 5); - encodeMask = id->idReg1(); + encodeMask = id->idReg3(); if ((encodeMask & 0x01) != 0) regmask |= RBM_R19; @@ -432,7 +432,7 @@ ssize_t emitter::emitGetInsAmdAny(instrDesc *id) if ((encodeMask & 0x10) != 0) regmask |= RBM_R23; - encodeMask = id->idReg2(); + encodeMask = id->idReg4(); if ((encodeMask & 0x01) != 0) regmask |= RBM_R24; -- 2.7.4