From 3ecbd8b4b4dc283207ffe6be60b78842d3767602 Mon Sep 17 00:00:00 2001
From: TIHan <lol.tihan@gmail.com>
Date: Thu, 16 Nov 2023 20:16:42 -0800
Subject: [PATCH 1/3] Added DOTNET_JitDisasmHexDumpFile

---
 src/coreclr/jit/codegencommon.cpp             | 20 +++++++++++
 src/coreclr/jit/compiler.cpp                  |  8 +++++
 src/coreclr/jit/compiler.h                    | 35 ++++++++++---------
 src/coreclr/jit/jitconfigvalues.h             |  4 +++
 .../superpmi-shim-collector/jithost.cpp       |  1 +
 5 files changed, 51 insertions(+), 17 deletions(-)

diff --git a/src/coreclr/jit/codegencommon.cpp b/src/coreclr/jit/codegencommon.cpp
index 225700208b4a2d..23a858182736cd 100644
--- a/src/coreclr/jit/codegencommon.cpp
+++ b/src/coreclr/jit/codegencommon.cpp
@@ -2097,6 +2097,26 @@ void CodeGen::genEmitUnwindDebugGCandEH()
     getDisAssembler().disAsmCode((BYTE*)*codePtr, finalHotCodeSize, (BYTE*)coldCodePtr, finalColdCodeSize);
 #endif // LATE_DISASM
 
+#ifdef DEBUG
+    if ((compiler->opts.disAsm || compiler->verbose) && compiler->opts.disAsmHexDumpFile)
+    {
+        FILE*   hexDmpf;
+        errno_t ec = _wfopen_s(&hexDmpf, compiler->opts.disAsmHexDumpFile, W("at")); // NOTE: file append mode
+        if (ec == 0)
+        {
+            assert(hexDmpf);
+
+            BYTE* addr = (BYTE*)*codePtr + compiler->GetEmitter()->writeableOffset;
+            for (unsigned int i = 0; i < codeSize; i++)
+            {
+                fprintf(hexDmpf, "%02X", *addr++);
+            }
+
+            fclose(hexDmpf);
+        }
+    }
+#endif // DEBUG
+
     /* Report any exception handlers to the VM */
 
     genReportEH();
diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp
index 355403baa92684..690f0d8b160b4a 100644
--- a/src/coreclr/jit/compiler.cpp
+++ b/src/coreclr/jit/compiler.cpp
@@ -2847,6 +2847,8 @@ void Compiler::compInitOptions(JitFlags* jitFlags)
     opts.compLongAddress = false;
     opts.optRepeat       = false;
 
+    opts.disAsmHexDumpFile = nullptr;
+
 #ifdef LATE_DISASM
     opts.doLateDisasm = false;
 #endif // LATE_DISASM
@@ -2931,6 +2933,12 @@ void Compiler::compInitOptions(JitFlags* jitFlags)
             opts.doLateDisasm = true;
 #endif // LATE_DISASM
 
