Skip to content

Commit

Permalink
Adjust the calleeSavedRegs on top frame for LoongArch64/RISCV64
Browse files Browse the repository at this point in the history
to support the GSCookie.
The frame layout:
 |                       |
 |-----------------------|
 |  incoming arguments   |
 +=======================+ <---- Caller's SP
 |  Varargs regs space   | // Only for varargs main functions; not used for LA64.
 |-----------------------|
 |    MonitorAcquired    | // 8 bytes; for synchronized methods
 |-----------------------|
 |        PSP slot       | // 8 bytes (omitted in NativeAOT ABI)
 |-----------------------|
 |Callee saved registers | // multiple of 8 bytes, not includting FP/RA
 |-----------------------|
 |      Saved RA         | // 8 bytes
 |-----------------------|
 |      Saved FP         | // 8 bytes
 |-----------------------|
 |  possible GS cookie   |
 |-----------------------|
 | locals, temps, etc.   |
 |-----------------------|
 |  possible GS cookie   |
 |-----------------------|
 |   Outgoing arg space  | // multiple of 8 bytes; if required (i.e., #outsz != 0)
 |-----------------------| <---- Ambient SP
 |       |               |
 ~       | Stack grows   ~
 |       | downward      |
  • Loading branch information
shushanhf committed Apr 15, 2024
1 parent 4e702bc commit f94cc0d
Show file tree
Hide file tree
Showing 7 changed files with 496 additions and 722 deletions.
23 changes: 1 addition & 22 deletions src/coreclr/jit/codegen.h
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ class CodeGen final : public CodeGenInterface

FuncletFrameInfoDsc genFuncletInfo;

#elif defined(TARGET_LOONGARCH64)
#elif defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)

// A set of information that is used by funclet prolog and epilog generation.
// It is collected once, before funclet prologs and epilogs are generated,
Expand All @@ -448,26 +448,6 @@ class CodeGen final : public CodeGenInterface
int fiFunction_CallerSP_to_FP_delta; // Delta between caller SP and the frame pointer in the parent function
// (negative)
int fiSP_to_CalleeSaved_delta; // CalleeSaved register save offset from SP (positive)
int fiCalleeSavedPadding; // CalleeSaved offset padding (positive)
int fiSP_to_PSP_slot_delta; // PSP slot offset from SP (positive)
int fiCallerSP_to_PSP_slot_delta; // PSP slot offset from Caller SP (negative)
int fiSpDelta; // Stack pointer delta (negative)
};

FuncletFrameInfoDsc genFuncletInfo;

#elif defined(TARGET_RISCV64)

// A set of information that is used by funclet prolog and epilog generation.
// It is collected once, before funclet prologs and epilogs are generated,
// and used by all funclet prologs and epilogs, which must all be the same.
struct FuncletFrameInfoDsc
{
regMaskTP fiSaveRegs; // Set of callee-saved registers saved in the funclet prolog (includes RA)
int fiFunction_CallerSP_to_FP_delta; // Delta between caller SP and the frame pointer in the parent function
// (negative)
int fiSP_to_CalleeSaved_delta; // CalleeSaved register save offset from SP (positive)
int fiCalleeSavedPadding; // CalleeSaved offset padding (positive)
int fiSP_to_PSP_slot_delta; // PSP slot offset from SP (positive)
int fiCallerSP_to_PSP_slot_delta; // PSP slot offset from Caller SP (negative)
int fiSpDelta; // Stack pointer delta (negative)
Expand Down Expand Up @@ -1272,7 +1252,6 @@ class CodeGen final : public CodeGenInterface
void genJmpMethod(GenTree* jmp);
BasicBlock* genCallFinally(BasicBlock* block);
#if defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
// TODO: refactor for LA.
void genCodeForJumpCompare(GenTreeOpCC* tree);
#endif
#if defined(TARGET_ARM64)
Expand Down
53 changes: 39 additions & 14 deletions src/coreclr/jit/codegencommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4087,7 +4087,7 @@ void CodeGen::genEnregisterOSRArgsAndLocals()

GetEmitter()->emitIns_R_AR(ins_Load(lclTyp), size, varDsc->GetRegNum(), genFramePointerReg(), offset);

#elif defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
#elif defined(TARGET_ARM64)

// Patchpoint offset is from top of Tier0 frame
//
Expand Down Expand Up @@ -4119,7 +4119,39 @@ void CodeGen::genEnregisterOSRArgsAndLocals()

genInstrWithConstant(ins_Load(lclTyp), size, varDsc->GetRegNum(), genFramePointerReg(), offset, initReg);
*pInitRegZeroed = false;
#endif // TARGET_ARM64 || TARGET_LOONGARCH64 || TARGET_RISCV64
#elif defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)

// Patchpoint offset is from top of Tier0 frame
//
// We need to determine the frame-pointer relative
// offset for this variable in the osr frame.
//
// First get the fp's relative offset within Tier0 frame
//
const int tier0FrameOffset = (int)compiler->info.compPatchpointInfo->CalleeSaveRegisters();

// then add the OSR frame size
//
const int osrFrameSize = genTotalFrameSize();

// then subtract OSR SP-FP delta
//
const int osrSpToFpDelta = genSPtoFPdelta();

// | => tier0 top of frame relative
// | + => tier0's fp relative offset
// | | + => osr bottom of frame (sp) relative
// | | | - => osr fp relative
// | | | |
const int offset = stkOffs + tier0FrameOffset + osrFrameSize - osrSpToFpDelta;

JITDUMP("---OSR--- V%02u (reg) Tier0 virtual offset %d OSR frame size %d OSR sp-fp "
"delta %d total offset %d (0x%x)\n",
varNum, stkOffs, osrFrameSize, osrSpToFpDelta, offset, offset);

genInstrWithConstant(ins_Load(lclTyp), size, varDsc->GetRegNum(), genFramePointerReg(), offset, initReg);
*pInitRegZeroed = false;
#endif // TARGET_LOONGARCH64 || TARGET_RISCV64
}
}

Expand Down Expand Up @@ -4745,20 +4777,13 @@ void CodeGen::genFinalizeFrame()
#endif // defined(TARGET_XARCH)

#if defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
if (isFramePointerUsed())
{
// For a FP based frame we have to push/pop the FP register
//
maskCalleeRegsPushed |= RBM_FPBASE;
// This assert check that we are not using REG_FP
assert(!regSet.rsRegsModified(RBM_FPBASE));

// This assert check that we are not using REG_FP
// as both the frame pointer and as a codegen register
//
assert(!regSet.rsRegsModified(RBM_FPBASE));
}
assert(isFramePointerUsed());
// we always push FP/RA. See genPushCalleeSavedRegisters
maskCalleeRegsPushed |= (RBM_FPBASE | RBM_RA);

// we always push RA. See genPushCalleeSavedRegisters
maskCalleeRegsPushed |= RBM_RA;
#endif // TARGET_LOONGARCH64 || TARGET_RISCV64

compiler->compCalleeRegsPushed = genCountBits(maskCalleeRegsPushed);
Expand Down
Loading

0 comments on commit f94cc0d

Please sign in to comment.