Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit c71c92a

Browse files
Merge pull request #23220 from BruceForstall/FixArm64HfaJmpCallNyi
Arm64: Implement JMP call for HFA register arguments
2 parents e73c7bc + c08f182 commit c71c92a

File tree

4 files changed

+1116
-31
lines changed

4 files changed

+1116
-31
lines changed

src/jit/codegenarmarch.cpp

Lines changed: 53 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2675,54 +2675,76 @@ void CodeGen::genJmpMethod(GenTree* jmp)
26752675
if (varDsc->lvRegNum != argReg)
26762676
{
26772677
var_types loadType = TYP_UNDEF;
2678-
if (varTypeIsStruct(varDsc))
2679-
{
2680-
// Must be <= 16 bytes or else it wouldn't be passed in registers
2681-
noway_assert(EA_SIZE_IN_BYTES(varDsc->lvSize()) <= MAX_PASS_MULTIREG_BYTES);
2682-
loadType = compiler->getJitGCType(varDsc->lvGcLayout[0]);
2683-
}
2684-
else
2678+
2679+
if (varDsc->lvIsHfaRegArg())
26852680
{
2686-
loadType = compiler->mangleVarArgsType(genActualType(varDsc->TypeGet()));
2687-
}
2688-
emitAttr loadSize = emitActualTypeSize(loadType);
2689-
getEmitter()->emitIns_R_S(ins_Load(loadType), loadSize, argReg, varNum, 0);
2681+
// Note that for HFA, the argument is currently marked address exposed so lvRegNum will always be
2682+
// REG_STK. We home the incoming HFA argument registers in the prolog. Then we'll load them back
2683+
// here, whether they are already in the correct registers or not. This is such a corner case that
2684+
// it is not worth optimizing it.
26902685

2691-
// Update argReg life and GC Info to indicate varDsc stack slot is dead and argReg is going live.
2692-
// Note that we cannot modify varDsc->lvRegNum here because another basic block may not be expecting it.
2693-
// Therefore manually update life of argReg. Note that GT_JMP marks the end of the basic block
2694-
// and after which reg life and gc info will be recomputed for the new block in genCodeForBBList().
2695-
regSet.AddMaskVars(genRegMask(argReg));
2696-
gcInfo.gcMarkRegPtrVal(argReg, loadType);
2686+
assert(!compiler->info.compIsVarArgs);
26972687

2698-
if (compiler->lvaIsMultiregStruct(varDsc, compiler->info.compIsVarArgs))
2688+
loadType = varDsc->GetHfaType();
2689+
regNumber fieldReg = argReg;
2690+
emitAttr loadSize = emitActualTypeSize(loadType);
2691+
unsigned cSlots = varDsc->lvHfaSlots();
2692+
2693+
for (unsigned ofs = 0, cSlot = 0; cSlot < cSlots; cSlot++, ofs += (unsigned)loadSize)
2694+
{
2695+
getEmitter()->emitIns_R_S(ins_Load(loadType), loadSize, fieldReg, varNum, ofs);
2696+
assert(genIsValidFloatReg(fieldReg)); // No GC register tracking for floating point registers.
2697+
fieldReg = regNextOfType(fieldReg, loadType);
2698+
}
2699+
}
2700+
else
26992701
{
2700-
if (varDsc->lvIsHfa())
2702+
if (varTypeIsStruct(varDsc))
2703+
{
2704+
// Must be <= 16 bytes or else it wouldn't be passed in registers, except for HFA,
2705+
// which can be bigger (and is handled above).
2706+
noway_assert(EA_SIZE_IN_BYTES(varDsc->lvSize()) <= 16);
2707+
loadType = compiler->getJitGCType(varDsc->lvGcLayout[0]);
2708+
}
2709+
else
27012710
{
2702-
NYI_ARM64("CodeGen::genJmpMethod with multireg HFA arg");
2711+
loadType = compiler->mangleVarArgsType(genActualType(varDsc->TypeGet()));
27032712
}
2713+
emitAttr loadSize = emitActualTypeSize(loadType);
2714+
getEmitter()->emitIns_R_S(ins_Load(loadType), loadSize, argReg, varNum, 0);
2715+
2716+
// Update argReg life and GC Info to indicate varDsc stack slot is dead and argReg is going live.
2717+
// Note that we cannot modify varDsc->lvRegNum here because another basic block may not be expecting it.
2718+
// Therefore manually update life of argReg. Note that GT_JMP marks the end of the basic block
2719+
// and after which reg life and gc info will be recomputed for the new block in genCodeForBBList().
2720+
regSet.AddMaskVars(genRegMask(argReg));
2721+
gcInfo.gcMarkRegPtrVal(argReg, loadType);
27042722

2705-
// Restore the second register.
2706-
argRegNext = genRegArgNext(argReg);
2723+
if (compiler->lvaIsMultiregStruct(varDsc, compiler->info.compIsVarArgs))
2724+
{
2725+
// Restore the second register.
2726+
argRegNext = genRegArgNext(argReg);
27072727

2708-
loadType = compiler->getJitGCType(varDsc->lvGcLayout[1]);
2709-
loadSize = emitActualTypeSize(loadType);
2710-
getEmitter()->emitIns_R_S(ins_Load(loadType), loadSize, argRegNext, varNum, TARGET_POINTER_SIZE);
2728+
loadType = compiler->getJitGCType(varDsc->lvGcLayout[1]);
2729+
loadSize = emitActualTypeSize(loadType);
2730+
getEmitter()->emitIns_R_S(ins_Load(loadType), loadSize, argRegNext, varNum, TARGET_POINTER_SIZE);
27112731

2712-
regSet.AddMaskVars(genRegMask(argRegNext));
2713-
gcInfo.gcMarkRegPtrVal(argRegNext, loadType);
2714-
}
2732+
regSet.AddMaskVars(genRegMask(argRegNext));
2733+
gcInfo.gcMarkRegPtrVal(argRegNext, loadType);
2734+
}
27152735

2716-
if (compiler->lvaIsGCTracked(varDsc))
2717-
{
2718-
VarSetOps::RemoveElemD(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex);
2736+
if (compiler->lvaIsGCTracked(varDsc))
2737+
{
2738+
VarSetOps::RemoveElemD(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex);
2739+
}
27192740
}
27202741
}
27212742

27222743
if (compiler->info.compIsVarArgs)
27232744
{
27242745
// In case of a jmp call to a vararg method ensure only integer registers are passed.
27252746
assert((genRegMask(argReg) & (RBM_ARG_REGS | RBM_ARG_RET_BUFF)) != RBM_NONE);
2747+
assert(!varDsc->lvIsHfaRegArg());
27262748

27272749
fixedIntArgMask |= genRegMask(argReg);
27282750

0 commit comments

Comments
 (0)