diff --git a/src/jit/codegencommon.cpp b/src/jit/codegencommon.cpp index d6d87f53e98e..a9c9c9c8be6a 100644 --- a/src/jit/codegencommon.cpp +++ b/src/jit/codegencommon.cpp @@ -4835,11 +4835,12 @@ void CodeGen::genCheckUseBlockInit() } #ifdef _TARGET_XARCH_ - // If we're going to use "REP STOS", remember that we will trash EDI - // For fastcall we will have to save ECX, EAX - // so reserve two extra callee saved - // This is better than pushing eax, ecx, because we in the later - // we will mess up already computed offsets on the stack (for ESP frames) + /* If we're going to use "REP STOS", remember that we will trash EDI */ + /* For fastcall we will have to save ECX, EAX + * so reserve two extra callee saved + * This is better than pushing eax, ecx, because we in the later + * we will mess up already computed offsets on the stack (for ESP frames) + */ regSet.rsSetRegsModified(RBM_EDI); @@ -5168,7 +5169,6 @@ void CodeGen::genPushCalleeSavedRegisters() offset += 2 * REGSIZE_BYTES; } } - if (frameType == 1) { getEmitter()->emitIns_R_R(INS_mov, EA_PTRSIZE, REG_FPBASE, REG_SPBASE); diff --git a/src/jit/emitxarch.cpp b/src/jit/emitxarch.cpp index 2d106e531ebd..876f5da9343e 100644 --- a/src/jit/emitxarch.cpp +++ b/src/jit/emitxarch.cpp @@ -1721,7 +1721,14 @@ UNATIVE_OFFSET emitter::emitInsSizeSV(size_t code, int var, int dsp) #endif { // Dev10 804810 - failing this assert can lead to bad codegen and runtime crashes +#ifdef UNIX_AMD64_ABI + LclVarDsc* varDsc = emitComp->lvaTable + var; + bool isRegPassedArg = varDsc->lvIsParam && varDsc->lvIsRegArg; + // Register passed args could have a stack offset of 0. + noway_assert((int)offs < 0 || isRegPassedArg); +#else // !UNIX_AMD64_ABI noway_assert((int)offs < 0); +#endif // !UNIX_AMD64_ABI } diff --git a/src/jit/target.h b/src/jit/target.h index e77933b5f5a1..5ee9bb8ee2c1 100644 --- a/src/jit/target.h +++ b/src/jit/target.h @@ -667,8 +667,7 @@ typedef unsigned short regPairNoSmall; // arm: need 12 bits #ifndef UNIX_AMD64_ABI #define ETW_EBP_FRAMED 0 // if 1 we cannot use EBP as a scratch register and must create EBP based frames for most methods #else // UNIX_AMD64_ABI - // TODO-Amd64-Unis: Enable Frame Pointer chaining for most methods when uniwinding and the rest is implemented. Set the following to 1. - #define ETW_EBP_FRAMED 0 // if 1 we cannot use EBP as a scratch register and must create EBP based frames for most methods + #define ETW_EBP_FRAMED 1 // if 1 we cannot use EBP as a scratch register and must create EBP based frames for most methods #endif // UNIX_AMD64_ABI #define FEATURE_FP_REGALLOC 0 // Enabled if RegAlloc is used to enregister Floating Point LclVars #define CSE_CONSTS 1 // Enable if we want to CSE constants @@ -723,71 +722,134 @@ typedef unsigned short regPairNoSmall; // arm: need 12 bits #define RBM_ALLINT (RBM_INT_CALLEE_SAVED | RBM_INT_CALLEE_TRASH) #ifndef UNIX_AMD64_ABI +#if !ETW_EBP_FRAMED #define RBM_LOWINT (RBM_EAX|RBM_ECX|RBM_EBX|RBM_EBP|RBM_ESI|RBM_EDI) +#else // ETW_EBP_FRAMED + #define RBM_LOWINT (RBM_EAX|RBM_ECX|RBM_EBX|RBM_ESI|RBM_EDI) +#endif // ETW_EBP_FRAMED #else // UNIX_AMD64_ABI +#if !ETW_EBP_FRAMED #define RBM_LOWINT (RBM_EAX|RBM_RDI|RBM_RSI|RBM_EDX|RBM_ECX|RBM_EBX|RBM_EBP) +#else // ETW_EBP_FRAMED + #define RBM_LOWINT (RBM_EAX|RBM_RDI|RBM_RSI|RBM_EDX|RBM_ECX|RBM_EBX) +#endif // ETW_EBP_FRAMED #endif // UNIX_AMD64_ABI #if 0 +#if !ETW_EBP_FRAMED #define REG_VAR_ORDER REG_EAX,REG_EDX,REG_ECX,REG_ESI,REG_EDI,REG_EBX,REG_EBP, \ REG_R8,REG_R9,REG_R10,REG_R11,REG_R14,REG_R15,REG_R12,REG_R13 +#else // ETW_EBP_FRAMED + #define REG_VAR_ORDER REG_EAX,REG_EDX,REG_ECX,REG_ESI,REG_EDI,REG_EBX, \ + REG_R8,REG_R9,REG_R10,REG_R11,REG_R14,REG_R15,REG_R12,REG_R13 +#endif // ETW_EBP_FRAMED + #else // TEMPORARY ORDER TO AVOID CALLEE-SAVES // TODO-CQ: Review this and set appropriately #ifndef UNIX_AMD64_ABI +#if !ETW_EBP_FRAMED #define REG_VAR_ORDER REG_EAX,REG_EDX,REG_ECX, \ REG_R8,REG_R9,REG_R10,REG_R11, \ REG_ESI,REG_EDI,REG_EBX,REG_EBP, \ REG_R14,REG_R15,REG_R12,REG_R13 +#else // ETW_EBP_FRAMED + #define REG_VAR_ORDER REG_EAX,REG_EDX,REG_ECX, \ + REG_R8,REG_R9,REG_R10,REG_R11, \ + REG_ESI,REG_EDI,REG_EBX, \ + REG_R14,REG_R15,REG_R12,REG_R13 +#endif // ETW_EBP_FRAMED #else // UNIX_AMD64_ABI +#if !ETW_EBP_FRAMED #define REG_VAR_ORDER \ - REG_EAX, REG_EDI, REG_ESI, \ - REG_EDX, REG_ECX, REG_R8, REG_R9, \ - REG_R10, REG_R11, REG_EBX, REG_EBP, \ - REG_R14, REG_R15, REG_R12, REG_R13 + REG_EAX,REG_EDI,REG_ESI, \ + REG_EDX,REG_ECX,REG_R8,REG_R9, \ + REG_R10,REG_R11,REG_EBX,REG_EBP, \ + REG_R14,REG_R15,REG_R12,REG_R13 +#else // ETW_EBP_FRAMED + #define REG_VAR_ORDER \ + REG_EAX,REG_EDI,REG_ESI, \ + REG_EDX,REG_ECX,REG_R8,REG_R9, \ + REG_R10,REG_R11,REG_EBX, \ + REG_R14,REG_R15,REG_R12,REG_R13 +#endif // ETW_EBP_FRAMED #endif // UNIX_AMD64_ABI #endif - #define REG_VAR_ORDER_FLT REG_XMM0, REG_XMM1, REG_XMM2, REG_XMM3, REG_XMM4, REG_XMM5, REG_XMM6, REG_XMM7, REG_XMM8, REG_XMM9, REG_XMM10, REG_XMM11, REG_XMM12, REG_XMM13, REG_XMM14, REG_XMM15 - - #define MAX_VAR_ORDER_SIZE 15 + #define REG_VAR_ORDER_FLT REG_XMM0,REG_XMM1,REG_XMM2,REG_XMM3,REG_XMM4,REG_XMM5,REG_XMM6,REG_XMM7,REG_XMM8,REG_XMM9,REG_XMM10,REG_XMM11,REG_XMM12,REG_XMM13,REG_XMM14,REG_XMM15 #ifndef UNIX_AMD64_ABI +#if !ETW_EBP_FRAMED + #define MAX_VAR_ORDER_SIZE 15 #define REG_TMP_ORDER REG_EAX,REG_EDX,REG_ECX,REG_EBX,REG_ESI,REG_EDI,REG_EBP, \ - REG_R8, REG_R9, REG_R10, REG_R11, REG_R14, REG_R15, REG_R12, REG_R13 + REG_R8,REG_R9,REG_R10,REG_R11,REG_R14,REG_R15,REG_R12,REG_R13 +#else // ETW_EBP_FRAMED + #define MAX_VAR_ORDER_SIZE 14 + #define REG_TMP_ORDER REG_EAX,REG_EDX,REG_ECX,REG_EBX,REG_ESI,REG_EDI, \ + REG_R8,REG_R9,REG_R10,REG_R11,REG_R14,REG_R15,REG_R12,REG_R13 +#endif // ETW_EBP_FRAMED + #else // UNIX_AMD64_ABI +#if !ETW_EBP_FRAMED #define REG_TMP_ORDER REG_EAX,REG_EDI,REG_ESI,REG_EDX,REG_ECX,REG_EBX,REG_EBP, \ - REG_R8, REG_R9, REG_R10, REG_R11, REG_R14, REG_R15, REG_R12, REG_R13 + REG_R8,REG_R9,REG_R10,REG_R11,REG_R14,REG_R15,REG_R12,REG_R13 +#else // ETW_EBP_FRAMED + #define REG_TMP_ORDER REG_EAX,REG_EDI,REG_ESI,REG_EDX,REG_ECX,REG_EBX, \ + REG_R8,REG_R9,REG_R10,REG_R11,REG_R14,REG_R15,REG_R12,REG_R13 +#endif // ETW_EBP_FRAMED + #endif // UNIX_AMD64_ABI - #define REG_TMP_ORDER_COUNT 15 #ifndef UNIX_AMD64_ABI +#if !ETW_EBP_FRAMED + #define REG_TMP_ORDER_COUNT 15 #define REG_PREDICT_ORDER REG_EAX,REG_EDX,REG_ECX,REG_EBX,REG_ESI,REG_EDI,REG_EBP, \ REG_R8,REG_R9,REG_R10,REG_R11,REG_R14,REG_R15,REG_R12,REG_R13 - #define CNT_CALLEE_SAVED (8) +#else // ETW_EBP_FRAMED + #define REG_TMP_ORDER_COUNT 14 + #define REG_PREDICT_ORDER REG_EAX,REG_EDX,REG_ECX,REG_EBX,REG_ESI,REG_EDI, \ + REG_R8,REG_R9,REG_R10,REG_R11,REG_R14,REG_R15,REG_R12,REG_R13 + #define CNT_CALLEE_SAVED (7) +#endif // ETW_EBP_FRAMED + #define CNT_CALLEE_TRASH (7) #define CNT_CALLEE_ENREG (CNT_CALLEE_SAVED) #define CNT_CALLEE_SAVED_FLOAT (10) #define CNT_CALLEE_TRASH_FLOAT (6) +#if !ETW_EBP_FRAMED #define REG_CALLEE_SAVED_ORDER REG_EBX,REG_ESI,REG_EDI,REG_EBP,REG_R12,REG_R13,REG_R14,REG_R15 #define RBM_CALLEE_SAVED_ORDER RBM_EBX,RBM_ESI,RBM_EDI,RBM_EBP,RBM_R12,RBM_R13,RBM_R14,RBM_R15 +#else // ETW_EBP_FRAMED + #define REG_CALLEE_SAVED_ORDER REG_EBX,REG_ESI,REG_EDI,REG_R12,REG_R13,REG_R14,REG_R15 + #define RBM_CALLEE_SAVED_ORDER RBM_EBX,RBM_ESI,RBM_EDI,RBM_R12,RBM_R13,RBM_R14,RBM_R15 +#endif // ETW_EBP_FRAMED #define CALLEE_SAVED_REG_MAXSZ (CNT_CALLEE_SAVED*REGSIZE_BYTES) // RBX, RSI, RDI, RBP, R12, R13, R14, R15 #else // UNIX_AMD64_ABI +#if !ETW_EBP_FRAMED #define REG_PREDICT_ORDER REG_EAX, REG_EDI, REG_ESI, REG_EDX, REG_ECX, REG_EBX, REG_EBP, \ - REG_R8, REG_R9, REG_R10, REG_R11, REG_R14, REG_R15, REG_R12, REG_R13 - + REG_R8,REG_R9,REG_R10,REG_R11,REG_R14,REG_R15,REG_R12,REG_R13 #define CNT_CALLEE_SAVED (6) +#else // ETW_EBP_FRAMED + #define REG_PREDICT_ORDER REG_EAX, REG_EDI, REG_ESI, REG_EDX, REG_ECX, REG_EBX, \ + REG_R8,REG_R9,REG_R10,REG_R11,REG_R14,REG_R15,REG_R12,REG_R13 + #define CNT_CALLEE_SAVED (5) +#endif // ETW_EBP_FRAMED #define CNT_CALLEE_TRASH (9) #define CNT_CALLEE_ENREG (CNT_CALLEE_SAVED) #define CNT_CALLEE_SAVED_FLOAT (0) #define CNT_CALLEE_TRASH_FLOAT (16) +#if !ETW_EBP_FRAMED #define REG_CALLEE_SAVED_ORDER REG_EBX,REG_EBP,REG_R12,REG_R13,REG_R14,REG_R15 #define RBM_CALLEE_SAVED_ORDER RBM_EBX,RBM_EBP,RBM_R12,RBM_R13,RBM_R14,RBM_R15 +#else // ETW_EBP_FRAMED + #define REG_CALLEE_SAVED_ORDER REG_EBX,REG_R12,REG_R13,REG_R14,REG_R15 + #define RBM_CALLEE_SAVED_ORDER RBM_EBX,RBM_R12,RBM_R13,RBM_R14,RBM_R15 +#endif // ETW_EBP_FRAMED #define CALLEE_SAVED_REG_MAXSZ (CNT_CALLEE_SAVED*REGSIZE_BYTES) // RBX, RBP, R12, R13, R14, R15 #endif // UNIX_AMD64_ABI diff --git a/src/jit/unwindamd64.cpp b/src/jit/unwindamd64.cpp index cf83ed3015ad..357b49281170 100644 --- a/src/jit/unwindamd64.cpp +++ b/src/jit/unwindamd64.cpp @@ -121,7 +121,15 @@ void Compiler::unwindPush(regNumber reg) unsigned int cbProlog = unwindGetCurrentOffset(func); noway_assert((BYTE)cbProlog == cbProlog); code->CodeOffset = (BYTE)cbProlog; - if (RBM_CALLEE_SAVED & genRegMask(reg)) + if (RBM_CALLEE_SAVED & genRegMask(reg) +#if ETW_EBP_FRAMED + // In case of ETW_EBP_FRAMED defined the REG_FPBASE (RBP) + // is excluded from the callee-save register list. + // Make sure the register gets PUSH unwind info in this case, + // since it is pushed as a frame register. + || (reg == REG_FPBASE) +#endif // ETW_EBP_FRAMED + ) { code->UnwindOp = UWOP_PUSH_NONVOL; code->OpInfo = (BYTE)reg;