diff --git a/src/coreclr/jit/codegen.h b/src/coreclr/jit/codegen.h index fc9aae292d5e9..214be8247d8c5 100644 --- a/src/coreclr/jit/codegen.h +++ b/src/coreclr/jit/codegen.h @@ -196,7 +196,6 @@ class CodeGen final : public CodeGenInterface void* coldCodePtr; void* consPtr; -#ifdef DEBUG // Last instr we have displayed for dspInstrs unsigned genCurDispOffset; @@ -204,7 +203,6 @@ class CodeGen final : public CodeGenInterface const char* genInsDisplayName(emitter::instrDesc* id); static const char* genSizeStr(emitAttr size); -#endif // DEBUG void genInitialize(); diff --git a/src/coreclr/jit/codegencommon.cpp b/src/coreclr/jit/codegencommon.cpp index 4a575febcf440..bd3396e1ebafc 100644 --- a/src/coreclr/jit/codegencommon.cpp +++ b/src/coreclr/jit/codegencommon.cpp @@ -1740,11 +1740,18 @@ void CodeGen::genGenerateMachineCode() { compiler->opts.disAsm = true; } +#endif compiler->compCurBB = compiler->fgFirstBB; if (compiler->opts.disAsm) { - printf("; Assembly listing for method %s\n", compiler->info.compFullName); +#ifdef DEBUG + const char* fullName = compiler->info.compFullName; +#else + const char* fullName = compiler->eeGetMethodFullName(compiler->info.compMethodHnd); +#endif + + printf("; Assembly listing for method %s\n", fullName); printf("; Emitting "); @@ -1905,7 +1912,6 @@ void CodeGen::genGenerateMachineCode() printf("; invoked as altjit\n"); } } -#endif // DEBUG // We compute the final frame layout before code generation. This is because LSRA // has already computed exactly the maximum concurrent number of spill temps of each type that are @@ -2057,6 +2063,11 @@ void CodeGen::genEmitMachineCode() printf("*************** After end code gen, before unwindEmit()\n"); GetEmitter()->emitDispIGlist(true); } +#else + if (compiler->opts.disAsm) + { + printf("\n; Total bytes of code %d\n\n", codeSize); + } #endif *nativeSizeOfCode = codeSize; diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index 78ad80d23352c..dedf9b1abdc1f 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -2076,10 +2076,6 @@ unsigned char Compiler::compGetJitDefaultFill(Compiler* comp) return defaultFill; } -#endif // DEBUG - -/*****************************************************************************/ -#ifdef DEBUG /*****************************************************************************/ VarName Compiler::compVarName(regNumber reg, bool isFloatReg) @@ -2124,13 +2120,15 @@ VarName Compiler::compVarName(regNumber reg, bool isFloatReg) return nullptr; } +#endif // DEBUG + const char* Compiler::compRegVarName(regNumber reg, bool displayVar, bool isFloatReg) { - #ifdef TARGET_ARM isFloatReg = genIsValidFloatReg(reg); #endif +#ifdef DEBUG if (displayVar && (reg != REG_NA)) { VarName varName = compVarName(reg, isFloatReg); @@ -2148,6 +2146,7 @@ const char* Compiler::compRegVarName(regNumber reg, bool displayVar, bool isFloa return nameVarReg[index]; } } +#endif /* no debug info required or no variable in that register -> return standard name */ @@ -2194,6 +2193,7 @@ const char* Compiler::compRegNameForSize(regNumber reg, size_t size) return sizeNames[reg][size - 1]; } +#ifdef DEBUG const char* Compiler::compLocalVarName(unsigned varNum, unsigned offs) { unsigned i; @@ -2214,9 +2214,8 @@ const char* Compiler::compLocalVarName(unsigned varNum, unsigned offs) return nullptr; } +#endif -/*****************************************************************************/ -#endif // DEBUG /*****************************************************************************/ void Compiler::compSetProcessor() @@ -2819,14 +2818,15 @@ void Compiler::compInitOptions(JitFlags* jitFlags) opts.compJitEarlyExpandMDArrays = (JitConfig.JitEarlyExpandMDArrays() != 0); + opts.disAsm = false; + opts.disDiffable = false; + opts.dspDiffable = false; #ifdef DEBUG opts.dspInstrs = false; opts.dspLines = false; opts.varNames = false; opts.dmpHex = false; - opts.disAsm = false; opts.disAsmSpilled = false; - opts.disDiffable = false; opts.disAddr = false; opts.disAlignment = false; opts.dspCode = false; @@ -3069,8 +3069,17 @@ void Compiler::compInitOptions(JitFlags* jitFlags) } s_pJitFunctionFileInitialized = true; } - -#endif // DEBUG +#else // DEBUG + if (!JitConfig.JitDisasm().isEmpty()) + { + const char* methodName = info.compCompHnd->getMethodName(info.compMethodHnd, nullptr); + const char* className = info.compCompHnd->getClassName(info.compClassHnd); + if (JitConfig.JitDisasm().contains(methodName, className, &info.compMethodInfo->args)) + { + opts.disAsm = true; + } + } +#endif // !DEBUG //------------------------------------------------------------------------- @@ -6732,6 +6741,7 @@ int Compiler::compCompileHelper(CORINFO_MODULE_HANDLE classPtr, } #endif + compMethodID = 0; #ifdef DEBUG /* Give the function a unique number */ diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 2bfa7d81c8468..1f56235633e5c 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -9170,6 +9170,9 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX bool optRepeat; // Repeat optimizer phases k times #endif + bool disAsm; // Display native code as it is generated + bool dspDiffable; // Makes the Jit Dump 'diff-able' (currently uses same COMPlus_* flag as disDiffable) + bool disDiffable; // Makes the Disassembly code 'diff-able' #ifdef DEBUG bool compProcedureSplittingEH; // Separate cold code from hot code for functions with EH bool dspCode; // Display native code generated @@ -9179,19 +9182,16 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 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 disAsm; // Display native code as it is generated bool disAsmSpilled; // Display native code when any register spilling occurs bool disasmWithGC; // Display GC info interleaved with disassembly. - bool disDiffable; // Makes the Disassembly code 'diff-able' bool disAddr; // Display process address next to each instruction in disassembly code bool disAlignment; // Display alignment boundaries 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 dspDiffable; // Makes the Jit Dump 'diff-able' (currently uses same COMPlus_* flag as disDiffable) - bool compLongAddress; // Force using large pseudo instructions for long address - // (IF_LARGEJMP/IF_LARGEADR/IF_LARGLDC) - bool dspGCtbls; // Display the GC tables + bool compLongAddress; // Force using large pseudo instructions for long address + // (IF_LARGEJMP/IF_LARGEADR/IF_LARGLDC) + bool dspGCtbls; // Display the GC tables #endif bool compExpandCallsEarly; // True if we should expand virtual call targets early for this method @@ -9296,9 +9296,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX static bool s_pJitFunctionFileInitialized; static MethodSet* s_pJitMethodSet; -#endif // DEBUG -#ifdef DEBUG // silence warning of cast to greater size. It is easier to silence than construct code the compiler is happy with, and // it is safe in this case #pragma warning(push) @@ -9316,6 +9314,24 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX return (o == ZERO) ? ZERO : (opts.dspDiffable ? T(0xD1FFAB1E) : o); } #pragma warning(pop) +#else +#pragma warning(push) +#pragma warning(disable : 4312) + template + T dspPtr(T p) + { + return p; + } + + template + T dspOffset(T o) + { + return o; + } +#pragma warning(pop) +#endif + +#ifdef DEBUG static int dspTreeID(GenTree* tree) { @@ -9788,11 +9804,11 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX public: #ifdef DEBUG - LONG compMethodID; unsigned compGenTreeID; unsigned compStatementID; unsigned compBasicBlockID; #endif + LONG compMethodID; BasicBlock* compCurBB; // the current basic block in process Statement* compCurStmt; // the current statement in process @@ -10000,12 +10016,12 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX const char* compLocalVarName(unsigned varNum, unsigned offs); VarName compVarName(regNumber reg, bool isFloatReg = false); - const char* compRegVarName(regNumber reg, bool displayVar = false, bool isFloatReg = false); - const char* compRegNameForSize(regNumber reg, size_t size); const char* compFPregVarName(unsigned fpReg, bool displayVar = false); void compDspSrcLinesByNativeIP(UNATIVE_OFFSET curIP); void compDspSrcLinesByLineNum(unsigned line, bool seek = false); #endif // DEBUG + const char* compRegNameForSize(regNumber reg, size_t size); + const char* compRegVarName(regNumber reg, bool displayVar = false, bool isFloatReg = false); //------------------------------------------------------------------------- diff --git a/src/coreclr/jit/emit.cpp b/src/coreclr/jit/emit.cpp index 430b9ec8e2b89..b9130fa443efd 100644 --- a/src/coreclr/jit/emit.cpp +++ b/src/coreclr/jit/emit.cpp @@ -104,8 +104,6 @@ void emitLocation::Print(LONG compMethodID) const * Return the name of an instruction format. */ -#if defined(DEBUG) || EMITTER_STATS - const char* emitter::emitIfName(unsigned f) { static const char* const ifNames[] = { @@ -124,8 +122,6 @@ const char* emitter::emitIfName(unsigned f) return errBuff; } -#endif - /*****************************************************************************/ #if EMITTER_STATS @@ -619,8 +615,13 @@ unsigned emitLclVarAddr::lvaOffset() // returns the offset into the variable to void emitter::emitBegCG(Compiler* comp, COMP_HANDLE cmpHandle) { - emitComp = comp; - emitCmpHandle = cmpHandle; + emitComp = comp; + emitCmpHandle = cmpHandle; + m_debugInfoSize = sizeof(instrDescDebugInfo*); +#ifndef DEBUG + if (!comp->opts.disAsm) + m_debugInfoSize = 0; +#endif } void emitter::emitEndCG() @@ -675,7 +676,8 @@ void emitter::emitGenIG(insGroup* ig) if (emitCurIGfreeBase == nullptr) { - emitIGbuffSize = SC_IG_BUFFER_SIZE; + emitIGbuffSize = (SC_IG_BUFFER_NUM_SMALL_DESCS * (SMALL_IDSC_SIZE + m_debugInfoSize)) + + (SC_IG_BUFFER_NUM_LARGE_DESCS * (sizeof(emitter::instrDesc) + m_debugInfoSize)); emitCurIGfreeBase = (BYTE*)emitGetMem(emitIGbuffSize); } @@ -1363,14 +1365,14 @@ void emitter::appendToCurIG(instrDesc* id) * Display (optionally) an instruction offset. */ -#ifdef DEBUG - void emitter::emitDispInsAddr(BYTE* code) { +#ifdef DEBUG if (emitComp->opts.disAddr) { printf(FMT_ADDR, DBG_ADDR(code)); } +#endif } void emitter::emitDispInsOffs(unsigned offs, bool doffs) @@ -1385,8 +1387,6 @@ void emitter::emitDispInsOffs(unsigned offs, bool doffs) } } -#endif // DEBUG - #ifdef JIT32_GCENCODER /***************************************************************************** @@ -1481,15 +1481,17 @@ void* emitter::emitAllocAnyInstr(size_t sz, emitAttr opsz) // Make sure we have enough space for the new instruction. // `igInsCnt` is currently a byte, so we can't have more than 255 instructions in a single insGroup. - if ((emitCurIGfreeNext + sz >= emitCurIGfreeEndp) || emitForceNewIG || (emitCurIGinsCnt >= 255)) + size_t fullSize = sz + m_debugInfoSize; + + if ((emitCurIGfreeNext + fullSize >= emitCurIGfreeEndp) || emitForceNewIG || (emitCurIGinsCnt >= 255)) { emitNxtIG(true); } /* Grab the space for the instruction */ - emitLastIns = id = (instrDesc*)emitCurIGfreeNext; - emitCurIGfreeNext += sz; + emitLastIns = id = (instrDesc*)(emitCurIGfreeNext + m_debugInfoSize); + emitCurIGfreeNext += fullSize; assert(sz >= sizeof(void*)); memset(id, 0, sz); @@ -1512,23 +1514,19 @@ void* emitter::emitAllocAnyInstr(size_t sz, emitAttr opsz) emitInsCount++; -#if defined(DEBUG) - /* In debug mode we clear/set some additional fields */ - - instrDescDebugInfo* info = (instrDescDebugInfo*)emitGetMem(sizeof(*info)); - - info->idNum = emitInsCount; - info->idSize = sz; - info->idVarRefOffs = 0; - info->idMemCookie = 0; - info->idFlags = GTF_EMPTY; - info->idFinallyCall = false; - info->idCatchRet = false; - info->idCallSig = nullptr; - - id->idDebugOnlyInfo(info); - -#endif // defined(DEBUG) + if (m_debugInfoSize > 0) + { + instrDescDebugInfo* info = (instrDescDebugInfo*)emitGetMem(sizeof(*info)); + info->idNum = emitInsCount; + info->idSize = sz; + info->idVarRefOffs = 0; + info->idMemCookie = 0; + info->idFlags = GTF_EMPTY; + info->idFinallyCall = false; + info->idCatchRet = false; + info->idCallSig = nullptr; + id->idDebugOnlyInfo(info); + } /* Store the size and handle the two special values that indicate GCref and ByRef */ @@ -2638,8 +2636,6 @@ void* emitter::emitAddInlineLabel() return emitCurIG; } -#ifdef DEBUG - //----------------------------------------------------------------------------- // emitPrintLabel: Print the assembly label for an insGroup. We could use emitter::emitLabelString() // to be consistent, but that seems silly. @@ -2670,8 +2666,6 @@ const char* emitter::emitLabelString(insGroup* ig) return retbuf; } -#endif // DEBUG - #if defined(TARGET_ARMARCH) || defined(TARGET_LOONGARCH64) // Does the argument location point to an IG at the end of a function or funclet? @@ -2845,12 +2839,12 @@ void emitter::emitGetInstrDescs(insGroup* ig, instrDesc** id, int* insCnt) assert(!(ig->igFlags & IGF_PLACEHOLDER)); if (ig == emitCurIG) { - *id = (instrDesc*)emitCurIGfreeBase; + *id = emitFirstInstrDesc(emitCurIGfreeBase); *insCnt = emitCurIGinsCnt; } else { - *id = (instrDesc*)ig->igData; + *id = emitFirstInstrDesc(ig->igData); *insCnt = ig->igInsCnt; } @@ -2939,7 +2933,7 @@ bool emitter::emitGetLocationInfo(emitLocation* emitLoc, int i; for (i = 0; i != insNum; ++i) { - castto(id, BYTE*) += emitSizeOfInsDsc(id); + emitAdvanceInstrDesc(&id, emitSizeOfInsDsc(id)); } // Return the info we found @@ -2967,7 +2961,7 @@ bool emitter::emitNextID(insGroup*& ig, instrDesc*& id, int& insRemaining) { if (insRemaining > 0) { - castto(id, BYTE*) += emitSizeOfInsDsc(id); + emitAdvanceInstrDesc(&id, emitSizeOfInsDsc(id)); --insRemaining; return true; } @@ -3809,7 +3803,7 @@ void emitter::emitDispIG(insGroup* ig, insGroup* igPrev, bool verbose) if (verbose) { - BYTE* ins = ig->igData; + instrDesc* id = emitFirstInstrDesc(ig->igData); UNATIVE_OFFSET ofs = ig->igOffs; unsigned cnt = ig->igInsCnt; @@ -3819,8 +3813,6 @@ void emitter::emitDispIG(insGroup* ig, insGroup* igPrev, bool verbose) do { - instrDesc* id = (instrDesc*)ins; - #ifdef TARGET_XARCH if (emitJmpInstHasNoCode(id)) { @@ -3833,8 +3825,8 @@ void emitter::emitDispIG(insGroup* ig, insGroup* igPrev, bool verbose) #endif emitDispIns(id, false, true, false, ofs, nullptr, 0, ig); - ins += emitSizeOfInsDsc(id); ofs += id->idCodeSize(); + emitAdvanceInstrDesc(&id, emitSizeOfInsDsc(id)); } while (--cnt); @@ -3928,6 +3920,38 @@ void emitter::emitDispJumpList() #endif // DEBUG +//------------------------------------------------------------------------ +// emitAdvanceInstrDesc: +// Advance to the next instrDesc in the buffer of instrDescs, taking optional +// debug info into account. +// +// Parameters: +// id - the pointer to the current instrDesc +// idSize - the size of the current instrDesc +// +void emitter::emitAdvanceInstrDesc(instrDesc** id, size_t idSize) +{ + assert(idSize == emitSizeOfInsDsc(*id)); + char* idData = reinterpret_cast(*id); + *id = reinterpret_cast(idData + idSize + m_debugInfoSize); +} + +//------------------------------------------------------------------------ +// emitFirstInstrDesc: +// Given a pointer to an instruction desc buffer, return a pointer to the +// first instrDesc taking optional debug info into account. +// +// Parameters: +// idData - the data +// +// Returns: +// A pointer to the first instrDesc. +// +emitter::instrDesc* emitter::emitFirstInstrDesc(BYTE* idData) +{ + return reinterpret_cast(idData + m_debugInfoSize); +} + /***************************************************************************** * * Issue the given instruction. Basically, this is just a thin wrapper around @@ -4068,7 +4092,6 @@ void emitter::emitRecomputeIGoffsets() // void emitter::emitDispCommentForHandle(size_t handle, size_t cookie, GenTreeFlags flag) { -#ifdef DEBUG #ifdef TARGET_XARCH const char* commentPrefix = " ;"; #else @@ -4107,6 +4130,7 @@ void emitter::emitDispCommentForHandle(size_t handle, size_t cookie, GenTreeFlag const char* str = nullptr; if (flag == GTF_ICON_STR_HDL) { +#ifdef DEBUG const WCHAR* wstr = emitComp->eeGetCPString(handle); // NOTE: eGetCPString always returns nullptr on Linux/ARM if (wstr == nullptr) @@ -4139,6 +4163,9 @@ void emitter::emitDispCommentForHandle(size_t handle, size_t cookie, GenTreeFlag } printf("%s \"%S\"", commentPrefix, buf); } +#else + str = "string handle"; +#endif } else if (flag == GTF_ICON_CLASS_HDL) { @@ -4177,7 +4204,6 @@ void emitter::emitDispCommentForHandle(size_t handle, size_t cookie, GenTreeFlag { printf("%s %s", commentPrefix, str); } -#endif // DEBUG } //**************************************************************************** @@ -4247,15 +4273,10 @@ void emitter::emitRemoveJumpToNextInst() #ifdef DEBUG unsigned instructionCount = jmpGroup->igInsCnt; assert(instructionCount > 0); - instrDesc* id = nullptr; + instrDesc* id = emitFirstInstrDesc(jmpGroup->igData); + for (unsigned i = 0; i < instructionCount - 1; i++) { - BYTE* dataPtr = jmpGroup->igData; - while (instructionCount > 0) - { - id = (instrDesc*)dataPtr; - dataPtr += emitSizeOfInsDsc(id); - instructionCount -= 1; - } + emitAdvanceInstrDesc(&id, emitSizeOfInsDsc(id)); } assert(id != nullptr); if (jmp != id) @@ -4272,12 +4293,12 @@ void emitter::emitRemoveJumpToNextInst() emitDispIG(targetGroup, nullptr, false); assert(jmp == id); } -#endif // DEBUG JITDUMP("IG%02u IN%04x is the last instruction in the group and jumps to the next instruction group " "IG%02u %s, removing.\n", jmpGroup->igNum, jmp->idDebugOnlyInfo()->idNum, targetGroup->igNum, emitLabelString(targetGroup)); +#endif // DEBUG // Unlink the jump from emitJumpList while keeping the previousJmp the same. if (previousJmp != nullptr) @@ -5168,7 +5189,7 @@ void emitter::emitJumpDistBind() // void emitter::emitCheckAlignFitInCurIG(unsigned nAlignInstr) { - unsigned instrDescSize = nAlignInstr * sizeof(instrDescAlign); + size_t instrDescSize = nAlignInstr * (m_debugInfoSize + sizeof(instrDescAlign)); // Ensure that all align instructions fall in same IG. if (emitCurIGfreeNext + instrDescSize >= emitCurIGfreeEndp) @@ -6653,7 +6674,7 @@ unsigned emitter::emitEndCodeGen(Compiler* comp, // if it were the instruction following a call. emitGenGCInfoIfFuncletRetTarget(ig, cp); - instrDesc* id = (instrDesc*)ig->igData; + instrDesc* id = emitFirstInstrDesc(ig->igData); #ifdef DEBUG /* Print the IG label, but only if it is a branch label */ @@ -6675,7 +6696,17 @@ unsigned emitter::emitEndCodeGen(Compiler* comp, printf("\n"); } } -#endif // DEBUG +#else // DEBUG + if (emitComp->opts.disAsm) + { + printf("\n%s:", emitLabelString(ig)); + if (!emitComp->opts.disDiffable) + { + printf(" ;; offset=%04XH", emitCurCodeOffs(cp)); + } + printf("\n"); + } +#endif // !DEBUG BYTE* bp = cp; @@ -6819,7 +6850,8 @@ unsigned emitter::emitEndCodeGen(Compiler* comp, #endif - castto(id, BYTE*) += emitIssue1Instr(ig, id, &cp); + size_t insSize = emitIssue1Instr(ig, id, &cp); + emitAdvanceInstrDesc(&id, insSize); #ifdef DEBUG // Print the alignment boundary @@ -6916,7 +6948,13 @@ unsigned emitter::emitEndCodeGen(Compiler* comp, ig->igPerfScore); } *instrCount += ig->igInsCnt; -#endif // DEBUG +#else // DEBUG + if (emitComp->opts.disAsm) + { + // Separate IGs with a blank line + printf(" "); + } +#endif // !DEBUG emitCurIG = nullptr; @@ -7179,7 +7217,7 @@ void emitter::emitGenGCInfoIfFuncletRetTarget(insGroup* ig, BYTE* cp) unsigned emitter::emitFindInsNum(insGroup* ig, instrDesc* idMatch) { - instrDesc* id = (instrDesc*)ig->igData; + instrDesc* id = emitFirstInstrDesc(ig->igData); // Check if we are the first instruction in the group if (id == idMatch) @@ -7193,7 +7231,7 @@ unsigned emitter::emitFindInsNum(insGroup* ig, instrDesc* idMatch) while (insRemaining > 0) { - castto(id, BYTE*) += emitSizeOfInsDsc(id); + emitAdvanceInstrDesc(&id, emitSizeOfInsDsc(id)); insNum++; insRemaining--; @@ -7215,7 +7253,7 @@ unsigned emitter::emitFindInsNum(insGroup* ig, instrDesc* idMatch) UNATIVE_OFFSET emitter::emitFindOffset(insGroup* ig, unsigned insNum) { - instrDesc* id = (instrDesc*)ig->igData; + instrDesc* id = emitFirstInstrDesc(ig->igData); UNATIVE_OFFSET of = 0; #ifdef DEBUG @@ -7230,7 +7268,7 @@ UNATIVE_OFFSET emitter::emitFindOffset(insGroup* ig, unsigned insNum) { of += id->idCodeSize(); - castto(id, BYTE*) += emitSizeOfInsDsc(id); + emitAdvanceInstrDesc(&id, emitSizeOfInsDsc(id)); insNum--; } @@ -7694,14 +7732,14 @@ void emitter::emitOutputDataSec(dataSecDsc* sec, BYTE* dst) printf("\nEmitting data sections: %u total bytes\n", sec->dsdOffs); } + unsigned secNum = 0; +#endif + if (emitComp->opts.disAsm) { emitDispDataSec(sec, dst); } - unsigned secNum = 0; -#endif - assert(dst); assert(sec->dsdOffs); assert(sec->dsdList); @@ -7810,8 +7848,6 @@ void emitter::emitOutputDataSec(dataSecDsc* sec, BYTE* dst) } } -#ifdef DEBUG - //------------------------------------------------------------------------ // emitDispDataSec: Dump a data section to stdout. // @@ -7832,10 +7868,12 @@ void emitter::emitDispDataSec(dataSecDsc* section, BYTE* dst) for (dataSection* data = section->dsdList; data != nullptr; data = data->dsNext) { +#ifdef DEBUG if (emitComp->opts.disAddr) { printf("; @" FMT_ADDR "\n", DBG_ADDR(dst)); } +#endif const char* labelFormat = "%-7s"; char label[64]; @@ -7937,7 +7975,7 @@ void emitter::emitDispDataSec(dataSecDsc* section, BYTE* dst) { case TYP_FLOAT: assert(data->dsSize >= 4); - printf("\tdd\t%08llXh\t", *reinterpret_cast(&data->dsCont[i])); + printf("\tdd\t%08llXh\t", (UINT64) * reinterpret_cast(&data->dsCont[i])); printf("\t; %9.6g", *reinterpret_cast(&data->dsCont[i])); i += 4; break; @@ -8012,7 +8050,6 @@ void emitter::emitDispDataSec(dataSecDsc* section, BYTE* dst) } } } -#endif /*****************************************************************************/ /***************************************************************************** diff --git a/src/coreclr/jit/emit.h b/src/coreclr/jit/emit.h index 658da7d577564..c5d245ba83c66 100644 --- a/src/coreclr/jit/emit.h +++ b/src/coreclr/jit/emit.h @@ -461,6 +461,8 @@ class emitter GCInfo* gcInfo; CodeGen* codeGen; + size_t m_debugInfoSize; + typedef GCInfo::varPtrDsc varPtrDsc; typedef GCInfo::regPtrDsc regPtrDsc; typedef GCInfo::CallDsc callDsc; @@ -554,8 +556,6 @@ class emitter #endif // TARGET_XARCH -#ifdef DEBUG // This information is used in DEBUG builds for additional diagnostics - struct instrDesc; struct instrDescDebugInfo @@ -570,8 +570,6 @@ class emitter CORINFO_SIG_INFO* idCallSig; // Used to report native call site signatures to the EE }; -#endif // DEBUG - #ifdef TARGET_ARM unsigned insEncodeSetFlags(insFlags sf); @@ -624,6 +622,8 @@ class emitter #endif public: + instrDesc() = delete; // Do not stack alloc this due to debug info that has to come before it. + instruction idIns() const { return _idIns; @@ -810,52 +810,35 @@ class emitter //////////////////////////////////////////////////////////////////////// CLANG_FORMAT_COMMENT_ANCHOR; -#ifdef DEBUG - - instrDescDebugInfo* _idDebugOnlyInfo; - public: instrDescDebugInfo* idDebugOnlyInfo() const { - return _idDebugOnlyInfo; + const char* addr = reinterpret_cast(this); + return *reinterpret_cast(addr - sizeof(instrDescDebugInfo*)); } void idDebugOnlyInfo(instrDescDebugInfo* info) { - _idDebugOnlyInfo = info; + char* addr = reinterpret_cast(this); + *reinterpret_cast(addr - sizeof(instrDescDebugInfo*)) = info; } private: -#endif // DEBUG - CLANG_FORMAT_COMMENT_ANCHOR; // -// This is the end of the 'small' instrDesc which is the same on all -// platforms (except 64-bit DEBUG which is a little bigger). -// Non-DEBUG sizes: -// x86/amd64/arm/arm64: 64 bits -// DEBUG sizes (includes one pointer): +// This is the end of the 'small' instrDesc which is the same on all platforms +// Sizes (includes one pointer): // x86: 2 DWORDs, 96 bits // amd64: 4 DWORDs, 128 bits // arm: 3 DWORDs, 96 bits // arm64: 4 DWORDs, 128 bits -// There should no padding or alignment issues on any platform or -// configuration (including DEBUG which has 1 extra pointer). +// There should no padding or alignment issues on any platform or configuration. // +// If you add lots more fields that need to be cleared (such +// as various flags), you might need to update the body of +// emitter::emitAllocInstr() to clear them. -/* - If you add lots more fields that need to be cleared (such - as various flags), you might need to update the body of - emitter::emitAllocInstr() to clear them. - */ - -#if DEBUG -#define SMALL_IDSC_DEBUG_EXTRA (sizeof(void*)) -#else -#define SMALL_IDSC_DEBUG_EXTRA (0) -#endif - -#define SMALL_IDSC_SIZE (8 + SMALL_IDSC_DEBUG_EXTRA) +#define SMALL_IDSC_SIZE 8 void checkSizes(); @@ -1528,6 +1511,8 @@ class emitter struct instrDescJmp : instrDesc { + instrDescJmp() = delete; + instrDescJmp* idjNext; // next jump in the group/method insGroup* idjIG; // containing group @@ -1555,6 +1540,8 @@ class emitter #if FEATURE_LOOP_ALIGN struct instrDescAlign : instrDesc { + instrDescAlign() = delete; + instrDescAlign* idaNext; // next align in the group/method insGroup* idaIG; // containing group insGroup* idaLoopHeadPredIG; // The IG before the loop IG. @@ -1590,16 +1577,22 @@ class emitter struct instrDescCns : instrDesc // large const { + instrDescCns() = delete; + cnsval_ssize_t idcCnsVal; }; struct instrDescDsp : instrDesc // large displacement { + instrDescDsp() = delete; + target_ssize_t iddDspVal; }; struct instrDescCnsDsp : instrDesc // large cons + disp { + instrDescCnsDsp() = delete; + target_ssize_t iddcCnsVal; int iddcDspVal; }; @@ -1608,11 +1601,15 @@ class emitter struct instrDescAmd : instrDesc // large addrmode disp { + instrDescAmd() = delete; + ssize_t idaAmdVal; }; struct instrDescCnsAmd : instrDesc // large cons + addrmode disp { + instrDescCnsAmd() = delete; + ssize_t idacCnsVal; ssize_t idacAmdVal; }; @@ -1621,6 +1618,8 @@ class emitter struct instrDescCGCA : instrDesc // call with ... { + instrDescCGCA() = delete; + VARSET_TP idcGCvars; // ... updated GC vars or ssize_t idcDisp; // ... big addrmode disp regMaskTP idcGcrefRegs; // ... gcref registers @@ -1650,10 +1649,33 @@ class emitter #endif // MULTIREG_HAS_SECOND_GC_RET }; + // TODO-Cleanup: Uses of stack-allocated instrDescs should be refactored to be unnecessary. + template + struct inlineInstrDesc + { + private: + instrDescDebugInfo* idDebugInfo; + alignas(alignof(T)) char idStorage[sizeof(T)]; + + public: + inlineInstrDesc() : idDebugInfo(nullptr), idStorage() + { + static_assert_no_msg((offsetof(inlineInstrDesc, idStorage) - sizeof(instrDescDebugInfo*)) == + offsetof(inlineInstrDesc, idDebugInfo)); + } + + T* id() + { + return reinterpret_cast(idStorage); + } + }; + #ifdef TARGET_ARM struct instrDescReloc : instrDesc { + instrDescReloc() = delete; + BYTE* idrRelocVal; }; @@ -1681,9 +1703,7 @@ class emitter ssize_t emitGetInsCIdisp(instrDesc* id); unsigned emitGetInsCIargs(instrDesc* id); -#ifdef DEBUG inline static emitAttr emitGetMemOpSize(instrDesc* id); -#endif // DEBUG // Return the argument count for a direct call "id". int emitGetInsCDinfo(instrDesc* id); @@ -1693,19 +1713,17 @@ class emitter cnsval_ssize_t emitGetInsSC(instrDesc* id); unsigned emitInsCount; -/************************************************************************/ -/* A few routines used for debug display purposes */ -/************************************************************************/ - -#if defined(DEBUG) || EMITTER_STATS + /************************************************************************/ + /* A few routines used for debug display purposes */ + /************************************************************************/ static const char* emitIfName(unsigned f); -#endif // defined(DEBUG) || EMITTER_STATS - #ifdef DEBUG - unsigned emitVarRefOffs; +#else // !DEBUG +#define emitVarRefOffs 0 +#endif // !DEBUG const char* emitRegName(regNumber reg, emitAttr size = EA_PTRSIZE, bool varName = true); const char* emitFloatRegName(regNumber reg, emitAttr size = EA_PTRSIZE, bool varName = true); @@ -1747,10 +1765,6 @@ class emitter size_t sz = 0, insGroup* ig = nullptr); -#else // !DEBUG -#define emitVarRefOffs 0 -#endif // !DEBUG - /************************************************************************/ /* Method prolog and epilog */ /************************************************************************/ @@ -1913,6 +1927,8 @@ class emitter unsigned int emitCounts_INS_OPTS_J; #endif // TARGET_LOONGARCH64 + instrDesc* emitFirstInstrDesc(BYTE* idData); + void emitAdvanceInstrDesc(instrDesc** id, size_t idSize); size_t emitIssue1Instr(insGroup* ig, instrDesc* id, BYTE** dp); size_t emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp); @@ -1994,10 +2010,12 @@ class emitter // movk xip1, #2 LSL #16 // ldr w8, [fp, xip1] // [V10 arg10] // which eats up our insGroup buffer. -#define SC_IG_BUFFER_SIZE (200 * sizeof(emitter::instrDesc)) +#define SC_IG_BUFFER_NUM_SMALL_DESCS 0 +#define SC_IG_BUFFER_NUM_LARGE_DESCS 200 #else -#define SC_IG_BUFFER_SIZE (50 * sizeof(emitter::instrDesc) + 14 * SMALL_IDSC_SIZE) +#define SC_IG_BUFFER_NUM_SMALL_DESCS 14 +#define SC_IG_BUFFER_NUM_LARGE_DESCS 50 #endif // !(TARGET_ARMARCH || TARGET_LOONGARCH64) size_t emitIGbuffSize; @@ -2184,10 +2202,8 @@ class emitter // continues to track GC info as if there was no label. void* emitAddInlineLabel(); -#ifdef DEBUG void emitPrintLabel(insGroup* ig); const char* emitLabelString(insGroup* ig); -#endif #if defined(TARGET_ARMARCH) || defined(TARGET_LOONGARCH64) @@ -2559,9 +2575,7 @@ class emitter dataSection* emitDataSecCur; void emitOutputDataSec(dataSecDsc* sec, BYTE* dst); -#ifdef DEBUG void emitDispDataSec(dataSecDsc* section, BYTE* dst); -#endif /************************************************************************/ /* Handles to the current class and method. */ @@ -2712,9 +2726,6 @@ class emitter inline void emitter::instrDesc::checkSizes() { -#ifdef DEBUG - C_ASSERT(SMALL_IDSC_SIZE == (offsetof(instrDesc, _idDebugOnlyInfo) + sizeof(instrDescDebugInfo*))); -#endif C_ASSERT(SMALL_IDSC_SIZE == offsetof(instrDesc, _idAddrUnion)); } @@ -3109,7 +3120,6 @@ inline unsigned emitter::emitGetInsCIargs(instrDesc* id) } } -#ifdef DEBUG //----------------------------------------------------------------------------- // emitGetMemOpSize: Get the memory operand size of instrDesc. // @@ -3277,7 +3287,6 @@ inline unsigned emitter::emitGetInsCIargs(instrDesc* id) } } } -#endif // DEBUG #endif // TARGET_XARCH diff --git a/src/coreclr/jit/emitarm.cpp b/src/coreclr/jit/emitarm.cpp index 5e172a0914a6d..c474fc3d1324c 100644 --- a/src/coreclr/jit/emitarm.cpp +++ b/src/coreclr/jit/emitarm.cpp @@ -644,8 +644,6 @@ bool emitter::emitInsMayWriteMultipleRegs(instrDesc* id) } } -/*****************************************************************************/ -#ifdef DEBUG /***************************************************************************** * * Return a string that represents the given register. @@ -672,7 +670,6 @@ const char* emitter::emitFloatRegName(regNumber reg, emitAttr attr, bool varName return rn; } -#endif // DEBUG /***************************************************************************** * @@ -4839,10 +4836,13 @@ void emitter::emitIns_Call(EmitCallType callType, VarSetOps::ToString(emitComp, ((instrDescCGCA*)id)->idcGCvars)); } } +#endif - id->idDebugOnlyInfo()->idMemCookie = (size_t)methHnd; // method token - id->idDebugOnlyInfo()->idCallSig = sigInfo; -#endif // DEBUG + if (m_debugInfoSize > 0) + { + INDEBUG(id->idDebugOnlyInfo()->idCallSig = sigInfo); + id->idDebugOnlyInfo()->idMemCookie = (size_t)methHnd; // method token + } #ifdef LATE_DISASM if (addr != nullptr) @@ -6696,6 +6696,13 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) { emitDispGCInfoDelta(); } +#else + if (emitComp->opts.disAsm) + { + size_t expected = emitSizeOfInsDsc(id); + assert(sz == expected); + emitDispIns(id, false, 0, true, emitCurCodeOffs(odst), *dp, (dst - *dp), ig); + } #endif /* All instructions are expected to generate code */ @@ -6710,8 +6717,6 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) /*****************************************************************************/ /*****************************************************************************/ -#ifdef DEBUG - static bool insAlwaysSetFlags(instruction ins) { bool result = false; @@ -7096,6 +7101,7 @@ void emitter::emitDispInsHex(instrDesc* id, BYTE* code, size_t sz) void emitter::emitDispInsHelp( instrDesc* id, bool isNew, bool doffs, bool asmfm, unsigned offset, BYTE* code, size_t sz, insGroup* ig) { +#ifdef DEBUG if (EMITVERBOSE) { unsigned idNum = id->idDebugOnlyInfo()->idNum; // Do not remove this! It is needed for VisualStudio @@ -7103,6 +7109,7 @@ void emitter::emitDispInsHelp( printf("IN%04x: ", idNum); } +#endif if (code == NULL) sz = 0; @@ -7645,7 +7652,7 @@ void emitter::emitDispInsHelp( UNATIVE_OFFSET srcOffs = ig->igOffs + emitFindOffset(ig, insNum + 1); UNATIVE_OFFSET dstOffs = ig->igOffs + emitFindOffset(ig, insNum + 1 + instrCount); ssize_t relOffs = (ssize_t)(emitOffsetToPtr(dstOffs) - emitOffsetToPtr(srcOffs)); - printf("pc%s%d (%d instructions)", (relOffs >= 0) ? "+" : "", relOffs, instrCount); + printf("pc%s%d (%d instructions)", (relOffs >= 0) ? "+" : "", (int)relOffs, (int)instrCount); } } else if (id->idIsBound()) @@ -7689,10 +7696,8 @@ void emitter::emitDispLargeJmp( // Note: don't touch the actual instrDesc. If we accidentally messed it up, it would create a very // difficult to find bug. - instrDescJmp idJmp; - instrDescJmp* pidJmp = &idJmp; - - memset(&idJmp, 0, sizeof(idJmp)); + inlineInstrDesc idJmp; + instrDescJmp* pidJmp = idJmp.id(); pidJmp->idIns(emitJumpKindToIns(emitReverseJumpKind(emitInsToJumpKind(id->idIns())))); // reverse the // conditional @@ -7785,6 +7790,7 @@ void emitter::emitDispIns( void emitter::emitDispFrameRef(int varx, int disp, int offs, bool asmfm) { +#ifdef DEBUG printf("["); if (varx < 0) @@ -7815,10 +7821,9 @@ void emitter::emitDispFrameRef(int varx, int disp, int offs, bool asmfm) printf("'"); } } +#endif } -#endif // DEBUG - void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataReg, GenTreeIndir* indir) { // Handle unaligned floating point loads/stores diff --git a/src/coreclr/jit/emitarm.h b/src/coreclr/jit/emitarm.h index 5640e8077a31f..e1c281a6fccf1 100644 --- a/src/coreclr/jit/emitarm.h +++ b/src/coreclr/jit/emitarm.h @@ -27,8 +27,6 @@ unsigned emitOutput_Thumb2Instr(BYTE* dst, code_t code); /* Debug-only routines to display instructions */ /************************************************************************/ -#ifdef DEBUG - void emitDispInst(instruction ins, insFlags flags); void emitDispImm(int imm, bool addComma, bool alwaysHex = false); void emitDispReloc(BYTE* addr); @@ -61,8 +59,6 @@ void emitDispInsHelp(instrDesc* id, size_t sz = 0, insGroup* ig = NULL); -#endif // DEBUG - /************************************************************************/ /* Private members that deal with target-dependent instr. descriptors */ /************************************************************************/ diff --git a/src/coreclr/jit/emitarm64.cpp b/src/coreclr/jit/emitarm64.cpp index fbc72a53d54fa..f4e5896bdb533 100644 --- a/src/coreclr/jit/emitarm64.cpp +++ b/src/coreclr/jit/emitarm64.cpp @@ -1269,7 +1269,6 @@ emitAttr emitter::emitInsLoadStoreSize(instrDesc* id) } /*****************************************************************************/ -#ifdef DEBUG // clang-format off static const char * const xRegNames[] = @@ -1392,8 +1391,6 @@ const char* emitter::emitVectorRegName(regNumber reg) return vRegNames[index]; } -#endif // DEBUG - /***************************************************************************** * * Returns the base encoding of the given CPU instruction. @@ -8703,10 +8700,13 @@ void emitter::emitIns_Call(EmitCallType callType, VarSetOps::ToString(emitComp, ((instrDescCGCA*)id)->idcGCvars)); } } +#endif - id->idDebugOnlyInfo()->idMemCookie = (size_t)methHnd; // method token - id->idDebugOnlyInfo()->idCallSig = sigInfo; -#endif // DEBUG + if (m_debugInfoSize > 0) + { + INDEBUG(id->idDebugOnlyInfo()->idCallSig = sigInfo); + id->idDebugOnlyInfo()->idMemCookie = (size_t)methHnd; // method token + } #ifdef LATE_DISASM if (addr != nullptr) @@ -11742,6 +11742,13 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) { emitDispGCInfoDelta(); } +#else + if (emitComp->opts.disAsm) + { + size_t expected = emitSizeOfInsDsc(id); + assert(sz == expected); + emitDispIns(id, false, 0, true, emitCurCodeOffs(odst), *dp, (dst - *dp), ig); + } #endif /* All instructions are expected to generate code */ @@ -11756,8 +11763,6 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) /*****************************************************************************/ /*****************************************************************************/ -#ifdef DEBUG - /***************************************************************************** * * Display the instruction name @@ -11804,7 +11809,7 @@ void emitter::emitDispImm(ssize_t imm, bool addComma, bool alwaysHex /* =false * if (!alwaysHex && (imm > -1000) && (imm < 1000)) { - printf("%d", imm); + printf("%d", (int)imm); } else { @@ -11820,7 +11825,7 @@ void emitter::emitDispImm(ssize_t imm, bool addComma, bool alwaysHex /* =false * } else { - printf("0x%02x", imm); + printf("0x%02x", (unsigned)imm); } } @@ -12018,7 +12023,7 @@ void emitter::emitDispVectorRegIndex(regNumber reg, emitAttr elemsize, ssize_t i assert(isVectorRegister(reg)); printf(emitVectorRegName(reg)); emitDispElemsize(elemsize); - printf("[%d]", index); + printf("[%d]", (int)index); if (addComma) printf(", "); @@ -12361,10 +12366,8 @@ void emitter::emitDispLargeJmp( // Note: don't touch the actual instrDesc. If we accidentally messed it up, it would create a very // difficult-to-find bug. - instrDescJmp idJmp; - instrDescJmp* pidJmp = &idJmp; - - memset(&idJmp, 0, sizeof(idJmp)); + inlineInstrDesc idJmp; + instrDescJmp* pidJmp = idJmp.id(); const instruction ins = id->idIns(); instruction reverseIns; @@ -12410,7 +12413,7 @@ void emitter::emitDispLargeJmp( // Next, display the unconditional branch. // Reset the local instrDesc. - memset(&idJmp, 0, sizeof(idJmp)); + memset(pidJmp, 0, sizeof(instrDescJmp)); pidJmp->idIns(INS_b); pidJmp->idInsFmt(IF_LARGEJMP); @@ -12482,6 +12485,7 @@ void emitter::emitDispIns( void emitter::emitDispInsHelp( instrDesc* id, bool isNew, bool doffs, bool asmfm, unsigned offset, BYTE* pCode, size_t sz, insGroup* ig) { +#ifdef DEBUG if (EMITVERBOSE) { unsigned idNum = @@ -12489,6 +12493,7 @@ void emitter::emitDispInsHelp( printf("IN%04x: ", idNum); } +#endif if (pCode == NULL) { @@ -12583,7 +12588,7 @@ void emitter::emitDispInsHelp( UNATIVE_OFFSET srcOffs = ig->igOffs + emitFindOffset(ig, insNum + 1); UNATIVE_OFFSET dstOffs = ig->igOffs + emitFindOffset(ig, insNum + 1 + instrCount); ssize_t relOffs = (ssize_t)(emitOffsetToPtr(dstOffs) - emitOffsetToPtr(srcOffs)); - printf("pc%s%d (%d instructions)", (relOffs >= 0) ? "+" : "", relOffs, instrCount); + printf("pc%s%d (%d instructions)", (relOffs >= 0) ? "+" : "", (int)relOffs, (int)instrCount); } } else if (id->idIsBound()) @@ -12627,7 +12632,7 @@ void emitter::emitDispInsHelp( UNATIVE_OFFSET srcOffs = ig->igOffs + emitFindOffset(ig, insNum + 1); UNATIVE_OFFSET dstOffs = ig->igOffs + emitFindOffset(ig, insNum + 1 + instrCount); ssize_t relOffs = (ssize_t)(emitOffsetToPtr(dstOffs) - emitOffsetToPtr(srcOffs)); - printf("pc%s%d (%d instructions)", (relOffs >= 0) ? "+" : "", relOffs, instrCount); + printf("pc%s%d (%d instructions)", (relOffs >= 0) ? "+" : "", (int)relOffs, (int)instrCount); } } else if (id->idIsBound()) @@ -12694,6 +12699,7 @@ void emitter::emitDispInsHelp( emitDispImm((ssize_t)id->idAddr()->iiaAddr, false); size_t targetHandle = id->idDebugOnlyInfo()->idMemCookie; +#ifdef DEBUG if (targetHandle == THT_InitializeArrayIntrinsics) { targetName = "InitializeArrayIntrinsics"; @@ -12706,6 +12712,7 @@ void emitter::emitDispInsHelp( { targetName = "SetGlobalSecurityCookie"; } +#endif } else if (id->idIsBound()) { @@ -13486,7 +13493,7 @@ void emitter::emitDispInsHelp( size = id->idOpSize(); emitDispVectorReg(id->idReg2(), (size == EA_8BYTE) ? INS_OPTS_8B : INS_OPTS_16B, true); index = emitGetInsSC(id); - printf("%s.4b[%d]", emitVectorRegName(id->idReg3()), index); + printf("%s.4b[%d]", emitVectorRegName(id->idReg3()), (int)index); } else { @@ -13682,6 +13689,7 @@ void emitter::emitDispInsHelp( void emitter::emitDispFrameRef(int varx, int disp, int offs, bool asmfm) { +#ifdef DEBUG printf("["); if (varx < 0) @@ -13712,10 +13720,9 @@ void emitter::emitDispFrameRef(int varx, int disp, int offs, bool asmfm) printf("'"); } } +#endif } -#endif // DEBUG - // Generate code for a load or store operation with a potentially complex addressing mode // This method handles the case of a GT_IND with contained GT_LEA op1 of the x86 form [base + index*scale + offset] // Since Arm64 does not directly support this complex of an addressing mode diff --git a/src/coreclr/jit/emitarm64.h b/src/coreclr/jit/emitarm64.h index dd9f6f25830e1..30ceeb4f34b80 100644 --- a/src/coreclr/jit/emitarm64.h +++ b/src/coreclr/jit/emitarm64.h @@ -15,8 +15,6 @@ static bool strictArmAsm; /* Routines that compute the size of / encode instructions */ /************************************************************************/ -#ifdef DEBUG - /************************************************************************/ /* Debug-only routines to display instructions */ /************************************************************************/ @@ -49,7 +47,6 @@ void emitDispShiftedReg(regNumber reg, insOpts opt, ssize_t imm, emitAttr attr); void emitDispExtendReg(regNumber reg, insOpts opt, ssize_t imm); void emitDispAddrRI(regNumber reg, insOpts opt, ssize_t imm); void emitDispAddrRRExt(regNumber reg1, regNumber reg2, insOpts opt, bool isScaled, emitAttr size); -#endif // DEBUG /************************************************************************/ /* Private members that deal with target-dependent instr. descriptors */ diff --git a/src/coreclr/jit/emitxarch.cpp b/src/coreclr/jit/emitxarch.cpp index bff896749a84b..1e645ad73fdb0 100644 --- a/src/coreclr/jit/emitxarch.cpp +++ b/src/coreclr/jit/emitxarch.cpp @@ -4368,9 +4368,10 @@ void emitter::emitIns_IJ(emitAttr attr, regNumber reg, unsigned base) id->idAddr()->iiaAddrMode.amIndxReg = reg; id->idAddr()->iiaAddrMode.amScale = emitter::OPSZP; -#ifdef DEBUG - id->idDebugOnlyInfo()->idMemCookie = base; -#endif + if (m_debugInfoSize > 0) + { + id->idDebugOnlyInfo()->idMemCookie = base; + } id->idCodeSize(sz); @@ -7990,20 +7991,12 @@ void emitter::emitIns_Call(EmitCallType callType, } } -#ifdef DEBUG - if (emitComp->verbose && 0) + if (m_debugInfoSize > 0) { - if (id->idIsLargeCall()) - { - printf("[%02u] Rec call GC vars = %s\n", id->idDebugOnlyInfo()->idNum, - VarSetOps::ToString(emitComp, ((instrDescCGCA*)id)->idcGCvars)); - } + INDEBUG(id->idDebugOnlyInfo()->idCallSig = sigInfo); + id->idDebugOnlyInfo()->idMemCookie = (size_t)methHnd; // method token } - id->idDebugOnlyInfo()->idMemCookie = (size_t)methHnd; // method token - id->idDebugOnlyInfo()->idCallSig = sigInfo; -#endif // DEBUG - #ifdef LATE_DISASM if (addr != nullptr) { @@ -8173,8 +8166,6 @@ size_t emitter::emitSizeOfInsDsc(instrDesc* id) return sizeof(instrDesc); } -/*****************************************************************************/ -#ifdef DEBUG /***************************************************************************** * * Return a string that represents the given register. @@ -8412,13 +8403,13 @@ void emitter::emitDispClsVar(CORINFO_FIELD_HANDLE fldHnd, ssize_t offs, bool rel if (fldHnd == FLD_GLOBAL_FS) { - printf("FS:[0x%04X]", offs); + printf("FS:[0x%04X]", (unsigned)offs); return; } if (fldHnd == FLD_GLOBAL_DS) { - printf("[0x%04X]", offs); + printf("[0x%04X]", (unsigned)offs); return; } @@ -8449,7 +8440,7 @@ void emitter::emitDispClsVar(CORINFO_FIELD_HANDLE fldHnd, ssize_t offs, bool rel } else { - printf("classVar[%#x]", emitComp->dspPtr(fldHnd)); + printf("classVar[%#p]", (void*)emitComp->dspPtr(fldHnd)); if (offs) { @@ -8459,6 +8450,7 @@ void emitter::emitDispClsVar(CORINFO_FIELD_HANDLE fldHnd, ssize_t offs, bool rel printf("]"); +#ifdef DEBUG if (emitComp->opts.varNames && offs < 0) { printf("'%s", emitComp->eeGetFieldName(fldHnd)); @@ -8468,6 +8460,7 @@ void emitter::emitDispClsVar(CORINFO_FIELD_HANDLE fldHnd, ssize_t offs, bool rel } printf("'"); } +#endif } /***************************************************************************** @@ -8550,7 +8543,7 @@ void emitter::emitDispFrameRef(int varx, int disp, int offs, bool asmfm) } printf("]"); - +#ifdef DEBUG if (varx >= 0 && emitComp->opts.varNames) { const char* varName = emitComp->compLocalVarName(varx, offs); @@ -8571,6 +8564,7 @@ void emitter::emitDispFrameRef(int varx, int disp, int offs, bool asmfm) printf("'"); } } +#endif } /***************************************************************************** @@ -8644,7 +8638,7 @@ void emitter::emitDispAddrMode(instrDesc* id, bool noDetail) { printf("reloc "); } - printf("J_M%03u_DS%02u", emitComp->compMethodID, id->idDebugOnlyInfo()->idMemCookie); + printf("J_M%03u_DS%02u", emitComp->compMethodID, (unsigned)id->idDebugOnlyInfo()->idMemCookie); disp -= id->idDebugOnlyInfo()->idMemCookie; } @@ -8678,7 +8672,7 @@ void emitter::emitDispAddrMode(instrDesc* id, bool noDetail) } if (scale > 1) { - printf("%u*", scale); + printf("%u*", (unsigned)scale); } printf("%s", emitRegName(id->idAddr()->iiaAddrMode.amIndxReg)); nsep = true; @@ -8712,34 +8706,34 @@ void emitter::emitDispAddrMode(instrDesc* id, bool noDetail) } if (frameRef) { - printf("%02XH", disp); + printf("%02XH", (unsigned)disp); } else if (disp < 1000) { - printf("%d", disp); + printf("%d", (unsigned)disp); } else if (disp <= 0xFFFF) { - printf("%04XH", disp); + printf("%04XH", (unsigned)disp); } else { - printf("%08XH", disp); + printf("%08XH", (unsigned)disp); } } else if (disp < 0) { if (frameRef) { - printf("-%02XH", -disp); + printf("-%02XH", (unsigned)-disp); } else if (disp > -1000) { - printf("-%d", -disp); + printf("-%d", (unsigned)-disp); } else if (disp >= -0xFFFF) { - printf("-%04XH", -disp); + printf("-%04XH", (unsigned)-disp); } else if (disp < -0xFFFFFF) { @@ -8747,22 +8741,23 @@ void emitter::emitDispAddrMode(instrDesc* id, bool noDetail) { printf("+"); } - printf("%08XH", disp); + printf("%08XH", (unsigned)disp); } else { - printf("-%08XH", -disp); + printf("-%08XH", (unsigned)-disp); } } else if (!nsep) { - printf("%04XH", disp); + printf("%04XH", (unsigned)disp); } } printf("]"); - // pretty print string if it looks like one +// pretty print string if it looks like one +#ifdef DEBUG if ((id->idGCref() == GCT_GCREF) && (id->idIns() == INS_mov) && (id->idAddr()->iiaAddrMode.amBaseReg == REG_NA)) { const WCHAR* str = emitComp->eeGetCPString(disp); @@ -8771,6 +8766,7 @@ void emitter::emitDispAddrMode(instrDesc* id, bool noDetail) printf(" '%S'", str); } } +#endif if (jdsc && !noDetail) { @@ -8868,7 +8864,7 @@ void emitter::emitDispInsHex(instrDesc* id, BYTE* code, size_t sz) if (sz < digits) { - printf("%.*s", 2 * (digits - sz), " "); + printf("%.*s", (int)(2 * (digits - sz)), " "); } } } @@ -8897,11 +8893,13 @@ void emitter::emitDispIns( instruction ins = id->idIns(); +#ifdef DEBUG if (emitComp->verbose) { unsigned idNum = id->idDebugOnlyInfo()->idNum; printf("IN%04x: ", idNum); } +#endif #define ID_INFO_DSP_RELOC ((bool)(id->idIsDspReloc())) @@ -9128,15 +9126,15 @@ void emitter::emitDispIns( } if ((val > -1000) && (val < 1000)) { - printf("%d", val); + printf("%d", (int)val); } else if ((val > 0) || (val < -0xFFFFFF)) { - printf("0x%IX", val); + printf("0x%IX", (ssize_t)val); } else { // (val < 0) - printf("-0x%IX", -val); + printf("-0x%IX", (ssize_t)-val); } emitDispCommentForHandle(srcVal, id->idDebugOnlyInfo()->idMemCookie, id->idDebugOnlyInfo()->idFlags); } @@ -10016,18 +10014,17 @@ void emitter::emitDispIns( break; } +#ifdef DEBUG if (sz != 0 && sz != id->idCodeSize() && (!asmfm || emitComp->verbose)) { // Code size in the instrDesc is different from the actual code size we've been given! printf(" (ECS:%d, ACS:%d)", id->idCodeSize(), sz); } +#endif printf("\n"); } -/*****************************************************************************/ -#endif - /***************************************************************************** * * Output nBytes bytes of NOP instructions @@ -13504,11 +13501,14 @@ BYTE* emitter::emitOutputLJ(insGroup* ig, BYTE* dst, instrDesc* i) // Make an instrDesc that looks like IF_RWR_ARD so that emitOutputAM emits the r/m32 for us. // We basically are doing what emitIns_R_AI does. // TODO-XArch-Cleanup: revisit this. - instrDescAmd idAmdStackLocal; - instrDescAmd* idAmd = &idAmdStackLocal; - *(instrDesc*)idAmd = *(instrDesc*)id; // copy all the "core" fields - memset((BYTE*)idAmd + sizeof(instrDesc), 0, - sizeof(instrDescAmd) - sizeof(instrDesc)); // zero out the tail that wasn't copied + inlineInstrDesc idAmdStackLocal; + instrDescAmd* idAmd = idAmdStackLocal.id(); + *(instrDesc*)idAmd = *(instrDesc*)id; // copy all the "core" fields + + if (m_debugInfoSize > 0) + { + idAmd->idDebugOnlyInfo(id->idDebugOnlyInfo()); + } idAmd->idInsFmt(IF_RWR_ARD); idAmd->idAddr()->iiaAddrMode.amBaseReg = REG_NA; @@ -14756,6 +14756,11 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) { emitDispIns(id, false, dspOffs, true, emitCurCodeOffs(*dp), *dp, (dst - *dp)); } +#else + if (emitComp->opts.disAsm && !emitJmpInstHasNoCode(id)) + { + emitDispIns(id, false, 0, true, emitCurCodeOffs(*dp), *dp, (dst - *dp)); + } #endif #if FEATURE_LOOP_ALIGN diff --git a/src/coreclr/jit/emitxarch.h b/src/coreclr/jit/emitxarch.h index c744e40dbd41e..6334e5a0ddf92 100644 --- a/src/coreclr/jit/emitxarch.h +++ b/src/coreclr/jit/emitxarch.h @@ -220,8 +220,6 @@ bool isPrefetch(instruction ins) /* Debug-only routines to display instructions */ /************************************************************************/ -#ifdef DEBUG - void emitDispReloc(ssize_t value); void emitDispAddrMode(instrDesc* id, bool noDetail = false); void emitDispShift(instruction ins, int cnt = 0); @@ -229,8 +227,6 @@ void emitDispShift(instruction ins, int cnt = 0); const char* emitXMMregName(unsigned reg); const char* emitYMMregName(unsigned reg); -#endif - /************************************************************************/ /* Private members that deal with target-dependent instr. descriptors */ /************************************************************************/ diff --git a/src/coreclr/jit/instr.cpp b/src/coreclr/jit/instr.cpp index 9843482bbef6c..44feba2ddee90 100644 --- a/src/coreclr/jit/instr.cpp +++ b/src/coreclr/jit/instr.cpp @@ -22,7 +22,6 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX #include "emit.h" /*****************************************************************************/ -#ifdef DEBUG //----------------------------------------------------------------------------- // genInsName: Returns the string representation of the given CPU instruction, as @@ -147,16 +146,11 @@ const char* CodeGen::genInsDisplayName(emitter::instrDesc* id) return insName; } -/*****************************************************************************/ -#endif // DEBUG - /***************************************************************************** * * Return the size string (e.g. "word ptr") appropriate for the given size. */ -#ifdef DEBUG - const char* CodeGen::genSizeStr(emitAttr attr) { // clang-format off @@ -213,8 +207,6 @@ const char* CodeGen::genSizeStr(emitAttr attr) } } -#endif - /***************************************************************************** * * Generate an instruction. diff --git a/src/coreclr/jit/jitconfigvalues.h b/src/coreclr/jit/jitconfigvalues.h index 673502f379d95..4571c1a3bdcb1 100644 --- a/src/coreclr/jit/jitconfigvalues.h +++ b/src/coreclr/jit/jitconfigvalues.h @@ -270,7 +270,11 @@ CONFIG_STRING(NgenDumpFgFile, W("NgenDumpFgFile")) // Ngen Xml/Dot flowgraph dum CONFIG_INTEGER(EnableIncompleteISAClass, W("EnableIncompleteISAClass"), 0) // Enable testing not-yet-implemented // intrinsic classes -#endif // defined(DEBUG) +#else // defined(DEBUG) + +// JitDisasm is supported in Release too +CONFIG_METHODSET(JitDisasm, W("JitDisasm")) +#endif // !defined(DEBUG) CONFIG_INTEGER(RichDebugInfo, W("RichDebugInfo"), 0) // If 1, keep rich debug info and report it back to the EE diff --git a/src/coreclr/jit/target.h b/src/coreclr/jit/target.h index c01ba5b476d66..392a541714139 100644 --- a/src/coreclr/jit/target.h +++ b/src/coreclr/jit/target.h @@ -315,10 +315,8 @@ class Target static const enum ArgOrder g_tgtUnmanagedArgOrder; }; -#if defined(DEBUG) || defined(LATE_DISASM) || DUMP_GC_TABLES const char* getRegName(unsigned reg); // this is for gcencode.cpp and disasm.cpp that don't use the regNumber type const char* getRegName(regNumber reg); -#endif // defined(DEBUG) || defined(LATE_DISASM) || DUMP_GC_TABLES #ifdef DEBUG const char* getRegNameFloat(regNumber reg, var_types type); diff --git a/src/coreclr/jit/utils.cpp b/src/coreclr/jit/utils.cpp index 5d58995f3377f..3898d338d138a 100644 --- a/src/coreclr/jit/utils.cpp +++ b/src/coreclr/jit/utils.cpp @@ -115,7 +115,6 @@ const char* varTypeName(var_types vt) return varTypeNames[vt]; } -#if defined(DEBUG) || defined(LATE_DISASM) || DUMP_GC_TABLES /***************************************************************************** * * Return the name of the given register. @@ -145,7 +144,6 @@ const char* getRegName(unsigned reg) // this is for gcencode.cpp and disasm.cpp { return getRegName((regNumber)reg); } -#endif // defined(DEBUG) || defined(LATE_DISASM) || DUMP_GC_TABLES #if defined(DEBUG)