[RISC-V] Add gcinfodumper implementation.
authorMikhail Kurinnoi <m.kurinnoi@samsung.com>
Wed, 29 May 2024 12:26:27 +0000 (15:26 +0300)
committer이형주/MDE Lab(SR)/삼성전자 <leee.lee@samsung.com>
Tue, 4 Jun 2024 07:39:43 +0000 (16:39 +0900)
Port from `diagnostics` upstream https://github.com/dotnet/diagnostics/pull/4703

src/shared/gcdump/gcinfodumper.cpp

index 79b09ae0400d414cebda501616f00036eeb5e47b..f7b483be3dd4072eae66a7a23b2e0f02458102ce 100644 (file)
@@ -187,26 +187,26 @@ BOOL GcInfoDumper::ReportPointerRecord (
 #undef REG
 #elif defined(TARGET_RISCV64)
 #undef REG
-#define REG(reg, field) { offsetof(RiscV64VolatileContextPointer, field) }
-        REG(zero, R0),
-        REG(a0, A0),
-        REG(a1, A1),
-        REG(a2, A2),
-        REG(a3, A3),
-        REG(a4, A4),
-        REG(a5, A5),
-        REG(a6, A6),
-        REG(a7, A7),
-        REG(t0, T0),
-        REG(t1, T1),
-        REG(t2, T2),
-        REG(t3, T3),
-        REG(t4, T4),
-        REG(t5, T5),
-        REG(t6, T6),
-#undef REG
-#define REG(reg, field) { offsetof(T_KNONVOLATILE_CONTEXT_POINTERS, field) }
+#define REG(reg, field) { FIELD_OFFSET(T_KNONVOLATILE_CONTEXT_POINTERS, field) }
+#define vREG(reg, field) { FIELD_OFFSET(RiscV64VolatileContextPointer, field) }
+        vREG(zero, R0),
+        REG(Ra, Ra),
+        { FIELD_OFFSET(T_CONTEXT, Sp) },
+        REG(Gp, Gp),
+        REG(Tp, Tp),
+        vREG(t0, T0),
+        vREG(t1, T1),
+        vREG(t2, T2),
+        REG(Fp, Fp),
         REG(s1, S1),
+        vREG(a0, A0),
+        vREG(a1, A1),
+        vREG(a2, A2),
+        vREG(a3, A3),
+        vREG(a4, A4),
+        vREG(a5, A5),
+        vREG(a6, A6),
+        vREG(a7, A7),
         REG(s2, S2),
         REG(s3, S3),
         REG(s4, S4),
@@ -217,11 +217,11 @@ BOOL GcInfoDumper::ReportPointerRecord (
         REG(s9, S9),
         REG(s10, S10),
         REG(s11, S11),
-        REG(ra, Ra),
-        REG(gp, Gp),
-        REG(tp, Tp),
-        REG(fp, Fp),
-        { offsetof(T_CONTEXT, Sp) },
+        vREG(t3, T3),
+        vREG(t4, T4),
+        vREG(t5, T5),
+        vREG(t6, T6),
+#undef vREG
 #undef REG
 #else
 PORTABILITY_ASSERT("GcInfoDumper::ReportPointerRecord is not implemented on this platform.")
@@ -241,11 +241,10 @@ PORTABILITY_ASSERT("GcInfoDumper::ReportPointerRecord is not implemented on this
     iSPRegister = (FIELD_OFFSET(T_CONTEXT, Sp) - FIELD_OFFSET(T_CONTEXT, R0)) / sizeof(ULONG);
     UINT iBFRegister = m_StackBaseRegister;
 #elif defined(TARGET_RISCV64)
-    assert(!"unimplemented on RISCV64 yet");
-    iSPRegister = 0;
+    iSPRegister = (FIELD_OFFSET(T_CONTEXT, Sp) - FIELD_OFFSET(T_CONTEXT, R0)) / sizeof(ULONGLONG);
 #endif
 
-#if defined(TARGET_ARM) || defined(TARGET_ARM64)
+#if defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_RISCV64)
     BYTE* pContext = (BYTE*)&(pRD->volatileCurrContextPointers);
 #else
     BYTE* pContext = (BYTE*)pRD->pCurrentContext;
@@ -313,6 +312,19 @@ PORTABILITY_ASSERT("GcInfoDumper::ReportPointerRecord is not implemented on this
             {
                 break;
             }
+#elif defined(TARGET_RISCV64)
+            bool isVolatile = (iReg == 0 || (iReg >= 5 && iReg <= 7) || (iReg >= 10 && iReg <= 17) || iReg >= 28);
+            if (ctx == 0)
+            {
+                if (!isVolatile)
+                {
+                    continue;
+                }
+            }
+            else if (isVolatile) // skip volatile registers for second context
+            {
+                continue;
+            }
 #endif
             {
                 _ASSERTE(iReg < ARRAY_SIZE(rgRegisters));
@@ -331,7 +343,7 @@ PORTABILITY_ASSERT("GcInfoDumper::ReportPointerRecord is not implemented on this
                     pReg = *(SIZE_T**)((BYTE*)pRD->pCurrentContextPointers + rgRegisters[iEncodedReg].cbContextOffset);
                 }
 
-#elif defined(TARGET_ARM64)
+#elif defined(TARGET_ARM64) || defined(TARGET_RISCV64)
                 pReg = *(SIZE_T**)(pContext + rgRegisters[iReg].cbContextOffset);
                 if (iEncodedReg == iSPRegister)
                 {
@@ -404,14 +416,14 @@ PORTABILITY_ASSERT("GcInfoDumper::ReportPointerRecord is not implemented on this
                 GcStackSlotBase base;
                 if (iSPRegister == iEncodedReg)
                 {
-#if defined(TARGET_ARM) || defined(TARGET_ARM64)
+#if defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_RISCV64)
                     base = GC_SP_REL;
 #else
                     if (0 == ctx)
                         base = GC_SP_REL;
                     else
                         base = GC_CALLER_SP_REL;
-#endif //defined(TARGET_ARM) || defined(TARGET_ARM64)
+#endif //defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_RISCV64)
                 }
                 else
                 {
@@ -433,7 +445,7 @@ PORTABILITY_ASSERT("GcInfoDumper::ReportPointerRecord is not implemented on this
             }
         }
 
-#if defined(TARGET_ARM) || defined(TARGET_ARM64)
+#if defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_RISCV64)
         pContext = (BYTE*)pRD->pCurrentContextPointers;
 #else
         pContext = (BYTE*)pRD->pCallerContext;
@@ -639,8 +651,57 @@ GcInfoDumper::EnumerateStateChangesResults GcInfoDumper::EnumerateStateChanges (
         *(ppVolatileReg+iReg) = &regdisp.pCurrentContext->X0 + iReg;
     }
 #elif defined(TARGET_RISCV64)
-#pragma message("Unimplemented for RISCV64 yet.")
-    assert(!"unimplemented on RISCV64 yet");
+    FILL_REGS(pCurrentContext->R0, 33);
+    FILL_REGS(pCallerContext->R0, 33);
+
+    regdisp.pCurrentContextPointers = &regdisp.ctxPtrsOne;
+    regdisp.pCallerContextPointers = &regdisp.ctxPtrsTwo;
+
+    // Set S1
+    regdisp.pCurrentContextPointers->S1 = &regdisp.pCurrentContext->S1;
+    regdisp.pCallerContextPointers ->S1 = &regdisp.pCallerContext ->S1;
+
+    ULONG64 **ppCurrentReg = &regdisp.pCurrentContextPointers->S2;
+    ULONG64 **ppCallerReg  = &regdisp.pCallerContextPointers ->S2;
+    // Set  S2-S11
+    for (iReg = 0; iReg < 10; iReg++)
+    {
+        *(ppCurrentReg + iReg) = &regdisp.pCurrentContext->S2 + iReg;
+        *(ppCallerReg  + iReg) = &regdisp.pCallerContext ->S2 + iReg;
+    }
+
+    // Set Fp
+    regdisp.pCurrentContextPointers->Fp = &regdisp.pCurrentContext->Fp;
+    regdisp.pCallerContextPointers ->Fp = &regdisp.pCallerContext ->Fp;
+
+    // Set Gp
+    regdisp.pCurrentContextPointers->Gp = &regdisp.pCurrentContext->Gp;
+    regdisp.pCallerContextPointers ->Gp = &regdisp.pCallerContext ->Gp;
+
+    // Set Tp
+    regdisp.pCurrentContextPointers->Tp = &regdisp.pCurrentContext->Tp;
+    regdisp.pCallerContextPointers ->Tp = &regdisp.pCallerContext ->Tp;
+
+    // Set Ra
+    regdisp.pCurrentContextPointers->Ra = &regdisp.pCurrentContext->Ra;
+    regdisp.pCallerContextPointers ->Ra = &regdisp.pCallerContext ->Ra;
+
+    regdisp.volatileCurrContextPointers.R0 = &regdisp.pCurrentContext->R0;
+    regdisp.volatileCurrContextPointers.A0 = &regdisp.pCurrentContext->A0;
+    regdisp.volatileCurrContextPointers.A1 = &regdisp.pCurrentContext->A1;
+    regdisp.volatileCurrContextPointers.A2 = &regdisp.pCurrentContext->A2;
+    regdisp.volatileCurrContextPointers.A3 = &regdisp.pCurrentContext->A3;
+    regdisp.volatileCurrContextPointers.A4 = &regdisp.pCurrentContext->A4;
+    regdisp.volatileCurrContextPointers.A5 = &regdisp.pCurrentContext->A5;
+    regdisp.volatileCurrContextPointers.A6 = &regdisp.pCurrentContext->A6;
+    regdisp.volatileCurrContextPointers.A7 = &regdisp.pCurrentContext->A7;
+    regdisp.volatileCurrContextPointers.T0 = &regdisp.pCurrentContext->T0;
+    regdisp.volatileCurrContextPointers.T1 = &regdisp.pCurrentContext->T1;
+    regdisp.volatileCurrContextPointers.T2 = &regdisp.pCurrentContext->T2;
+    regdisp.volatileCurrContextPointers.T3 = &regdisp.pCurrentContext->T3;
+    regdisp.volatileCurrContextPointers.T4 = &regdisp.pCurrentContext->T4;
+    regdisp.volatileCurrContextPointers.T5 = &regdisp.pCurrentContext->T5;
+    regdisp.volatileCurrContextPointers.T6 = &regdisp.pCurrentContext->T6;
 #else
 PORTABILITY_ASSERT("GcInfoDumper::EnumerateStateChanges is not implemented on this platform.")
 #endif
@@ -688,9 +749,9 @@ PORTABILITY_ASSERT("GcInfoDumper::EnumerateStateChanges is not implemented on th
                                (GcInfoDecoderFlags)(  DECODE_SECURITY_OBJECT
                                                     | DECODE_CODE_LENGTH
                                                     | DECODE_VARARG
-#if defined(TARGET_ARM) || defined(TARGET_ARM64)
+#if defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_RISCV64)
                                                     | DECODE_HAS_TAILCALLS
-#endif // TARGET_ARM || TARGET_ARM64
+#endif // TARGET_ARM || TARGET_ARM64 || TARGET_RISCV64
 
                                                     | DECODE_INTERRUPTIBILITY),
                                offset);
@@ -709,7 +770,7 @@ PORTABILITY_ASSERT("GcInfoDumper::EnumerateStateChanges is not implemented on th
 
 #ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED
         UINT32 safePointOffset = offset;
-#if defined(TARGET_AMD64) || defined(TARGET_ARM) || defined(TARGET_ARM64)
+#if defined(TARGET_AMD64) || defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_RISCV64)
         safePointOffset++;
 #endif
         if(safePointDecoder.IsSafePoint(safePointOffset))