+        const WCHAR* disAsmHexDumpFile = JitConfig.JitDisasmHexDumpFile();
+        if (disAsmHexDumpFile != nullptr)
+        {
+            opts.disAsmHexDumpFile = disAsmHexDumpFile;
+        }
+
         // This one applies to both Ngen/Jit Disasm output: DOTNET_JitDasmWithAddress=1
         if (JitConfig.JitDasmWithAddress() != 0)
         {
diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h
index 48a3278077f622..ec50b1b7067e8e 100644
--- a/src/coreclr/jit/compiler.h
+++ b/src/coreclr/jit/compiler.h
@@ -9705,23 +9705,24 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
         bool disAlignment; // Display alignment boundaries in disassembly code
         bool disCodeBytes; // Display instruction code bytes in disassembly code
 #ifdef DEBUG
-        bool compProcedureSplittingEH; // Separate cold code from hot code for functions with EH
-        bool dspCode;                  // Display native code generated
-        bool dspEHTable;               // Display the EH table reported to the VM
-        bool dspDebugInfo;             // Display the Debug info reported to the VM
-        bool dspInstrs;                // Display the IL instructions intermixed with the native code output
-        bool dspLines;                 // Display source-code lines intermixed with native code output
-        bool dmpHex;                   // Display raw bytes in hex of native code output
-        bool varNames;                 // Display variables names in native code output
-        bool disAsmSpilled;            // Display native code when any register spilling occurs
-        bool disasmWithGC;             // Display GC info interleaved with disassembly.
-        bool disAddr;                  // Display process address next to each instruction in disassembly code
-        bool disAsm2;                  // Display native code after it is generated using external disassembler
-        bool dspOrder;                 // Display names of each of the methods that we ngen/jit
-        bool dspUnwind;                // Display the unwind info output
-        bool compLongAddress;          // Force using large pseudo instructions for long address
-                                       // (IF_LARGEJMP/IF_LARGEADR/IF_LARGLDC)
-        bool dspGCtbls;                // Display the GC tables
+        bool compProcedureSplittingEH;  // Separate cold code from hot code for functions with EH
+        bool dspCode;                   // Display native code generated
+        bool dspEHTable;                // Display the EH table reported to the VM
+        bool dspDebugInfo;              // Display the Debug info reported to the VM
+        bool dspInstrs;                 // Display the IL instructions intermixed with the native code output
+        bool dspLines;                  // Display source-code lines intermixed with native code output
+        bool dmpHex;                    // Display raw bytes in hex of native code output
+        bool varNames;                  // Display variables names in native code output
+        bool disAsmSpilled;             // Display native code when any register spilling occurs
+        bool disasmWithGC;              // Display GC info interleaved with disassembly.
+        bool disAddr;                   // Display process address next to each instruction in disassembly code
+        bool disAsm2;                   // Display native code after it is generated using external disassembler
+        bool dspOrder;                  // Display names of each of the methods that we ngen/jit
+        bool dspUnwind;                 // Display the unwind info output
+        bool compLongAddress;           // Force using large pseudo instructions for long address
+                                        // (IF_LARGEJMP/IF_LARGEADR/IF_LARGLDC)
+        bool dspGCtbls;                 // Display the GC tables
+        const WCHAR* disAsmHexDumpFile; // Writes the raw bytes in hex of native code to the specified file
 #endif
 
 // Default numbers used to perform loop alignment. All the numbers are chosen
diff --git a/src/coreclr/jit/jitconfigvalues.h b/src/coreclr/jit/jitconfigvalues.h
index 65afd348819e11..9e1b1470362956 100644
--- a/src/coreclr/jit/jitconfigvalues.h
+++ b/src/coreclr/jit/jitconfigvalues.h
@@ -676,6 +676,10 @@ CONFIG_INTEGER(JitEnableCrossBlockLocalAssertionProp, W("JitEnableCrossBlockLoca
 CONFIG_STRING(JitFunctionFile, W("JitFunctionFile"))
 #endif // DEBUG
 
+#if defined(DEBUG)
+CONFIG_STRING(JitDisasmHexDumpFile, W("JitDisasmHexDumpFile"))
+#endif // DEBUG
+
 #if defined(DEBUG)
 #if defined(TARGET_ARM64)
 // JitSaveFpLrWithCalleeSavedRegisters:
diff --git a/src/coreclr/tools/superpmi/superpmi-shim-collector/jithost.cpp b/src/coreclr/tools/superpmi/superpmi-shim-collector/jithost.cpp
index 2917fdab80cb43..35610f325f5344 100644
--- a/src/coreclr/tools/superpmi/superpmi-shim-collector/jithost.cpp
+++ b/src/coreclr/tools/superpmi/superpmi-shim-collector/jithost.cpp
@@ -86,6 +86,7 @@ bool RecordVariable(const WCHAR* key)
         W("JitInlinePolicyDumpXml"),
         W("JitInlineReplayFile"),
         W("JitFunctionFile")
+        W("JitDisasmHexDumpFile")
     };
 
     for (const WCHAR* ignoredVar : s_ignoredVars)

From 1e899a596b9e14984fc688f565f8919f7a98c75d Mon Sep 17 00:00:00 2001
From: TIHan <lol.tihan@gmail.com>
Date: Fri, 17 Nov 2023 12:42:01 -0800
Subject: [PATCH 2/3] Feedback. Removed old hexdmp code as it was not being
 used.

---
 src/coreclr/jit/codegencommon.cpp             | 100 ++++--------------
 src/coreclr/jit/compiler.cpp                  |   9 --
 src/coreclr/jit/compiler.h                    |  34 +++---
 src/coreclr/jit/jitconfigvalues.h             |   3 +-
 src/coreclr/jit/utils.cpp                     |  13 +--
 src/coreclr/jit/utils.h                       |   2 +-
 .../superpmi-shim-collector/jithost.cpp       |   3 +-
 7 files changed, 45 insertions(+), 119 deletions(-)

diff --git a/src/coreclr/jit/codegencommon.cpp b/src/coreclr/jit/codegencommon.cpp
index 23a858182736cd..e0a56103f8438b 100644
--- a/src/coreclr/jit/codegencommon.cpp
+++ b/src/coreclr/jit/codegencommon.cpp
@@ -2098,21 +2098,31 @@ void CodeGen::genEmitUnwindDebugGCandEH()
 #endif // LATE_DISASM
 
 #ifdef DEBUG
-    if ((compiler->opts.disAsm || compiler->verbose) && compiler->opts.disAsmHexDumpFile)
+    if (JitConfig.JitRawHexCode().contains(compiler->info.compMethodHnd, compiler->info.compClassHnd,
+                                           &compiler->info.compMethodInfo->args))
     {
-        FILE*   hexDmpf;
-        errno_t ec = _wfopen_s(&hexDmpf, compiler->opts.disAsmHexDumpFile, W("at")); // NOTE: file append mode
-        if (ec == 0)
-        {
-            assert(hexDmpf);
+        BYTE* addr = (BYTE*)*codePtr + compiler->GetEmitter()->writeableOffset;
 
-            BYTE* addr = (BYTE*)*codePtr + compiler->GetEmitter()->writeableOffset;
-            for (unsigned int i = 0; i < codeSize; i++)
+        const WCHAR* rawHexCodeFilePath = JitConfig.JitRawHexCodeFile();
+        if (rawHexCodeFilePath)
+        {
+            FILE*   hexDmpf;
+            errno_t ec = _wfopen_s(&hexDmpf, rawHexCodeFilePath, W("at")); // NOTE: file append mode
+            if (ec == 0)
             {
-                fprintf(hexDmpf, "%02X", *addr++);
+                assert(hexDmpf);
+                hexDump(hexDmpf, addr, codeSize);
+                fclose(hexDmpf);
             }
+        }
+        else
+        {
+            FILE* dmpf = jitstdout();
 
-            fclose(hexDmpf);
+            fprintf(dmpf, "Generated native code for %s:\n", compiler->info.compFullName);
+            fprintf(dmpf, "\n");
+            hexDump(dmpf, addr, codeSize);
+            fprintf(dmpf, "\n\n");
         }
     }
 #endif // DEBUG
@@ -2121,74 +2131,8 @@ void CodeGen::genEmitUnwindDebugGCandEH()
 
     genReportEH();
 
-#ifdef JIT32_GCENCODER
-#ifdef DEBUG
-    void* infoPtr =
-#endif // DEBUG
-#endif
-        // Create and store the GC info for this method.
-        genCreateAndStoreGCInfo(codeSize, prologSize, epilogSize DEBUGARG(codePtr));
-
-#ifdef DEBUG
-    FILE* dmpf = jitstdout();
-
-    compiler->opts.dmpHex = false;
-    if (!strcmp(compiler->info.compMethodName, "<name of method you want the hex dump for"))
-    {
-        FILE*   codf;
-        errno_t ec = fopen_s(&codf, "C:\\JIT.COD", "at"); // NOTE: file append mode
-        if (ec != 0)
-        {
-            assert(codf);
-            dmpf                  = codf;
-            compiler->opts.dmpHex = true;
-        }
-    }
-    if (compiler->opts.dmpHex)
-    {
-        size_t consSize = GetEmitter()->emitDataSize();
-
-        fprintf(dmpf, "Generated code for %s:\n", compiler->info.compFullName);
-        fprintf(dmpf, "\n");
-
-        if (codeSize)
-        {
-            fprintf(dmpf, "    Code  at %p [%04X bytes]\n", dspPtr(*codePtr), codeSize);
-        }
-        if (consSize)
-        {
-            fprintf(dmpf, "    Const at %p [%04X bytes]\n", dspPtr(consPtr), consSize);
-        }
-#ifdef JIT32_GCENCODER
-        size_t infoSize = compiler->compInfoBlkSize;
-        if (infoSize)
-            fprintf(dmpf, "    Info  at %p [%04X bytes]\n", dspPtr(infoPtr), infoSize);
-#endif // JIT32_GCENCODER
-
-        fprintf(dmpf, "\n");
-
-        if (codeSize)
-        {
-            hexDump(dmpf, "Code", (BYTE*)*codePtr, codeSize);
-        }
-        if (consSize)
-        {
-            hexDump(dmpf, "Const", (BYTE*)consPtr, consSize);
-        }
-#ifdef JIT32_GCENCODER
-        if (infoSize)
-            hexDump(dmpf, "Info", (BYTE*)infoPtr, infoSize);
-#endif // JIT32_GCENCODER
-
-        fflush(dmpf);
-    }
-
-    if (dmpf != jitstdout())
-    {
-        fclose(dmpf);
-    }
-
-#endif // DEBUG
+    // Create and store the GC info for this method.
+    genCreateAndStoreGCInfo(codeSize, prologSize, epilogSize DEBUGARG(codePtr));
 
     /* Tell the emitter that we're done with this function */
 
diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp
index 690f0d8b160b4a..fa72c8139b9324 100644
--- a/src/coreclr/jit/compiler.cpp
+++ b/src/coreclr/jit/compiler.cpp
@@ -2835,7 +2835,6 @@ void Compiler::compInitOptions(JitFlags* jitFlags)
     opts.dspInstrs       = false;
     opts.dspLines        = false;
     opts.varNames        = false;
-    opts.dmpHex          = false;
     opts.disAsmSpilled   = false;
     opts.disAddr         = false;
     opts.dspCode         = false;
@@ -2847,8 +2846,6 @@ void Compiler::compInitOptions(JitFlags* jitFlags)
     opts.compLongAddress = false;
     opts.optRepeat       = false;
 
-    opts.disAsmHexDumpFile = nullptr;
-
 #ifdef LATE_DISASM
     opts.doLateDisasm = false;
 #endif // LATE_DISASM
@@ -2933,12 +2930,6 @@ void Compiler::compInitOptions(JitFlags* jitFlags)
             opts.doLateDisasm = true;
 #endif // LATE_DISASM
 
-        const WCHAR* disAsmHexDumpFile = JitConfig.JitDisasmHexDumpFile();
-        if (disAsmHexDumpFile != nullptr)
-        {
-            opts.disAsmHexDumpFile = disAsmHexDumpFile;
-        }
-
         // This one applies to both Ngen/Jit Disasm output: DOTNET_JitDasmWithAddress=1
         if (JitConfig.JitDasmWithAddress() != 0)
         {
diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h
index ec50b1b7067e8e..bf68511f1ee268 100644
--- a/src/coreclr/jit/compiler.h
+++ b/src/coreclr/jit/compiler.h
@@ -9705,24 +9705,22 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
         bool disAlignment; // Display alignment boundaries in disassembly code
         bool disCodeBytes; // Display instruction code bytes in disassembly code
 #ifdef DEBUG
-        bool compProcedureSplittingEH;  // Separate cold code from hot code for functions with EH
-        bool dspCode;                   // Display native code generated
-        bool dspEHTable;                // Display the EH table reported to the VM
-        bool dspDebugInfo;              // Display the Debug info reported to the VM
-        bool dspInstrs;                 // Display the IL instructions intermixed with the native code output
-        bool dspLines;                  // Display source-code lines intermixed with native code output
-        bool dmpHex;                    // Display raw bytes in hex of native code output
-        bool varNames;                  // Display variables names in native code output
-        bool disAsmSpilled;             // Display native code when any register spilling occurs
-        bool disasmWithGC;              // Display GC info interleaved with disassembly.
-        bool disAddr;                   // Display process address next to each instruction in disassembly code
-        bool disAsm2;                   // Display native code after it is generated using external disassembler
-        bool dspOrder;                  // Display names of each of the methods that we ngen/jit
-        bool dspUnwind;                 // Display the unwind info output
-        bool compLongAddress;           // Force using large pseudo instructions for long address
-                                        // (IF_LARGEJMP/IF_LARGEADR/IF_LARGLDC)
-        bool dspGCtbls;                 // Display the GC tables
-        const WCHAR* disAsmHexDumpFile; // Writes the raw bytes in hex of native code to the specified file
+        bool compProcedureSplittingEH; // Separate cold code from hot code for functions with EH
+        bool dspCode;                  // Display native code generated
+        bool dspEHTable;               // Display the EH table reported to the VM
+        bool dspDebugInfo;             // Display the Debug info reported to the VM
+        bool dspInstrs;                // Display the IL instructions intermixed with the native code output
+        bool dspLines;                 // Display source-code lines intermixed with native code output
+        bool varNames;                 // Display variables names in native code output
+        bool disAsmSpilled;            // Display native code when any register spilling occurs
+        bool disasmWithGC;             // Display GC info interleaved with disassembly.
+        bool disAddr;                  // Display process address next to each instruction in disassembly code
+        bool disAsm2;                  // Display native code after it is generated using external disassembler
+        bool dspOrder;                 // Display names of each of the methods that we ngen/jit
+        bool dspUnwind;                // Display the unwind info output
+        bool compLongAddress;          // Force using large pseudo instructions for long address
+                                       // (IF_LARGEJMP/IF_LARGEADR/IF_LARGLDC)
+        bool dspGCtbls;                // Display the GC tables
 #endif
 
 // Default numbers used to perform loop alignment. All the numbers are chosen
diff --git a/src/coreclr/jit/jitconfigvalues.h b/src/coreclr/jit/jitconfigvalues.h
index 9e1b1470362956..7c0c69e238c2f8 100644
--- a/src/coreclr/jit/jitconfigvalues.h
+++ b/src/coreclr/jit/jitconfigvalues.h
@@ -677,7 +677,8 @@ CONFIG_STRING(JitFunctionFile, W("JitFunctionFile"))
 #endif // DEBUG
 
 #if defined(DEBUG)
-CONFIG_STRING(JitDisasmHexDumpFile, W("JitDisasmHexDumpFile"))
+CONFIG_METHODSET(JitRawHexCode, W("JitRawHexCode"))
+CONFIG_STRING(JitRawHexCodeFile, W("JitRawHexCodeFile"))
 #endif // DEBUG
 
 #if defined(DEBUG)
diff --git a/src/coreclr/jit/utils.cpp b/src/coreclr/jit/utils.cpp
index 099155e85f0b98..50885fb94da722 100644
--- a/src/coreclr/jit/utils.cpp
+++ b/src/coreclr/jit/utils.cpp
@@ -1319,7 +1319,7 @@ int SimpleSprintf_s(_In_reads_(cbBufSize - (pWriteStart - pBufStart)) char* pWri
 
 #ifdef DEBUG
 
-void hexDump(FILE* dmpf, const char* name, BYTE* addr, size_t size)
+void hexDump(FILE* dmpf, BYTE* addr, size_t size)
 {
     if (!size)
     {
@@ -1328,19 +1328,10 @@ void hexDump(FILE* dmpf, const char* name, BYTE* addr, size_t size)
 
     assert(addr);
 
-    fprintf(dmpf, "Hex dump of %s:\n", name);
-
     for (unsigned i = 0; i < size; i++)
     {
-        if ((i % 16) == 0)
-        {
-            fprintf(dmpf, "\n    %04X: ", i);
-        }
-
-        fprintf(dmpf, "%02X ", *addr++);
+        fprintf(dmpf, "%02X", *addr++);
     }
-
-    fprintf(dmpf, "\n\n");
 }
 
 #endif // DEBUG
diff --git a/src/coreclr/jit/utils.h b/src/coreclr/jit/utils.h
index 747daf9d719d46..1eaa16d67ba81e 100644
--- a/src/coreclr/jit/utils.h
+++ b/src/coreclr/jit/utils.h
@@ -321,7 +321,7 @@ int SimpleSprintf_s(_In_reads_(cbBufSize - (pWriteStart - pBufStart)) char* pWri
                     ...);
 
 #ifdef DEBUG
-void hexDump(FILE* dmpf, const char* name, BYTE* addr, size_t size);
+void hexDump(FILE* dmpf, BYTE* addr, size_t size);
 #endif // DEBUG
 
 /******************************************************************************
diff --git a/src/coreclr/tools/superpmi/superpmi-shim-collector/jithost.cpp b/src/coreclr/tools/superpmi/superpmi-shim-collector/jithost.cpp
index 35610f325f5344..29cfc53e86fc73 100644
--- a/src/coreclr/tools/superpmi/superpmi-shim-collector/jithost.cpp
+++ b/src/coreclr/tools/superpmi/superpmi-shim-collector/jithost.cpp
@@ -86,7 +86,8 @@ bool RecordVariable(const WCHAR* key)
         W("JitInlinePolicyDumpXml"),
         W("JitInlineReplayFile"),
         W("JitFunctionFile")
-        W("JitDisasmHexDumpFile")
+        W("JitRawHexCode"),
+        W("JitRawHexCodeFile")
     };
 
     for (const WCHAR* ignoredVar : s_ignoredVars)

From c01ff8f4daffa35120ff964c86353daed235e05e Mon Sep 17 00:00:00 2001
From: TIHan <lol.tihan@gmail.com>
Date: Fri, 17 Nov 2023 13:57:22 -0800
Subject: [PATCH 3/3] minor cleanup

---
 src/coreclr/jit/codegencommon.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/coreclr/jit/codegencommon.cpp b/src/coreclr/jit/codegencommon.cpp
index e0a56103f8438b..744462af3d7ab0 100644
--- a/src/coreclr/jit/codegencommon.cpp
+++ b/src/coreclr/jit/codegencommon.cpp
@@ -2120,7 +2120,6 @@ void CodeGen::genEmitUnwindDebugGCandEH()
             FILE* dmpf = jitstdout();
 
             fprintf(dmpf, "Generated native code for %s:\n", compiler->info.compFullName);
-            fprintf(dmpf, "\n");
             hexDump(dmpf, addr, codeSize);
             fprintf(dmpf, "\n\n");
         }
