From 7d680c2a481779ac3c2f5cb5c8c3f3dec14f1cab Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Mon, 29 Jun 2020 12:16:47 -0700 Subject: [PATCH] Fixed actualization of illegal offset scales --- IDEHelper/Backend/BeMCContext.cpp | 501 +++++++++++++++--------------- IDEHelper/Backend/BeMCContext.h | 30 +- 2 files changed, 283 insertions(+), 248 deletions(-) diff --git a/IDEHelper/Backend/BeMCContext.cpp b/IDEHelper/Backend/BeMCContext.cpp index d8382c3d..d46eb2f0 100644 --- a/IDEHelper/Backend/BeMCContext.cpp +++ b/IDEHelper/Backend/BeMCContext.cpp @@ -3636,7 +3636,7 @@ BeMCOperand BeMCContext::AllocVirtualReg(BeType* type, int refCount, bool mustBe if (mDebugging) { - if (mcOperand.mVRegIdx == 263) + if (mcOperand.mVRegIdx == 97) { NOP; } @@ -5180,13 +5180,10 @@ uint8 BeMCContext::GetREX(const BeMCOperand& r, const BeMCOperand& rm, bool is64 if (vregInfo->IsDirectRelTo()) return GetREX(r, vregInfo->mRelTo, is64Bit); - X64CPURegister regA = X64Reg_None; - X64CPURegister regB = X64Reg_None; - int bScale = 1; - int disp = 0; - GetRMParams(rm, regA, regB, bScale, disp); - is64BitExRM |= ((regA >= X64Reg_R8) && (regA <= X64Reg_R15)) || ((regA >= X64Reg_R8D) && (regA <= X64Reg_R15D)); - hasSibExRM |= ((regB >= X64Reg_R8) && (regB <= X64Reg_R15)) || ((regB >= X64Reg_R8D) && (regB <= X64Reg_R15D)); + BeRMParamsInfo rmInfo; + GetRMParams(rm, rmInfo); + is64BitExRM |= ((rmInfo.mRegA >= X64Reg_R8) && (rmInfo.mRegA <= X64Reg_R15)) || ((rmInfo.mRegA >= X64Reg_R8D) && (rmInfo.mRegA <= X64Reg_R15D)); + hasSibExRM |= ((rmInfo.mRegB >= X64Reg_R8) && (rmInfo.mRegB <= X64Reg_R15)) || ((rmInfo.mRegB >= X64Reg_R8D) && (rmInfo.mRegB <= X64Reg_R15D)); } else if (rm.IsSymbol()) { @@ -5354,10 +5351,10 @@ int BeMCContext::GetRegSize(int regNum) return 8; } -BeMCRMMode BeMCContext::ValidateRMResult(const BeMCOperand& operand, X64CPURegister& regA, X64CPURegister& regB, int& bScale, int& disp, int* errorVReg, BeMCRMMode result, bool doValidate) +void BeMCContext::ValidateRMResult(const BeMCOperand& operand, BeRMParamsInfo& rmInfo, bool doValidate) { if (!doValidate) - return result; + return; //TODO: WTF- this previous version just seems to be wrong! Why did think this was true? the REX.X and REX.B flags fix these // in a SIB, the base can't be R13 (which is RBP+REX), and the scaled index can't be R12 (which is RSP+REX) @@ -5376,40 +5373,45 @@ BeMCRMMode BeMCContext::ValidateRMResult(const BeMCOperand& operand, X64CPURegis //} // In a SIB, the base can't be RBP, and the scaled index can't be RSP - if ((regB != X64Reg_None) && - ((regA == X64Reg_RBP) || (regB == X64Reg_RSP))) + if ((rmInfo.mRegB != X64Reg_None) && + ((rmInfo.mRegA == X64Reg_RBP) || (rmInfo.mRegB == X64Reg_RSP))) { // We can't just swap the regs if we have a scale applied - if (bScale != 1) - { - if (errorVReg != NULL) - *errorVReg = -2; // Scale error - return BeMCRMMode_Invalid; + if (rmInfo.mBScale != 1) + { + rmInfo.mErrorVReg = -2; // Scale error + rmInfo.mMode = BeMCRMMode_Invalid; + return; } - BF_SWAP(regA, regB); + BF_SWAP(rmInfo.mRegA, rmInfo.mRegB); } - return result; + return; } -BeMCRMMode BeMCContext::GetRMParams(const BeMCOperand& operand, X64CPURegister& regA, X64CPURegister& regB, int& bScale, int& disp, int* errorVReg, bool doValidate) -{ +void BeMCContext::GetRMParams(const BeMCOperand& operand, BeRMParamsInfo& rmInfo, bool doValidate) +{ BeMCRMMode rmMode = BeMCRMMode_Invalid; if (operand.mKind == BeMCOperandKind_NativeReg) { - if (regA == X64Reg_None) - regA = operand.mReg; - else if (regB == X64Reg_None) - regB = operand.mReg; - else - return BeMCRMMode_Invalid; - return ValidateRMResult(operand, regA, regB, bScale, disp, errorVReg, BeMCRMMode_Direct, doValidate); + if (rmInfo.mRegA == X64Reg_None) + rmInfo.mRegA = operand.mReg; + else if (rmInfo.mRegB == X64Reg_None) + rmInfo.mRegB = operand.mReg; + else + { + rmInfo.mMode = BeMCRMMode_Invalid; + return; + } + rmInfo.mMode = BeMCRMMode_Direct; + return ValidateRMResult(operand, rmInfo, doValidate); } else if (operand.IsImmediateInt()) { - disp += (int)operand.mImmediate; - return ValidateRMResult(operand, regA, regB, bScale, disp, errorVReg, BeMCRMMode_Direct, doValidate); + rmInfo.mDisp += (int)operand.mImmediate; + rmInfo.mMode = BeMCRMMode_Direct; + return ValidateRMResult(operand, rmInfo, doValidate); } if (operand.mKind == BeMCOperandKind_VReg) @@ -5420,20 +5422,25 @@ BeMCRMMode BeMCContext::GetRMParams(const BeMCOperand& operand, X64CPURegister& auto reg = vregInfo->mReg; if (reg != X64Reg_None) { - if (regA == X64Reg_None) - regA = reg; - else if (regB == X64Reg_None) - regB = reg; + if (rmInfo.mRegA == X64Reg_None) + rmInfo.mRegA = reg; + else if (rmInfo.mRegB == X64Reg_None) + rmInfo.mRegB = reg; else - return BeMCRMMode_Invalid; - return ValidateRMResult(operand, regA, regB, bScale, disp, errorVReg, BeMCRMMode_Direct, doValidate); + { + rmInfo.mMode = BeMCRMMode_Invalid; + return; + } + rmInfo.mMode = BeMCRMMode_Direct; + return ValidateRMResult(operand, rmInfo, doValidate); } - auto result = GetRMParams(BeMCOperand::ToAddr(operand), regA, regB, bScale, disp, errorVReg, doValidate); - if (result == BeMCRMMode_Invalid) - return BeMCRMMode_Invalid; - BF_ASSERT(result == BeMCRMMode_Direct); - return ValidateRMResult(BeMCOperand::ToAddr(operand), regA, regB, bScale, disp, errorVReg, BeMCRMMode_Deref, doValidate); + GetRMParams(BeMCOperand::ToAddr(operand), rmInfo, doValidate); + if (rmInfo.mMode == BeMCRMMode_Invalid) + return; + BF_ASSERT(rmInfo.mMode == BeMCRMMode_Direct); + rmInfo.mMode = BeMCRMMode_Deref; + return ValidateRMResult(BeMCOperand::ToAddr(operand), rmInfo, doValidate); } // Fall through } @@ -5446,13 +5453,14 @@ BeMCRMMode BeMCContext::GetRMParams(const BeMCOperand& operand, X64CPURegister& if (vregInfo->IsDirectRelToAny()) { if (vregInfo->mRelTo.mKind == BeMCOperandKind_VReg) - return GetRMParams(BeMCOperand::FromVRegAddr(vregInfo->mRelTo.mVRegIdx), regA, regB, bScale, disp, errorVReg, doValidate); + return GetRMParams(BeMCOperand::FromVRegAddr(vregInfo->mRelTo.mVRegIdx), rmInfo, doValidate); else if (vregInfo->mRelTo.mKind == BeMCOperandKind_VRegLoad) - return GetRMParams(BeMCOperand::FromVReg(vregInfo->mRelTo.mVRegIdx), regA, regB, bScale, disp, errorVReg, doValidate); + return GetRMParams(BeMCOperand::FromVReg(vregInfo->mRelTo.mVRegIdx), rmInfo, doValidate); } - *errorVReg = operand.mVRegIdx; - return BeMCRMMode_Invalid; + rmInfo.mErrorVReg = operand.mVRegIdx; + rmInfo.mMode = BeMCRMMode_Invalid; + return; } BF_ASSERT(!vregInfo->mIsExpr); @@ -5461,17 +5469,18 @@ BeMCRMMode BeMCContext::GetRMParams(const BeMCOperand& operand, X64CPURegister& if ((vregInfo->mIsRetVal) && (mCompositeRetVRegIdx != -1) && (mCompositeRetVRegIdx != operand.mVRegIdx)) { - return GetRMParams(BeMCOperand::FromVReg(mCompositeRetVRegIdx), regA, regB, bScale, disp, errorVReg, doValidate); + return GetRMParams(BeMCOperand::FromVReg(mCompositeRetVRegIdx), rmInfo, doValidate); } reg = mUseBP ? X64Reg_RBP : X64Reg_RSP; - disp = mStackSize + vregInfo->mFrameOffset; + rmInfo.mDisp = mStackSize + vregInfo->mFrameOffset; - if (regA == X64Reg_None) - regA = reg; - else if (regB == X64Reg_None) - regB = reg; - return ValidateRMResult(operand, regA, regB, bScale, disp, errorVReg, BeMCRMMode_Direct, doValidate); + if (rmInfo.mRegA == X64Reg_None) + rmInfo.mRegA = reg; + else if (rmInfo.mRegB == X64Reg_None) + rmInfo.mRegB = reg; + rmInfo.mMode = BeMCRMMode_Direct; + return ValidateRMResult(operand, rmInfo, doValidate); } else if (operand.mKind == BeMCOperandKind_VRegLoad) { @@ -5480,21 +5489,23 @@ BeMCRMMode BeMCContext::GetRMParams(const BeMCOperand& operand, X64CPURegister& { auto reg = vregInfo->mReg; if (reg == X64Reg_None) - { - if (errorVReg != NULL) - *errorVReg = operand.mVRegIdx; - return BeMCRMMode_Invalid; + { + rmInfo.mErrorVReg = operand.mVRegIdx; + rmInfo.mMode = BeMCRMMode_Invalid; + return; } - if (regA == X64Reg_None) - regA = reg; - else if (regB == X64Reg_None) - regB = reg; - return ValidateRMResult(operand, regA, regB, bScale, disp, errorVReg, BeMCRMMode_Deref, doValidate); + if (rmInfo.mRegA == X64Reg_None) + rmInfo.mRegA = reg; + else if (rmInfo.mRegB == X64Reg_None) + rmInfo.mRegB = reg; + rmInfo.mMode = BeMCRMMode_Deref; + return ValidateRMResult(operand, rmInfo, doValidate); } } else { - return BeMCRMMode_Invalid; + rmInfo.mMode = BeMCRMMode_Invalid; + return; } auto vregInfo = mVRegInfo[operand.mVRegIdx]; @@ -5502,101 +5513,114 @@ BeMCRMMode BeMCContext::GetRMParams(const BeMCOperand& operand, X64CPURegister& if (vregInfo->mRelTo) { - auto oldRegA = regA; - auto result = GetRMParams(vregInfo->mRelTo, regA, regB, bScale, disp, errorVReg, false); - if (result == BeMCRMMode_Invalid) + auto oldRegA = rmInfo.mRegA; + GetRMParams(vregInfo->mRelTo, rmInfo, false); + if (rmInfo.mMode == BeMCRMMode_Invalid) { - if ((errorVReg != NULL) && (*errorVReg == -1)) + if (rmInfo.mErrorVReg == -1) { - *errorVReg = operand.mVRegIdx; + rmInfo.mErrorVReg = operand.mVRegIdx; } - return BeMCRMMode_Invalid; + return; } - if (result == BeMCRMMode_Deref) + if (rmInfo.mMode == BeMCRMMode_Deref) { // A deref can only stand alone, and no double-derefs if ((vregInfo->mRelOffset) || (vregInfo->mRelOffsetScale != 1) || (operand.mKind == BeMCOperandKind_VRegLoad)) { - if (errorVReg != NULL) - { - BF_ASSERT(vregInfo->mRelTo.IsVRegAny()); - *errorVReg = vregInfo->mRelTo.mVRegIdx; - // For some reason we had changed this to: - //*errorVReg = operand.mVRegIdx; - // This doesn't work, it's the deref that we want to isolate, otherwise we just end up creating another invalid expression - } - return BeMCRMMode_Invalid; + + BF_ASSERT(vregInfo->mRelTo.IsVRegAny()); + rmInfo.mErrorVReg = vregInfo->mRelTo.mVRegIdx; + // For some reason we had changed this to: + //*errorVReg = operand.mVRegIdx; + // This doesn't work, it's the deref that we want to isolate, otherwise we just end up creating another invalid expression + rmInfo.mMode = BeMCRMMode_Invalid; + return; } if (operand.mKind == BeMCOperandKind_VRegAddr) - return ValidateRMResult(vregInfo->mRelTo, regA, regB, bScale, disp, errorVReg, BeMCRMMode_Direct, doValidate); + { + rmInfo.mMode = BeMCRMMode_Direct; + return ValidateRMResult(vregInfo->mRelTo, rmInfo, doValidate); + } else if (operand.mKind == BeMCOperandKind_VReg) - return ValidateRMResult(vregInfo->mRelTo, regA, regB, bScale, disp, errorVReg, BeMCRMMode_Deref, doValidate); + { + rmInfo.mMode = BeMCRMMode_Deref; + return ValidateRMResult(vregInfo->mRelTo, rmInfo, doValidate); + } else NotImpl(); } } if (vregInfo->mRelOffset) - { - bool relToComplicated = (regB != X64Reg_None) || (bScale != 1); - auto result = GetRMParams(vregInfo->mRelOffset, regA, regB, bScale, disp, errorVReg, false); - if (result == BeMCRMMode_Invalid) - { - if (errorVReg != NULL) - { - // Pick the "most complicated" between relOffset and relTo? - if (relToComplicated) - { - BF_ASSERT(vregInfo->mRelTo.IsVRegAny()); - *errorVReg = vregInfo->mRelTo.mVRegIdx; - } - else - { - BF_ASSERT(vregInfo->mRelOffset.IsVRegAny()); - *errorVReg = vregInfo->mRelOffset.mVRegIdx; - } - } - return BeMCRMMode_Invalid; - } - if (result == BeMCRMMode_Deref) // Deref only allowed on relTo - { - if (errorVReg != NULL) + { + if (vregInfo->mRelOffsetScale != 1) + rmInfo.mVRegWithScaledOffset = operand.mVRegIdx; + + bool relToComplicated = (rmInfo.mRegB != X64Reg_None) || (rmInfo.mBScale != 1); + GetRMParams(vregInfo->mRelOffset, rmInfo, false); + if (rmInfo.mMode == BeMCRMMode_Invalid) + { + // Pick the "most complicated" between relOffset and relTo? + if (relToComplicated) + { + BF_ASSERT(vregInfo->mRelTo.IsVRegAny()); + rmInfo.mErrorVReg = vregInfo->mRelTo.mVRegIdx; + } + else { BF_ASSERT(vregInfo->mRelOffset.IsVRegAny()); - *errorVReg = vregInfo->mRelOffset.mVRegIdx; - } - return BeMCRMMode_Invalid; + rmInfo.mErrorVReg = vregInfo->mRelOffset.mVRegIdx; + } + rmInfo.mMode = BeMCRMMode_Invalid; + return; + } + if (rmInfo.mMode == BeMCRMMode_Deref) // Deref only allowed on relTo + { + BF_ASSERT(vregInfo->mRelOffset.IsVRegAny()); + rmInfo.mErrorVReg = vregInfo->mRelOffset.mVRegIdx; + rmInfo.mMode = BeMCRMMode_Invalid; + return; } } bool success = true; if (vregInfo->mRelOffsetScale != 1) { - if (bScale != 1) + if (rmInfo.mBScale != 1) success = false; - bScale = vregInfo->mRelOffsetScale; - if ((bScale != 2) && (bScale != 4) && (bScale != 8)) + rmInfo.mBScale = vregInfo->mRelOffsetScale; + if ((rmInfo.mBScale != 2) && (rmInfo.mBScale != 4) && (rmInfo.mBScale != 8)) success = false; - if (regB == X64Reg_None) + if (rmInfo.mRegB == X64Reg_None) { - regB = regA; - regA = X64Reg_None; + rmInfo.mRegB = rmInfo.mRegA; + rmInfo.mRegA = X64Reg_None; } } if (!success) { - if ((errorVReg != NULL) && (*errorVReg == -1)) - *errorVReg = operand.mVRegIdx; + if (rmInfo.mErrorVReg == -1) + rmInfo.mErrorVReg = operand.mVRegIdx; } if (success) { if (operand.mKind == BeMCOperandKind_VRegLoad) - return ValidateRMResult(vregInfo->mRelOffset, regA, regB, bScale, disp, errorVReg, BeMCRMMode_Deref, doValidate); + { + rmInfo.mMode = BeMCRMMode_Deref; + return ValidateRMResult(vregInfo->mRelOffset, rmInfo, doValidate); + } else - return ValidateRMResult(vregInfo->mRelOffset, regA, regB, bScale, disp, errorVReg, BeMCRMMode_Direct, doValidate); + { + rmInfo.mMode = BeMCRMMode_Direct; + return ValidateRMResult(vregInfo->mRelOffset, rmInfo, doValidate); + } } else - return BeMCRMMode_Invalid; + { + rmInfo.mMode = BeMCRMMode_Invalid; + return; + } } void BeMCContext::DisableRegister(const BeMCOperand& operand, X64CPURegister reg) @@ -5641,24 +5665,20 @@ void BeMCContext::MarkInvalidRMRegs(const BeMCOperand& operand) void BeMCContext::GetUsedRegs(const BeMCOperand& operand, X64CPURegister& regA, X64CPURegister& regB) { - int scale = 1; - int offset = 0; - GetRMParams(operand, regA, regB, scale, offset, NULL); - if (regA != X64Reg_None) - regA = ResizeRegister(regA, 8); - if (regB != X64Reg_None) - regB = ResizeRegister(regB, 8); + BeRMParamsInfo rmInfo; + GetRMParams(operand, rmInfo); + if (rmInfo.mRegA != X64Reg_None) + regA = ResizeRegister(rmInfo.mRegA, 8); + if (rmInfo.mRegB != X64Reg_None) + regB = ResizeRegister(rmInfo.mRegB, 8); } BeMCRMMode BeMCContext::GetRMForm(const BeMCOperand& operand, bool& isMulti) { - X64CPURegister regA = X64Reg_None; - X64CPURegister regB = X64Reg_None; - int bScale = 1; - int disp = 0; - auto result = GetRMParams(operand, regA, regB, bScale, disp); - isMulti = (regB != X64Reg_None) || (disp != 0); - return result; + BeRMParamsInfo rmInfo; + GetRMParams(operand, rmInfo); + isMulti = (rmInfo.mRegB != X64Reg_None) || (rmInfo.mDisp != 0); + return rmInfo.mMode; } void BeMCContext::GetValAddr(const BeMCOperand& operand, X64CPURegister& reg, int& offset) @@ -5935,14 +5955,11 @@ void BeMCContext::EmitModRM(int rx, BeMCOperand rm, int relocOfs) if ((rm.IsVReg()) && (vregInfo->IsDirectRelToAny())) return EmitModRM(rx, vregInfo->mRelTo, relocOfs); - X64CPURegister regA = X64Reg_None; - X64CPURegister regB = X64Reg_None; - int bScale = 1; - int disp = 0; - auto resultType = GetRMParams(rm, regA, regB, bScale, disp); + BeRMParamsInfo rmInfo; + GetRMParams(rm, rmInfo); //BF_ASSERT(resultType != BeMCRMMode_Invalid); - BF_ASSERT(resultType == BeMCRMMode_Deref); - EmitModRMRel(rx, regA, regB, bScale, disp); + BF_ASSERT(rmInfo.mMode == BeMCRMMode_Deref); + EmitModRMRel(rx, rmInfo.mRegA, rmInfo.mRegB, rmInfo.mBScale, rmInfo.mDisp); return; } else @@ -5998,13 +6015,10 @@ void BeMCContext::EmitModRM_Addr(BeMCOperand r, BeMCOperand rm) auto relVRegInfo = GetVRegInfo(vregInfo->mRelTo); if (relVRegInfo->mRelTo) { - X64CPURegister regA = X64Reg_None; - X64CPURegister regB = X64Reg_None; - int bScale = 1; - int disp = 0; - auto resultType = GetRMParams(rm, regA, regB, bScale, disp); - BF_ASSERT(resultType != BeMCRMMode_Invalid); - EmitModRMRel(EncodeRegNum(r.mReg), regA, regB, bScale, disp); + BeRMParamsInfo rmInfo; + GetRMParams(rm, rmInfo); + BF_ASSERT(rmInfo.mMode != BeMCRMMode_Invalid); + EmitModRMRel(EncodeRegNum(r.mReg), rmInfo.mRegA, rmInfo.mRegB, rmInfo.mBScale, rmInfo.mDisp); return; } else @@ -8256,8 +8270,25 @@ void BeMCContext::DoActualization() { int vregIdx = inst->mArg0.mVRegIdx; auto vregInfo = GetVRegInfo(inst->mArg0); + + if (vregInfo->mWantsExprOffsetActualize) + { + vregInfo->mWantsExprOffsetActualize = false; + + auto offsetType = GetType(vregInfo->mRelOffset); + + auto scratchReg = AllocVirtualReg(offsetType, 2, false); + CreateDefineVReg(scratchReg, instIdx++); + + AllocInst(BeMCInstKind_Mov, scratchReg, vregInfo->mRelOffset, instIdx++); + AllocInst(BeMCInstKind_IMul, scratchReg, BeMCOperand::FromImmediate(vregInfo->mRelOffsetScale), instIdx++); + + vregInfo->mRelOffset = scratchReg; + vregInfo->mRelOffsetScale = 1; + } + if ((vregInfo->mWantsExprActualize) || (forceMove)) - { + { if (vregInfo->mDbgVariable != NULL) { // Wait until dbgDecl so we can potentially set to VRegAddr @@ -8289,7 +8320,7 @@ void BeMCContext::DoActualization() CreateDefineVReg(scratchReg, instIdx++ + 1); AllocInst(BeMCInstKind_Mov, BeMCOperand::FromVReg(vregIdx), scratchReg, instIdx++ + 1); } - } + } } } } @@ -8411,6 +8442,14 @@ bool BeMCContext::DoLegalization() continue; } + if (mDebugging) + { + if (inst->mArg1.mVRegIdx == 61) + { + NOP; + } + } + // Check operands if ((!inst->IsPsuedo()) && (arg0Type != NULL) && (!arg0Type->IsComposite())) { @@ -8424,17 +8463,13 @@ bool BeMCContext::DoLegalization() { bool isMulti = false; - X64CPURegister regA = X64Reg_None; - X64CPURegister regB = X64Reg_None; - int bScale = 1; - int disp = 0; - int errorVReg = -1; - auto rmForm = GetRMParams(remappedOperand, regA, regB, bScale, disp, &errorVReg); + BeRMParamsInfo rmInfo; + GetRMParams(remappedOperand, rmInfo); bool badOperand = false; bool scratchForceReg = false; - if (rmForm == BeMCRMMode_Invalid) + if (rmInfo.mMode == BeMCRMMode_Invalid) { badOperand = true; scratchForceReg = true; @@ -8455,8 +8490,8 @@ bool BeMCContext::DoLegalization() } else { - if ((rmForm == BeMCRMMode_Direct) && - ((regB != X64Reg_None) || (bScale != 1) || (disp != 0))) + if ((rmInfo.mMode == BeMCRMMode_Direct) && + ((rmInfo.mRegB != X64Reg_None) || (rmInfo.mBScale != 1) || (rmInfo.mDisp != 0))) { badOperand = true; } @@ -8502,8 +8537,13 @@ bool BeMCContext::DoLegalization() if (badOperand) { - //if (vregExprChangeSet.find(errorVReg) == vregExprChangeSet.end()) - if (!vregExprChangeSet.Contains(errorVReg)) + if ((rmInfo.mErrorVReg == -2) && (rmInfo.mVRegWithScaledOffset != -1)) + { + auto offsetVRegInfo = mVRegInfo[rmInfo.mVRegWithScaledOffset]; + offsetVRegInfo->mWantsExprOffsetActualize = true; + hasPendingActualizations = true; + } + else if (!vregExprChangeSet.Contains(rmInfo.mErrorVReg)) { auto remappedVRegInfo = mVRegInfo[remappedOperand.mVRegIdx]; BeMCOperand savedOperand = BeMCOperand::FromVReg(remappedOperand.mVRegIdx); @@ -8553,7 +8593,7 @@ bool BeMCContext::DoLegalization() replacedOpr = true; isFinalRun = false; if (debugging) - OutputDebugStrF(" BadOperand %d\n", errorVReg); + OutputDebugStrF(" BadOperand %d\n", rmInfo.mErrorVReg); } } } @@ -9039,16 +9079,13 @@ bool BeMCContext::DoLegalization() } } - X64CPURegister regA = X64Reg_None; - X64CPURegister regB = X64Reg_None; - int bScale = 1; - int disp = 0; - int errorVRegIdx = -1; - bool isValid = GetRMParams(inst->mArg0, regA, regB, bScale, disp, &errorVRegIdx) != BeMCRMMode_Invalid; + BeRMParamsInfo rmInfo; + GetRMParams(inst->mArg0, rmInfo); + bool isValid = rmInfo.mMode != BeMCRMMode_Invalid; if (!isValid) { - if (errorVRegIdx == -1) + if (rmInfo.mErrorVReg == -1) { BF_ASSERT(!vregInfo->mRelOffset); if (vregInfo->mType->IsPointer()) @@ -9074,7 +9111,7 @@ bool BeMCContext::DoLegalization() continue; } } - else if (errorVRegIdx == -2) + else if (rmInfo.mErrorVReg == -2) { vregExprChangeSet.Add(inst->mArg0.mVRegIdx); MarkInvalidRMRegs(inst->mArg0); @@ -9085,7 +9122,7 @@ bool BeMCContext::DoLegalization() } //if (vregExprChangeSet.find(errorVRegIdx) != vregExprChangeSet.end()) - if (vregExprChangeSet.Contains(errorVRegIdx)) + if (vregExprChangeSet.Contains(rmInfo.mErrorVReg)) { // This means we have already modified some dependent vregs, so we may be legalized already. // Wait till next iteration to determine that. @@ -9097,9 +9134,9 @@ bool BeMCContext::DoLegalization() // The only valid form is [*<1/2/4/8>+] // If we violate that then we have to break it up //if ((vregInfo->mRelOffsetScale != 1) && (vregInfo->mRelOffsetScale != 2) && (vregInfo->mRelOffsetScale != 4) && (vregInfo->mRelOffsetScale != 8)) - if ((!isValid) && (errorVRegIdx == inst->mArg0.mVRegIdx)) + if ((!isValid) && (rmInfo.mErrorVReg == inst->mArg0.mVRegIdx)) { - vregExprChangeSet.Add(errorVRegIdx); + vregExprChangeSet.Add(rmInfo.mErrorVReg); if ((vregInfo->mRelOffsetScale != 1) && (vregInfo->mRelOffsetScale != 2) && (vregInfo->mRelOffsetScale != 4) && (vregInfo->mRelOffsetScale != 8)) { auto relOffsetType = GetType(vregInfo->mRelOffset); @@ -9123,13 +9160,13 @@ bool BeMCContext::DoLegalization() } else if (!isValid) { - auto errorVRegInfo = mVRegInfo[errorVRegIdx]; + auto errorVRegInfo = mVRegInfo[rmInfo.mErrorVReg]; if ((errorVRegInfo->mIsExpr) && (!errorVRegInfo->IsDirectRelTo())) { errorVRegInfo->mWantsExprActualize = true; hasPendingActualizations = true; - vregExprChangeSet.Add(errorVRegIdx); + vregExprChangeSet.Add(rmInfo.mErrorVReg); isFinalRun = false; if (debugging) OutputDebugStrF(" RM not valid, actualize\n"); @@ -9173,7 +9210,7 @@ bool BeMCContext::DoLegalization() // This may be a local variable that failed to be assigned to a reg, create a scratch local with a forced reg auto scratchReg = AllocVirtualReg(errorVRegInfo->mType, 2, false); auto scratchVRegInfo = mVRegInfo[scratchReg.mVRegIdx]; - auto errorVReg = BeMCOperand::FromVReg(errorVRegIdx); + auto errorVReg = BeMCOperand::FromVReg(rmInfo.mErrorVReg); if ((vregInfo->mRelTo == errorVReg) || (vregInfo->mRelOffset == errorVReg)) { @@ -9223,44 +9260,39 @@ bool BeMCContext::DoLegalization() auto vregInfo = mVRegInfo[vregIdx]; auto dbgVar = vregInfo->mDbgVariable; - - X64CPURegister regA = X64Reg_None; - X64CPURegister regB = X64Reg_None; - int scale = 1; - int disp = 0; - BeMCRMMode mode; + BeRMParamsInfo rmInfo; if (dbgVar->mIsValue) - mode = GetRMParams(inst->mArg0, regA, regB, scale, disp); + GetRMParams(inst->mArg0, rmInfo); else { if (inst->mArg0.mKind == BeMCOperandKind_VRegAddr) - mode = GetRMParams(BeMCOperand::ToLoad(inst->mArg0), regA, regB, scale, disp); + GetRMParams(BeMCOperand::ToLoad(inst->mArg0), rmInfo); else { - mode = GetRMParams(inst->mArg0, regA, regB, scale, disp); - if ((mode != BeMCRMMode_Direct) && (scale != 1) && (disp != 0)) + GetRMParams(inst->mArg0, rmInfo); + if ((rmInfo.mMode != BeMCRMMode_Direct) && (rmInfo.mBScale != 1) && (rmInfo.mDisp != 0)) isInvalid = true; } } - if (mode == BeMCRMMode_Invalid) + if (rmInfo.mMode == BeMCRMMode_Invalid) { if (vregInfo->mType->mSize != 0) { isInvalid = true; } } - else if (mode == BeMCRMMode_Direct) + else if (rmInfo.mMode == BeMCRMMode_Direct) { - if ((regB != X64Reg_None) || (disp != 0) || (scale != 1)) + if ((rmInfo.mRegB != X64Reg_None) || (rmInfo.mDisp != 0) || (rmInfo.mBScale != 1)) { isInvalid = true; } } - else if (mode == BeMCRMMode_Deref) + else if (rmInfo.mMode == BeMCRMMode_Deref) { - if ((regB != X64Reg_None) || (scale != 1)) + if ((rmInfo.mRegB != X64Reg_None) || (rmInfo.mBScale != 1)) { isInvalid = true; } @@ -9319,12 +9351,9 @@ bool BeMCContext::DoLegalization() { auto mcArg = BeMCOperand::FromEncoded(*argIdxPtr); - X64CPURegister regA = X64Reg_None; - X64CPURegister regB = X64Reg_None; - int bScale = 1; - int disp = 0; - auto form = GetRMParams(mcArg, regA, regB, bScale, disp); - if ((form != BeMCRMMode_Direct) || (regB != X64Reg_None) || (regA == X64Reg_R11)) + BeRMParamsInfo rmInfo; + GetRMParams(mcArg, rmInfo); + if ((rmInfo.mMode != BeMCRMMode_Direct) || (rmInfo.mRegB != X64Reg_None) || (rmInfo.mRegA == X64Reg_R11)) { BeMCOperand scratchReg = AllocVirtualReg(GetType(mcArg), 2, true); auto vregInfo = GetVRegInfo(scratchReg); @@ -9346,12 +9375,9 @@ bool BeMCContext::DoLegalization() { if (inst->mArg1) { - X64CPURegister regA = X64Reg_None; - X64CPURegister regB = X64Reg_None; - int bScale = 1; - int disp = 0; - auto form = GetRMParams(inst->mArg1, regA, regB, bScale, disp); - if ((form != BeMCRMMode_Direct) || (regB != X64Reg_None) || (regA == X64Reg_R11) || (disp != 0)) + BeRMParamsInfo rmInfo; + GetRMParams(inst->mArg1, rmInfo); + if ((rmInfo.mMode != BeMCRMMode_Direct) || (rmInfo.mRegB != X64Reg_None) || (rmInfo.mRegA == X64Reg_R11) || (rmInfo.mDisp != 0)) { BeMCOperand scratchReg = AllocVirtualReg(GetType(inst->mArg1), 2, true); auto vregInfo = GetVRegInfo(scratchReg); @@ -9914,12 +9940,9 @@ bool BeMCContext::DoLegalization() isFinalRun = false; } - X64CPURegister regA = X64Reg_None; - X64CPURegister regB = X64Reg_None; - int bScale = 1; - int disp = 0; - auto form = GetRMParams(inst->mArg0, regA, regB, bScale, disp); - if (form == BeMCRMMode_Invalid) + BeRMParamsInfo rmInfo; + GetRMParams(inst->mArg0, rmInfo); + if (rmInfo.mMode == BeMCRMMode_Invalid) { if (inst->mArg0.IsSymbol()) { @@ -10081,18 +10104,14 @@ bool BeMCContext::DoLegalization() BeMCOperand& origOperand = (oprIdx == 0) ? inst->mArg0 : inst->mArg1; if (origOperand.IsVRegAny()) { - X64CPURegister regA = X64Reg_None; - X64CPURegister regB = X64Reg_None; - int bScale = 1; - int disp = 0; - int errorVReg = -1; - auto rmForm = GetRMParams(origOperand, regA, regB, bScale, disp, &errorVReg); + BeRMParamsInfo rmInfo; + GetRMParams(origOperand, rmInfo); auto vregInfo = GetVRegInfo(origOperand); bool isValid = true; if (oprIdx == 1) { - if (rmForm != BeMCRMMode_Direct) + if (rmInfo.mMode != BeMCRMMode_Direct) { auto newVReg = ReplaceWithNewVReg(origOperand, instIdx, true, true); auto newVRegInfo = GetVRegInfo(newVReg); @@ -10111,16 +10130,12 @@ bool BeMCContext::DoLegalization() BeMCOperand& origOperand = (oprIdx == 0) ? inst->mArg0 : inst->mArg1; if (origOperand.IsVRegAny()) { - X64CPURegister regA = X64Reg_None; - X64CPURegister regB = X64Reg_None; - int bScale = 1; - int disp = 0; - int errorVReg = -1; - auto rmForm = GetRMParams(origOperand, regA, regB, bScale, disp, &errorVReg); + BeRMParamsInfo rmInfo; + GetRMParams(origOperand, rmInfo); auto vregInfo = GetVRegInfo(origOperand); - if ((ResizeRegister(regA, 8) == X64Reg_RAX) || (ResizeRegister(regB, 8) == X64Reg_RAX)) + if ((ResizeRegister(rmInfo.mRegA, 8) == X64Reg_RAX) || (ResizeRegister(rmInfo.mRegB, 8) == X64Reg_RAX)) { if (!vregInfo->mIsExpr) { @@ -10150,7 +10165,7 @@ bool BeMCContext::DoLegalization() bool isValid = true; if (oprIdx == 1) { - if (rmForm != BeMCRMMode_Direct) + if (rmInfo.mMode != BeMCRMMode_Direct) { int safeIdx = FindSafeInstInsertPos(instIdx, true); auto newVReg = ReplaceWithNewVReg(origOperand, safeIdx, true, true); @@ -11396,14 +11411,11 @@ void BeMCContext::DoRegFinalization() instEndIdx = instIdx; if (inst->mKind == BeMCInstKind_Call) { - X64CPURegister regA = X64Reg_None; - X64CPURegister regB = X64Reg_None; - int bScale = 1; - int disp = 0; - GetRMParams(inst->mArg0, regA, regB, bScale, disp); + BeRMParamsInfo rmInfo; + GetRMParams(inst->mArg0, rmInfo); - if (((regA != X64Reg_None) && (regA != X64Reg_RAX) && (regStomped[regA])) || - ((regB != X64Reg_None) && (regStomped[regB]))) + if (((rmInfo.mRegA != X64Reg_None) && (rmInfo.mRegA != X64Reg_RAX) && (regStomped[rmInfo.mRegA])) || + ((rmInfo.mRegB != X64Reg_None) && (regStomped[rmInfo.mRegB]))) { BF_ASSERT(pass == 0); @@ -12159,11 +12171,8 @@ bool BeMCContext::EmitPackedXMMInst(BeMCInstForm instForm, BeMCInst* inst, uint8 void BeMCContext::EmitAggMov(const BeMCOperand& dest, const BeMCOperand& src) { - X64CPURegister regA = X64Reg_None; - X64CPURegister regB = X64Reg_None; - int bScale = 1; - int disp = 0; - auto form = GetRMParams(dest, regA, regB, bScale, disp); + BeRMParamsInfo rmInfo; + GetRMParams(dest, rmInfo); BF_ASSERT(src.mKind == BeMCOperandKind_ConstAgg); auto aggConstant = src.mConstant; @@ -12262,21 +12271,21 @@ void BeMCContext::EmitAggMov(const BeMCOperand& dest, const BeMCOperand& src) if (repSize >= 16) { bool regSaved = false; - if ((regA == X64Reg_RAX) || - (regA == X64Reg_RCX) || - (regA == X64Reg_RDI)) + if ((rmInfo.mRegA == X64Reg_RAX) || + (rmInfo.mRegA == X64Reg_RCX) || + (rmInfo.mRegA == X64Reg_RDI)) { - BF_ASSERT(regB == X64Reg_None); + BF_ASSERT(rmInfo.mRegB == X64Reg_None); // mov R11, regA Emit(0x49); Emit(0x89); - EmitModRM(BeMCOperand::FromReg(regA), BeMCOperand::FromReg(X64Reg_R11)); + EmitModRM(BeMCOperand::FromReg(rmInfo.mRegA), BeMCOperand::FromReg(X64Reg_R11)); regSaved = true; } // lea rdi, EmitREX(BeMCOperand::FromReg(X64Reg_RDI), dest, true); Emit(0x8D); - EmitModRMRel(EncodeRegNum(X64Reg_RDI), regA, regB, 1, disp + curOfs); + EmitModRMRel(EncodeRegNum(X64Reg_RDI), rmInfo.mRegA, rmInfo.mRegB, 1, rmInfo.mDisp + curOfs); // mov al, Emit(0xB0); Emit(val); @@ -12292,7 +12301,7 @@ void BeMCContext::EmitAggMov(const BeMCOperand& dest, const BeMCOperand& src) { // mov regA, R11 Emit(0x4C); Emit(0x89); - EmitModRM(BeMCOperand::FromReg(X64Reg_R11), BeMCOperand::FromReg(regA)); + EmitModRM(BeMCOperand::FromReg(X64Reg_R11), BeMCOperand::FromReg(rmInfo.mRegA)); } curOfs += repSize; @@ -12306,7 +12315,7 @@ void BeMCContext::EmitAggMov(const BeMCOperand& dest, const BeMCOperand& src) // mov , R11 EmitREX(BeMCOperand::FromReg(X64Reg_R11), dest, true); Emit(0x89); - EmitModRMRel(EncodeRegNum(X64Reg_R11), regA, regB, 1, disp + curOfs); + EmitModRMRel(EncodeRegNum(X64Reg_R11), rmInfo.mRegA, rmInfo.mRegB, 1, rmInfo.mDisp + curOfs); curOfs += 8; } @@ -12319,7 +12328,7 @@ void BeMCContext::EmitAggMov(const BeMCOperand& dest, const BeMCOperand& src) // mov , R11d EmitREX(BeMCOperand::FromReg(X64Reg_R11D), dest, false); Emit(0x89); - EmitModRMRel(EncodeRegNum(X64Reg_R11D), regA, regB, 1, disp + curOfs); + EmitModRMRel(EncodeRegNum(X64Reg_R11D), rmInfo.mRegA, rmInfo.mRegB, 1, rmInfo.mDisp + curOfs); } for (; curOfs <= memSize - 2; curOfs += 2) @@ -12331,7 +12340,7 @@ void BeMCContext::EmitAggMov(const BeMCOperand& dest, const BeMCOperand& src) // mov , R11w Emit(0x66); EmitREX(BeMCOperand::FromReg(X64Reg_R11W), dest, false); Emit(0x89); - EmitModRMRel(EncodeRegNum(X64Reg_R11W), regA, regB, 1, disp + curOfs); + EmitModRMRel(EncodeRegNum(X64Reg_R11W), rmInfo.mRegA, rmInfo.mRegB, 1, rmInfo.mDisp + curOfs); } for (; curOfs <= memSize - 1; curOfs += 1) @@ -12343,7 +12352,7 @@ void BeMCContext::EmitAggMov(const BeMCOperand& dest, const BeMCOperand& src) // mov , R11b EmitREX(BeMCOperand::FromReg(X64Reg_R11B), dest, false); Emit(0x89 - 1); - EmitModRMRel(EncodeRegNum(X64Reg_R11B), regA, regB, 1, disp + curOfs); + EmitModRMRel(EncodeRegNum(X64Reg_R11B), rmInfo.mRegA, rmInfo.mRegB, 1, rmInfo.mDisp + curOfs); } } @@ -15470,7 +15479,7 @@ void BeMCContext::Generate(BeFunction* function) mDbgPreferredRegs[32] = X64Reg_R8;*/ //mDbgPreferredRegs[8] = X64Reg_RAX; - //mDebugging = (function->mName == "?FindSourceViewPanel@IDEApp@IDE@bf@@QEAAPEAVSourceViewPanel@ui@23@PEAVString@System@3@@Z"); + //mDebugging = (function->mName == "?Main@Program@bf@@SAXPEAV?$Array1@PEAVString@System@bf@@@System@2@@Z"); // || (function->mName == "?__BfStaticCtor@roboto_font@Drawing@ClassicUO_assistant@bf@@SAXXZ") // || (function->mName == "?Hey@Blurg@bf@@SAXXZ") // ; diff --git a/IDEHelper/Backend/BeMCContext.h b/IDEHelper/Backend/BeMCContext.h index b8b83421..a28b538e 100644 --- a/IDEHelper/Backend/BeMCContext.h +++ b/IDEHelper/Backend/BeMCContext.h @@ -788,6 +788,7 @@ public: bool mDoConservativeLife; // Keep alive through 'init' as well as 'uninit' bool mIsExpr; // Not an actual value, something like 'mRelTo + mRelOffset' bool mWantsExprActualize; + bool mWantsExprOffsetActualize; bool mChainLifetimeEnd; // Kill relTo's when we are killed bool mForceMem; bool mForceReg; @@ -827,6 +828,7 @@ public: mType = NULL; mIsExpr = false; mWantsExprActualize = false; + mWantsExprOffsetActualize = false; mChainLifetimeEnd = false; mFrameOffset = INT_MIN; mHasDynLife = false; @@ -1274,6 +1276,30 @@ public: } }; +struct BeRMParamsInfo +{ + X64CPURegister mRegA; + X64CPURegister mRegB; + int mBScale; + int mDisp; + BeMCRMMode mMode; + + int mErrorVReg; + int mVRegWithScaledOffset; + + BeRMParamsInfo() + { + mRegA = X64Reg_None; + mRegB = X64Reg_None; + mBScale = 1; + mDisp = 0; + mMode = BeMCRMMode_Invalid; + + mErrorVReg = -1; + mVRegWithScaledOffset = -1; + } +}; + // This class only processes one function per instantiation class BeMCContext { @@ -1409,8 +1435,8 @@ public: uint8 EncodeRegNum(X64CPURegister regNum); int GetRegSize(int regNum); - BeMCRMMode ValidateRMResult(const BeMCOperand& operand, X64CPURegister& regA, X64CPURegister& regB, int& bScale, int& disp, int* errorVReg, BeMCRMMode result, bool doValidate = true); - BeMCRMMode GetRMParams(const BeMCOperand& operand, X64CPURegister& regA, X64CPURegister& regB, int& bScale, int& disp, int* errorVReg = NULL, bool doValidate = true); + void ValidateRMResult(const BeMCOperand& operand, BeRMParamsInfo& rmInfo, bool doValidate = true); + void GetRMParams(const BeMCOperand& operand, BeRMParamsInfo& rmInfo, bool doValidate = true); void DisableRegister(const BeMCOperand& operand, X64CPURegister reg); void MarkInvalidRMRegs(const BeMCOperand& operand); void GetUsedRegs(const BeMCOperand& operand, X64CPURegister& regA, X64CPURegister& regB); // Expands regs