Skip to content

Commit

Permalink
[RISC-V] Implement some of the NYI methods in unwindriscv64 (#95128)
Browse files Browse the repository at this point in the history
* [RISC-V] Implement Compiler::mapRegNumToDwarfReg

* [RISC-V] Add BAD_CODE definition

* [RISC-V] Implement GetUnwindSizeFromUnwindHeader

* [RISC-V] Implement UnwindPrologCodes::Dump

* [RISC-V] Implement UnwindEpilogCodes::Dump

* [RISC-V] Implement UnwindEpilogInfo::Dump

* [Risc-V] Implement UnwindFragmentInfo::Dump

* [RISC-V] Implement UnwindInfo::HotColdSplitCodes

* [RISC-V] Implement UnwindInfo::Dump

* [RISC-V] Partly fix for previous implementation of GetUnwindSizeFromUnwindHeader

* [RISC-V] Mark s_UnwindSize as const

Co-authored-by: Tomasz Sowiński <tomeksowi@gmail.com>

* [RISC-V] Replace NULL with nullptr in new functions

* [RISC-V] Fix formatting and shorten mapRegNumToDwarfReg

* [RISC-V] Apply format.linux.x64.patch

* [RISC-V] Add braces according to coding standard in jit

* [RISC-V] Correct array of unwind sizes

* [RISC-V] Fix s_UnwindSize: 0xDE=2, 0xDD=3

---------

Co-authored-by: Tomasz Sowiński <tomeksowi@gmail.com>
  • Loading branch information
sirntar and tomeksowi authored Nov 28, 2023
1 parent f106d7e commit 05bc701
Show file tree
Hide file tree
Showing 3 changed files with 178 additions and 21 deletions.
2 changes: 2 additions & 0 deletions src/coreclr/jit/instr.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

#ifdef TARGET_LOONGARCH64
#define BAD_CODE 0XFFFFFFFF
#elif TARGET_RISCV64
#define BAD_CODE 0X00000000
#else
#define BAD_CODE 0x0BADC0DE // better not match a real encoding!
#endif
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/jit/instrsriscv64.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
* ld/st/cmp -- load/store/compare instruction
* encode -- encoding 1
*
******************************************************************************/
******************************************************************************/

#if !defined(TARGET_RISCV64)
#error Unexpected target type
Expand All @@ -31,7 +31,7 @@
// clang-format off

// RV32I & RV64I
INST(invalid, "INVALID", 0, 0x00000000)
INST(invalid, "INVALID", 0, BAD_CODE)
INST(nop, "nop", 0, 0x00000013)

//// R_R
Expand Down
193 changes: 174 additions & 19 deletions src/coreclr/jit/unwindriscv64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,20 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#if defined(FEATURE_CFI_SUPPORT)
short Compiler::mapRegNumToDwarfReg(regNumber reg)
{
NYI_RISCV64("mapRegNumToDwarfReg-----unimplemented on RISCV64 yet----");
return 0;
short dwarfReg = DWARF_REG_ILLEGAL;

// On RISC-V registers from R0 to F31
// can be mapped directly to dwarf structure
if (reg >= REG_R0 && reg <= REG_F31)
{
dwarfReg = static_cast<short>(reg);
}
else
{
NYI("CFI codes"); // e.g. V-extension
}

return dwarfReg;
}
#endif // FEATURE_CFI_SUPPORT

Expand Down Expand Up @@ -166,8 +178,8 @@ void Compiler::unwindSaveReg(regNumber reg, int offset)
{
// save_reg: 11010000 | 000xxxxx | zzzzzzzz: save reg r(1 + #X) at [sp + #Z * 8], offset <= 2047

assert(reg == REG_RA ||
(REG_FP <= reg && reg <= REG_S11)); // first legal register: RA, last legal register: S11
assert(reg == REG_RA || (REG_FP <= reg && reg <= REG_S11)); // first legal register: RA, last legal register:
// S11

BYTE x = (BYTE)(reg - REG_RA);
assert(0 <= x && x <= 0x1B);
Expand Down Expand Up @@ -212,8 +224,29 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

unsigned GetUnwindSizeFromUnwindHeader(BYTE b1)
{
NYI_RISCV64("GetUnwindSizeFromUnwindHeader-----unimplemented on RISCV64 yet----");
return 0;
static const BYTE s_UnwindSize[256] = {
// array of unwind sizes, in bytes
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 00-0F
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 10-1F
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 20-2F
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 30-3F
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 40-4F
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 50-5F
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 60-6F
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 70-7F
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 80-8F
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 90-9F
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A0-AF
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B0-BF
2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 3, 2, 2, 2, // C0-CF
3, 2, 2, 2, 2, 2, 3, 2, 3, 2, 3, 2, 3, 3, 2, 1, // D0-DF
4, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E0-EF
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F0-FF
};

unsigned size = s_UnwindSize[b1];
assert(1 <= size && size <= 4);
return size;
}

#endif // DEBUG
Expand Down Expand Up @@ -864,13 +897,11 @@ void Compiler::unwindEmitFunc(FuncInfoDsc* func, void* pHotCode, void* pColdCode

void UnwindPrologCodes::SetFinalSize(int headerBytes, int epilogBytes)
{
#if 0 // TODO COMMENTED OUT BECAUSE s_UnwindSize is not set
#ifdef DEBUG
// We're done adding codes. Check that we didn't accidentally create a bigger prolog.
unsigned codeSize = GetCodeSizeFromUnwindCodes(true);
assert(codeSize <= MAX_PROLOG_SIZE_BYTES);
#endif // DEBUG
#endif

int prologBytes = Size();

Expand Down Expand Up @@ -929,9 +960,9 @@ void UnwindPrologCodes::AppendEpilog(UnwindEpilogInfo* pEpi)

int epiSize = pEpi->Size();
memcpy_s(&upcMem[upcEpilogSlot], upcMemSize - upcEpilogSlot - 3, pEpi->GetCodes(),
epiSize); // -3 to avoid writing to the alignment padding
assert(pEpi->GetStartIndex() ==
upcEpilogSlot - upcCodeSlot); // Make sure we copied it where we expected to copy it.
epiSize); // -3 to avoid writing to the alignment padding
assert(pEpi->GetStartIndex() == upcEpilogSlot - upcCodeSlot); // Make sure we copied it where we expected to copy
// it.

upcEpilogSlot += epiSize;
assert(upcEpilogSlot <= upcMemSize - 3);
Expand Down Expand Up @@ -1053,7 +1084,41 @@ void UnwindPrologCodes::EnsureSize(int requiredSize)
#ifdef DEBUG
void UnwindPrologCodes::Dump(int indent)
{
NYI_RISCV64("Dump-----unimplemented on RISCV64 yet----");
printf("%*sUnwindPrologCodes @0x%08p, size:%d:\n", indent, "", dspPtr(this), sizeof(*this));
printf("%*s uwiComp: 0x%08p\n", indent, "", dspPtr(uwiComp));
printf("%*s &upcMemLocal[0]: 0x%08p\n", indent, "", dspPtr(&upcMemLocal[0]));
printf("%*s upcMem: 0x%08p\n", indent, "", dspPtr(upcMem));
printf("%*s upcMemSize: %d\n", indent, "", upcMemSize);
printf("%*s upcCodeSlot: %d\n", indent, "", upcCodeSlot);
printf("%*s upcHeaderSlot: %d\n", indent, "", upcHeaderSlot);
printf("%*s upcEpilogSlot: %d\n", indent, "", upcEpilogSlot);
printf("%*s upcUnwindBlockSlot: %d\n", indent, "", upcUnwindBlockSlot);

if (upcMemSize > 0)
{
printf("%*s codes:", indent, "");
for (int i = 0; i < upcMemSize; i++)
{
printf(" %02x", upcMem[i]);
if (i == upcCodeSlot)
{
printf(" <-C");
}
else if (i == upcHeaderSlot)
{
printf(" <-H");
}
else if (i == upcEpilogSlot)
{
printf(" <-E");
}
else if (i == upcUnwindBlockSlot)
{
printf(" <-U");
}
}
printf("\n");
}
}
#endif // DEBUG

Expand Down Expand Up @@ -1092,7 +1157,27 @@ void UnwindEpilogCodes::EnsureSize(int requiredSize)
#ifdef DEBUG
void UnwindEpilogCodes::Dump(int indent)
{
NYI_RISCV64("Dump-----unimplemented on RISCV64 yet----");
printf("%*sUnwindEpilogCodes @0x%08p, size:%d:\n", indent, "", dspPtr(this), sizeof(*this));
printf("%*s uwiComp: 0x%08p\n", indent, "", dspPtr(uwiComp));
printf("%*s &uecMemLocal[0]: 0x%08p\n", indent, "", dspPtr(&uecMemLocal[0]));
printf("%*s uecMem: 0x%08p\n", indent, "", dspPtr(uecMem));
printf("%*s uecMemSize: %d\n", indent, "", uecMemSize);
printf("%*s uecCodeSlot: %d\n", indent, "", uecCodeSlot);
printf("%*s uecFinalized: %s\n", indent, "", dspBool(uecFinalized));

if (uecMemSize > 0)
{
printf("%*s codes:", indent, "");
for (int i = 0; i < uecMemSize; i++)
{
printf(" %02x", uecMem[i]);
if (i == uecCodeSlot)
{
printf(" <-C"); // Indicate the current pointer
}
}
printf("\n");
}
}
#endif // DEBUG

Expand Down Expand Up @@ -1149,7 +1234,15 @@ void UnwindEpilogInfo::FinalizeOffset()
#ifdef DEBUG
void UnwindEpilogInfo::Dump(int indent)
{
NYI_RISCV64("Dump-----unimplemented on RISCV64 yet----");
printf("%*sUnwindEpilogInfo @0x%08p, size:%d:\n", indent, "", dspPtr(this), sizeof(*this));
printf("%*s uwiComp: 0x%08p\n", indent, "", dspPtr(uwiComp));
printf("%*s epiNext: 0x%08p\n", indent, "", dspPtr(epiNext));
printf("%*s epiEmitLocation: 0x%08p\n", indent, "", dspPtr(epiEmitLocation));
printf("%*s epiStartOffset: 0x%x\n", indent, "", epiStartOffset);
printf("%*s epiMatches: %s\n", indent, "", dspBool(epiMatches));
printf("%*s epiStartIndex: %d\n", indent, "", epiStartIndex);

epiCodes.Dump(indent + 2);
}
#endif // DEBUG

Expand Down Expand Up @@ -1500,8 +1593,8 @@ void UnwindFragmentInfo::Finalize(UNATIVE_OFFSET functionLength)

// Start writing the header

noway_assert(headerFunctionLength <=
0x3FFFFU); // We create fragments to prevent this from firing, so if it hits, we have an internal error
noway_assert(headerFunctionLength <= 0x3FFFFU); // We create fragments to prevent this from firing, so if it hits,
// we have an internal error

if ((headerEpilogCount > UW_MAX_EPILOG_COUNT) || (headerCodeWords > UW_MAX_CODE_WORDS_COUNT))
{
Expand Down Expand Up @@ -1686,7 +1779,39 @@ void UnwindFragmentInfo::Allocate(
#ifdef DEBUG
void UnwindFragmentInfo::Dump(int indent)
{
NYI_RISCV64("Dump-----unimplemented on RISCV64 yet----");
unsigned count;
UnwindEpilogInfo* pEpi;

count = 0;
for (pEpi = ufiEpilogList; pEpi != nullptr; pEpi = pEpi->epiNext)
{
++count;
}

printf("%*sUnwindFragmentInfo #%d, @0x%08p, size:%d:\n", indent, "", ufiNum, dspPtr(this), sizeof(*this));
printf("%*s uwiComp: 0x%08p\n", indent, "", dspPtr(uwiComp));
printf("%*s ufiNext: 0x%08p\n", indent, "", dspPtr(ufiNext));
printf("%*s ufiEmitLoc: 0x%08p\n", indent, "", dspPtr(ufiEmitLoc));
printf("%*s ufiHasPhantomProlog: %s\n", indent, "", dspBool(ufiHasPhantomProlog));
printf("%*s %d epilog%s\n", indent, "", count, (count != 1) ? "s" : "");
printf("%*s ufiEpilogList: 0x%08p\n", indent, "", dspPtr(ufiEpilogList));
printf("%*s ufiEpilogLast: 0x%08p\n", indent, "", dspPtr(ufiEpilogLast));
printf("%*s ufiCurCodes: 0x%08p\n", indent, "", dspPtr(ufiCurCodes));
printf("%*s ufiSize: %u\n", indent, "", ufiSize);
printf("%*s ufiSetEBit: %s\n", indent, "", dspBool(ufiSetEBit));
printf("%*s ufiNeedExtendedCodeWordsEpilogCount: %s\n", indent, "", dspBool(ufiNeedExtendedCodeWordsEpilogCount));
printf("%*s ufiCodeWords: %u\n", indent, "", ufiCodeWords);
printf("%*s ufiEpilogScopes: %u\n", indent, "", ufiEpilogScopes);
printf("%*s ufiStartOffset: 0x%x\n", indent, "", ufiStartOffset);
printf("%*s ufiInProlog: %s\n", indent, "", dspBool(ufiInProlog));
printf("%*s ufiInitialized: 0x%08x\n", indent, "", ufiInitialized);

ufiPrologCodes.Dump(indent + 2);

for (pEpi = ufiEpilogList; pEpi != nullptr; pEpi = pEpi->epiNext)
{
pEpi->Dump(indent + 2);
}
}
#endif // DEBUG

Expand Down Expand Up @@ -1729,7 +1854,18 @@ void UnwindInfo::InitUnwindInfo(Compiler* comp, emitLocation* startLoc, emitLoca

void UnwindInfo::HotColdSplitCodes(UnwindInfo* puwi)
{
NYI_RISCV64("HotColdSplitCodes-----unimplemented on RISCV64 yet----");
// Ensure that there is exactly a single fragment in both the hot and the cold sections
assert(&uwiFragmentFirst == uwiFragmentLast);
assert(&puwi->uwiFragmentFirst == puwi->uwiFragmentLast);
assert(uwiFragmentLast->ufiNext == nullptr);
assert(puwi->uwiFragmentLast->ufiNext == nullptr);

// The real prolog is in the hot section, so this, cold, section has a phantom prolog
uwiFragmentLast->ufiHasPhantomProlog = true;
uwiFragmentLast->CopyPrologCodes(puwi->uwiFragmentLast);

// Now split the epilog codes
uwiFragmentLast->SplitEpilogCodes(uwiFragmentLast->ufiEmitLoc, puwi->uwiFragmentLast);
}

// Split the function or funclet into fragments that are no larger than 512K,
Expand Down Expand Up @@ -1942,7 +2078,26 @@ void UnwindInfo::AddFragment(emitLocation* emitLoc)

void UnwindInfo::Dump(bool isHotCode, int indent)
{
NYI_RISCV64("Dump-----unimplemented on RISCV64 yet----");
unsigned count;
UnwindFragmentInfo* pFrag;

count = 0;
for (pFrag = &uwiFragmentFirst; pFrag != nullptr; pFrag = pFrag->ufiNext)
{
++count;
}

printf("%*sUnwindInfo %s@0x%08p, size:%d:\n", indent, "", isHotCode ? "" : "COLD ", dspPtr(this), sizeof(*this));
printf("%*s uwiComp: 0x%08p\n", indent, "", dspPtr(uwiComp));
printf("%*s %d fragment%s\n", indent, "", count, (count != 1) ? "s" : "");
printf("%*s uwiFragmentLast: 0x%08p\n", indent, "", dspPtr(uwiFragmentLast));
printf("%*s uwiEndLoc: 0x%08p\n", indent, "", dspPtr(uwiEndLoc));
printf("%*s uwiInitialized: 0x%08x\n", indent, "", uwiInitialized);

for (pFrag = &uwiFragmentFirst; pFrag != nullptr; pFrag = pFrag->ufiNext)
{
pFrag->Dump(indent + 2);
}
}

#endif // DEBUG
Expand Down

0 comments on commit 05bc701

Please sign in to comment.