Skip to content
Snippets Groups Projects
SMPInstr.cpp 554 KiB
Newer Older
				set<DefOrUse, LessDefUse>::iterator MoveUseIter = DefInst->FindUse(MoveUseOp);
				assert(MoveUseIter != DefInst->GetLastUse());
				int MoveUseSSANum = MoveUseIter->GetSSANum();
clc5q's avatar
clc5q committed
				FoundMoveZX = DefInst->IsOpSourceZeroExtendedMove(MoveUseOp, MoveUseSSANum, TruncationCheck); // recurse
			}
		}
		else if (TruncationCheck && DefInst->MDIsNonOverflowingBitManipulation()) {
clc5q's avatar
clc5q committed
			// Not a move, not a zero-extended move. We must return false for the non-truncation case,
			//  but we allow non-overflowing bit manipulation instructions in the chain for truncation checks.
			//  This is because of a benign code pattern:
			//   reg: = zero-extended move
			//   reg := reg AND bit pattern
			//   reg := reg OR bit pattern
			//   store lower bits of reg
			//  Compilers like to do 32-bit arithmetic. There was never any good reason otherwise to zero-extend the
			//   value in the first instruction in the pattern. The lower bits that are stored at the end of the code
			//   sequence are the only bits that ever mattered, so this is not really a truncation.
			set<DefOrUse, LessDefUse>::iterator BitUseIter = DefInst->FindUse(UseOp);
			if (BitUseIter != DefInst->GetLastUse()) {
				int BitUseSSANum = BitUseIter->GetSSANum();
				FoundMoveZX = DefInst->IsOpSourceZeroExtendedMove(UseOp, BitUseSSANum, true); // recurse up the chain
	return FoundMoveZX;
} // end of SMPInstr::IsOpSourceZeroExtendedMove()
// Does UseOp ultimately come from a move-with-zero-extension instruction OR from a condition code OR from a right shift?
bool SMPInstr::IsOpSourceZeroExtendedMoveShiftRightOrConditionCode(op_t UseOp, int UseSSANum, bool TruncationCheck) {
	bool UseFP = this->GetBlock()->GetFunc()->UsesFramePointer();
	if ((UseSSANum == -1) || (!MDIsDataFlowOpnd(UseOp, UseFP))) {
	bool LocalName = this->GetBlock()->IsLocalName(UseOp);
	bool IndirectMemAccess = MDIsIndirectMemoryOpnd(UseOp, UseFP);
	bool AboveStackFrame = (!RegDef && !IndirectMemAccess && (this->GetBlock()->GetFunc()->WritesAboveLocalFrame(UseOp, this->AreDefsNormalized())));
	ea_t UseAddr = this->GetAddr();
	ea_t FirstFuncAddr = this->GetBlock()->GetFunc()->GetFirstFuncAddr();
	ea_t UseDefAddr = this->GetBlock()->GetDefAddrFromUseAddr(UseOp, UseAddr, UseSSANum, LocalName);
	bool UpExposedUse = (UseDefAddr == (this->GetBlock()->GetFirstAddr() - 1));
	if (!LocalName && !AboveStackFrame && !IndirectMemAccess && ((UseDefAddr == BADADDR) || UpExposedUse)) {
		// Try to find in the function level.
		UseDefAddr = this->GetBlock()->GetFunc()->GetGlobalDefAddr(UseOp, UseSSANum);
	}

	if ((UseDefAddr == (FirstFuncAddr - 1)) || AboveStackFrame
		|| (UseDefAddr == BADADDR) || IndirectMemAccess) {
		// Cannot search for general memory DEFs; must be stack or register.
		//  FirstFuncAddr - 1 signifies the pseudo-inst to hold DEFs of regs
		//  that are LiveIn to the function; pseudo-inst is not a bitwise not.
		//  First block addr - 1 is pseudo-location that indicates live-in, UpExposed, 
		//   and LocalName means we will not find a DEF anywhere besides this block.
		//   AboveStackFrame means an incoming arg, whose DEF will not be seen.
		FoundMoveZXCC = false; 
	}
	else if (UseDefAddr < this->GetBlock()->GetFunc()->GetNumBlocks()) {
		// A block number was returned. That means the DEF is in a Phi Function.
		//  We could trace all Phi USEs and see if all of them come from zero-extended
		//  moves into the UseOp register, but we only need one of the Phi USEs to come from
		//  a zero-extended move to potentially lead to a false positive numeric error. We
		//  will recurse on all Phi USEs, declaring success if we find a single one of them
		//  to come from a zero-extended move.
		size_t BlockNum = (size_t) UseDefAddr;
		assert(!LocalName);
		SMPBasicBlock *PhiDefBlock = this->GetBlock()->GetFunc()->GetBlockByNum(BlockNum);
		assert(NULL != PhiDefBlock);
		if (!PhiDefBlock->IsProcessed()) { // Prevent infinite recursion
			set<SMPPhiFunction, LessPhi>::iterator DefPhiIter = PhiDefBlock->FindPhi(UseOp);
			assert(DefPhiIter != PhiDefBlock->GetLastPhi());
			size_t PhiListSize = DefPhiIter->GetPhiListSize();
			PhiDefBlock->SetProcessed(true); // Prevent infinite recursion
			for (size_t UseIndex = 0; UseIndex < PhiListSize; ++UseIndex) {
				int PhiUseSSANum = DefPhiIter->GetUseSSANum(UseIndex);
				if (this->IsOpSourceZeroExtendedMoveShiftRightOrConditionCode(UseOp, PhiUseSSANum, TruncationCheck)) {
					FoundMoveZXCC = true; // only one success on all Phi USEs is needed
					break;
				}
			}
		}
	}
	else {
		SMPInstr *DefInst = this->GetBlock()->GetFunc()->GetInstFromAddr(UseDefAddr);
		unsigned short SignMask;
		if (DefInst->MDIsSignedLoad(SignMask)) {
			FoundMoveZXCC = (FG_MASK_UNSIGNED == SignMask);
		}
		else if (DefInst->MDIsAnySetValue() || DefInst->MDIsShiftRight()) {
			FoundMoveZXCC = true;
		}
		else if (DefInst->MDIsMoveInstr()) {
			op_t MoveUseOp = DefInst->GetMoveSource();
			if (MDIsDataFlowOpnd(MoveUseOp, UseFP)) { // pattern is simple; don't try to follow through non-stack memory
				CanonicalizeOpnd(MoveUseOp);
				set<DefOrUse, LessDefUse>::iterator MoveUseIter = DefInst->FindUse(MoveUseOp);
				assert(MoveUseIter != DefInst->GetLastUse());
				int MoveUseSSANum = MoveUseIter->GetSSANum();
				FoundMoveZXCC = DefInst->IsOpSourceZeroExtendedMoveShiftRightOrConditionCode(MoveUseOp, MoveUseSSANum, TruncationCheck); // recurse
			}
		}
clc5q's avatar
clc5q committed
		else if (TruncationCheck && (DefInst->MDIsNonOverflowingBitManipulation() || DefInst->MDIsSmallAdditionOrSubtraction())) {
			// Not a move, not a zero-extended move. We must return false for the non-truncation case,
			//  but we allow non-overflowing bit manipulation instructions in the chain for truncation checks.
			//  This is because of a benign code pattern:
			//   reg: = zero-extended move
			//   reg := reg AND bit pattern
			//   reg := reg OR bit pattern
			//   store lower bits of reg
			//  Compilers like to do 32-bit arithmetic. There was never any good reason otherwise to zero-extend the
			//   value in the first instruction in the pattern. The lower bits that are stored at the end of the code
			//   sequence are the only bits that ever mattered, so this is not really a truncation.
clc5q's avatar
clc5q committed
			// NOTE: We combine into this case additions or subtractions of small values, as they only operate on the
			//  lower bits of the register.
			set<DefOrUse, LessDefUse>::iterator BitUseIter = DefInst->FindUse(UseOp);
			if (BitUseIter != DefInst->GetLastUse()) {
				int BitUseSSANum = BitUseIter->GetSSANum();
				FoundMoveZXCC = DefInst->IsOpSourceZeroExtendedMoveShiftRightOrConditionCode(UseOp, BitUseSSANum, true); // recurse up the chain
			}
		}
		else {
			FoundMoveZXCC = false;
		}
	}

	return FoundMoveZXCC;
} // end of SMPInstr::IsOpSourceZeroExtendedMoveShiftRightOrConditionCode()
// Trace through moves to any of the above cases, return source inst
bool SMPInstr::IsOpSourceSpecial(op_t UseOp, int UseSSANum, bool TruncationCheck, ea_t &SourceInstAddr) {
	bool UseFP = this->GetBlock()->GetFunc()->UsesFramePointer();
	if ((UseSSANum == -1) || (!MDIsDataFlowOpnd(UseOp, UseFP))) {
		return false;
	}

	bool FoundMoveNotZXCCSubreg = false;
	bool RegDef = (o_reg == UseOp.type);
	bool LocalName = this->GetBlock()->IsLocalName(UseOp);
	bool IndirectMemAccess = MDIsIndirectMemoryOpnd(UseOp, UseFP);
	bool AboveStackFrame = (!RegDef && !IndirectMemAccess && (this->GetBlock()->GetFunc()->WritesAboveLocalFrame(UseOp, this->AreDefsNormalized())));
	ea_t UseAddr = this->GetAddr();
	ea_t FirstFuncAddr = this->GetBlock()->GetFunc()->GetFirstFuncAddr();
	ea_t UseDefAddr = this->GetBlock()->GetDefAddrFromUseAddr(UseOp, UseAddr, UseSSANum, LocalName);
	bool UpExposedUse = (UseDefAddr == (this->GetBlock()->GetFirstAddr() - 1));

	if (!LocalName && !AboveStackFrame && !IndirectMemAccess && ((UseDefAddr == BADADDR) || UpExposedUse)) {
		// Try to find in the function level.
		UseDefAddr = this->GetBlock()->GetFunc()->GetGlobalDefAddr(UseOp, UseSSANum);
	}

	if ((UseDefAddr == (FirstFuncAddr - 1)) || AboveStackFrame
		|| (UseDefAddr == BADADDR) || IndirectMemAccess) {
		// Cannot search for general memory DEFs; must be stack or register.
		//  FirstFuncAddr - 1 signifies the pseudo-inst to hold DEFs of regs
		//  that are LiveIn to the function; pseudo-inst is not a bitwise not.
		//  First block addr - 1 is pseudo-location that indicates live-in, UpExposed, 
		//   and LocalName means we will not find a DEF anywhere besides this block.
		//   AboveStackFrame means an incoming arg, whose DEF will not be seen.
		FoundMoveNotZXCCSubreg = false; 
	}
	else if (UseDefAddr < this->GetBlock()->GetFunc()->GetNumBlocks()) {
		// A block number was returned. That means the DEF is in a Phi Function.
		//  We could trace all Phi USEs and see if all of them come from zero-extended
		//  moves into the UseOp register, but we only need one of the Phi USEs to come from
		//  a zero-extended move to potentially lead to a false positive numeric error. We
		//  will recurse on all Phi USEs, declaring success if we find a single one of them
		//  to come from a zero-extended move.
		size_t BlockNum = (size_t) UseDefAddr;
		assert(!LocalName);
		SMPBasicBlock *PhiDefBlock = this->GetBlock()->GetFunc()->GetBlockByNum(BlockNum);
		assert(NULL != PhiDefBlock);
		if (!PhiDefBlock->IsProcessed()) { // Prevent infinite recursion
			set<SMPPhiFunction, LessPhi>::iterator DefPhiIter = PhiDefBlock->FindPhi(UseOp);
			assert(DefPhiIter != PhiDefBlock->GetLastPhi());
			size_t PhiListSize = DefPhiIter->GetPhiListSize();
			PhiDefBlock->SetProcessed(true); // Prevent infinite recursion
			for (size_t UseIndex = 0; UseIndex < PhiListSize; ++UseIndex) {
				int PhiUseSSANum = DefPhiIter->GetUseSSANum(UseIndex);
				if (this->IsOpSourceSpecial(UseOp, PhiUseSSANum, TruncationCheck, SourceInstAddr)) {
					FoundMoveNotZXCCSubreg = true; // only one success on all Phi USEs is needed
					break;
				}
			}
		}
	}
	else {
		SMPInstr *DefInst = this->GetBlock()->GetFunc()->GetInstFromAddr(UseDefAddr);
		unsigned short SignMask;
		if (DefInst->MDIsSignedLoad(SignMask)) {
			FoundMoveNotZXCCSubreg = ((FG_MASK_UNSIGNED == SignMask) || TruncationCheck); // Truncation chain cares if source was reduced width.
			if (FoundMoveNotZXCCSubreg) {
				SourceInstAddr = DefInst->GetAddr();
			}
		}
		else if (DefInst->MDIsAnySetValue() || DefInst->MDIsShiftRight() || DefInst->MDIsBitwiseNotOpcode()) {
			FoundMoveNotZXCCSubreg = true;
			SourceInstAddr = DefInst->GetAddr();
		}
		else if (DefInst->MDIsMoveInstr()) {
			op_t MoveUseOp = DefInst->GetMoveSource();
			if (MDIsDataFlowOpnd(MoveUseOp, UseFP)) { // pattern is simple; don't try to follow through non-stack memory
				CanonicalizeOpnd(MoveUseOp);
				set<DefOrUse, LessDefUse>::iterator MoveUseIter = DefInst->FindUse(MoveUseOp);
				assert(MoveUseIter != DefInst->GetLastUse());
				int MoveUseSSANum = MoveUseIter->GetSSANum();
				FoundMoveNotZXCCSubreg = DefInst->IsOpSourceSpecial(MoveUseOp, MoveUseSSANum, TruncationCheck, SourceInstAddr); // recurse
			}
		}
		else if (TruncationCheck && (DefInst->MDIsNonOverflowingBitManipulation() || DefInst->MDIsSmallAdditionOrSubtraction())) {
			// Not a move, not a zero-extended move. We must return false for the non-truncation case,
			//  but we allow non-overflowing bit manipulation instructions in the chain for truncation checks.
			//  This is because of a benign code pattern:
			//   reg: = zero-extended move
			//   reg := reg AND bit pattern
			//   reg := reg OR bit pattern
			//   store lower bits of reg
			//  Compilers like to do 32-bit arithmetic. There was never any good reason otherwise to zero-extend the
			//   value in the first instruction in the pattern. The lower bits that are stored at the end of the code
			//   sequence are the only bits that ever mattered, so this is not really a truncation.
			// NOTE: We combine into this case additions or subtractions of small values, as they only operate on the
			//  lower bits of the register.
			set<DefOrUse, LessDefUse>::iterator BitUseIter = DefInst->FindUse(UseOp);
			if (BitUseIter != DefInst->GetLastUse()) {
				int BitUseSSANum = BitUseIter->GetSSANum();
				FoundMoveNotZXCCSubreg = DefInst->IsOpSourceSpecial(UseOp, BitUseSSANum, true, SourceInstAddr); // recurse up the chain
			}
		}
clc5q's avatar
clc5q committed
		else if (TruncationCheck) {
			// Check for reduced-width arithmetic.
			if (DefInst->IsReducedWidthDef()) { // chain like sub cl,3; mov eax,ecx; then "truncating" move of al
				FoundMoveNotZXCCSubreg = true;
				SourceInstAddr = DefInst->GetAddr();
			}
		}
	}

	return FoundMoveNotZXCCSubreg;
} // end of SMPInstr::IsOpSourceSpecial()

// Is opcode a shift or rotate?
// NOTE: We omit MMX/SSE unit shifts that do not use a general purpose
//  register as a shift counter, because right now this method is only
//  used as a helper for IsSubRegUsedAsShiftCount().
bool SMPInstr::MDIsShiftOrRotate(void) const {
	return (((NN_rcl <= SMPcmd.itype) && (NN_ror >= SMPcmd.itype))
		|| ((NN_sal <= SMPcmd.itype) && (NN_shr >= SMPcmd.itype))
		|| (NN_shld == SMPcmd.itype) || (NN_shrd == SMPcmd.itype));
} // end of SMPInstr::MDIsShiftOrRotate()
// Is opcode a shift to the right?
bool SMPInstr::MDIsShiftRight(void) const {
	return ((NN_sar == SMPcmd.itype) || (NN_shr == SMPcmd.itype));
}

// Does the shift or rotate RTL move the upper HalfBitWidth bits
//  into the lower half of the register? Or, if MustBeHalfRegWidth is false,
//  do we shift right by HalfBitWidth bits?
bool SMPInstr::ShiftMakesUpperBitsLower(size_t HalfBitWidth, bool MustBeHalfRegWidth) {
	if (!MustBeHalfRegWidth || (MD_NORMAL_MACHINE_BITWIDTH == (HalfBitWidth * 2))) {
		SMPRegTransfer *CurrRT = this->RTL.GetRT(0);
		if ((NULL != CurrRT) && (CurrRT->HasRightSubTree())) {
			CurrRT = CurrRT->GetRightTree();
			SMPoperator CurrOper =  CurrRT->GetOperator();
			bool LeftRotate = (SMP_ROTATE_LEFT == CurrOper);
			if ((SMP_U_RIGHT_SHIFT == CurrOper) || (SMP_S_RIGHT_SHIFT == CurrOper)
				|| LeftRotate || (SMP_ROTATE_RIGHT == CurrOper)) {
				if (CurrRT->HasRightSubTree()) { // double-word shift
					CurrRT = CurrRT->GetRightTree();
				}
				assert(!(CurrRT->HasRightSubTree()));
				op_t ShiftCount = CurrRT->GetRightOperand();
				if (o_imm == ShiftCount.type) {
					uval_t ImmVal = ShiftCount.value;
					// If we rotate left by e.g. 32-HalfBitWidth bits, then we are processing
					//  bytes or halfregs one at a time; if we rotate or shift right by HalfBitWidth,
					//  we are processing the register one HalfBitWidth at a time. We also a
					if (MustBeHalfRegWidth || (!LeftRotate)) {
						FullCircle = (HalfBitWidth == ImmVal);
					}
					else {
						// Left rotate amount plus HalfBitWidth must add up to full register width
						FullCircle = (MD_NORMAL_MACHINE_BITWIDTH == (ImmVal + HalfBitWidth));
					}
				}
			}
		}
	}
	return FullCircle;
} // SMPInstr::ShiftMakesUpperBitsLower()

#if 0
// Find SearchDelta in StackDeltaSet, inserting it if not found. Return whether it was initially found.
bool SMPInstr::FindStackPtrDelta(sval_t SearchDelta) const {
	bool found = (this->StackDeltaSet.find(SearchDelta) != this->StackDeltaSet.end());
	if (!found) {
		this->StackDeltaSet.insert(SearchDelta);
		if (SearchDelta < this->StackPtrOffset) {
			// Mimic IDA Pro, which seems to keep the biggest stack frame possible.
			//  With negative stack deltas, this means the smallest stack delta is kept.
			this->SetStackPtrOffset(SearchDelta);
		}
	}
	return found;
} // end of SMPInstr::FindStackPtrDelta()
#endif

// Set the type of all immediate operands found in the USE set.
// Set all flags and floating point register USEs and DEFs to NUMERIC also,
//  along with easily determined types for special cases.
void SMPInstr::SetImmedTypes(bool UseFP) {
	set<DefOrUse, LessDefUse>::iterator CurrUse;
	set<DefOrUse, LessDefUse>::iterator CurrDef;
	bool DebugFlag = false;
#if SMP_VERBOSE_DEBUG_BUILD_RTL
	DebugFlag = DebugFlag || (this->address == 0x805cd52) || (this->address == 0x805cd56);
	DebugFlag |= (0 == strncmp("__libc_csu_fini", this->BasicBlock->GetFunc()->GetFuncName(), 15));
#endif

	CurrUse = this->GetFirstUse();
	while (CurrUse != this->GetLastUse()) {
		UseOp = CurrUse->GetOp();
		if (DebugFlag) {
			PrintOperand(UseOp);
		if (o_imm == UseOp.type) {
			ImmVal = UseOp.value;
			if (IsImmedGlobalAddress((ea_t) ImmVal)) {
				if (DebugFlag) SMP_msg("Setting to GLOBALPTR\n");
				CurrUse = this->SetUseType(UseOp, GLOBALPTR);
#if 0
			else if (IsDataAddress((ea_t) ImmVal)) {
				// NOTE: We must call IsDataAddress() before we call IsImmedCodeAddress()
				//  to catch the data addresses within the code address range.
				if (DebugFlag) SMP_msg("Setting to POINTER\n");
				CurrUse = this->SetUseType(UseOp, POINTER);
			}
#endif
			else if (this->MDIsInterruptCall() || IsImmedCodeAddress((ea_t) ImmVal)) {
				if (DebugFlag) SMP_msg("Setting to CODEPTR\n");
				CurrUse = this->SetUseType(UseOp, CODEPTR);
				if (DebugFlag) SMP_msg("Setting to NUMERIC\n");
				CurrUse = this->SetUseType(UseOp, NUMERIC);
		else if (o_reg == UseOp.type) {
			if (UseOp.is_reg(X86_FLAGS_REG)) {
				if (DebugFlag) SMP_msg("Setting flags reg to NUMERIC\n");
				CurrUse = this->SetUseType(UseOp, NUMERIC);
			}
#if 1
			else if (MDIsStackOrFramePointerReg(UseOp, UseFP)) {
				if (DebugFlag) SMP_msg("Setting reg to STACKPTR\n");
				CurrUse = this->SetUseType(UseOp, STACKPTR);
			}
#endif
		}
#if 0  // could these registers have pointers in them?
		else if ((o_trreg == UseOp.type) ||(o_dbreg == UseOp.type) || (o_crreg == UseOp.type)) {
			if (DebugFlag) SMP_msg("Setting special reg to NUMERIC\n");
			CurrUse = this->SetUseType(UseOp, NUMERIC);
		}
#endif
		else if ((o_fpreg == UseOp.type) || (o_mmxreg == UseOp.type) || (o_xmmreg == UseOp.type)) {
			if (DebugFlag) SMP_msg("Setting floating point reg to NUMERIC\n");
			CurrUse = this->SetUseType(UseOp, NUMERIC);
		}
		else if ((o_mem == UseOp.type) || (o_phrase == UseOp.type) || (o_displ == UseOp.type)) {
			// For memory operands, we need to identify the POINTER value that
			//  is used in the addressing mode, if possible.
			(void) this->MDFindPointerUse(UseOp, UseFP);
		}
		++CurrUse;
	} // end while all USEs via CurrUse

	CurrDef = this->GetFirstDef();
	while (CurrDef != this->GetLastDef()) {
		DefOp = CurrDef->GetOp();
		if (DebugFlag) {
			PrintOperand(DefOp);
		if (DebugFlag) SMP_msg("FuncName: %s\n", this->BasicBlock->GetFunc()->GetFuncName());
		if (o_reg == DefOp.type) {
			if (DefOp.is_reg(X86_FLAGS_REG)) {
				if (DebugFlag) SMP_msg("Setting flags reg DEF to NUMERIC\n");
				CurrDef = this->SetDefType(DefOp, NUMERIC);
				// No need to propagate this DEF type, as all flags will become NUMERIC.
			else if (MDIsStackOrFramePointerReg(DefOp, UseFP)) {
				if (DebugFlag) SMP_msg("Setting reg DEF to STACKPTR\n");
				CurrDef = this->SetDefType(DefOp, STACKPTR);
				assert(CurrDef != this->Defs.GetLastRef());
				// No need to propagate; all stack and frame pointers will become STACKPTR.
		else if ((o_fpreg == DefOp.type) || (o_mmxreg == DefOp.type) || (o_xmmreg == DefOp.type)) {
			if (DebugFlag) SMP_msg("Setting floating point reg DEF to NUMERIC\n");
			CurrDef = this->SetDefType(DefOp, NUMERIC);
			// No need to propagate; all FP reg uses will become NUMERIC anyway.
		}
#if 0  // could these registers have pointers in them?
		else if ((o_trreg == DefOp.type) || (o_dbreg == DefOp.type) || (o_crreg == DefOp.type)) {
			if (DebugFlag) SMP_msg("Setting special reg DEF to NUMERIC\n");
			CurrDef = this->SetDefType(DefOp, NUMERIC);
		}
#endif	
		else if ((o_mem == DefOp.type) || (o_phrase == DefOp.type) || (o_displ == DefOp.type)) {
			// For memory operands, we need to identify the POINTER value that
			//  is used in the addressing mode, if possible.
			(void) this->MDFindPointerUse(DefOp, UseFP);
		}
		++CurrDef;
	} // end while all DEFs via CurrDef
	return;
} // end of SMPInstr::SetImmedTypes()

// Is the instruction a load from the stack?
void SMPInstr::MDFindLoadFromStack(bool UseFP) {
	set<DefOrUse, LessDefUse>::iterator UseIter;
	op_t UseOp;

	if ((3 == this->OptType) && (this->HasSourceMemoryOperand())) {
		// Loads and stores are OptCategory 3. We want only loads from the stack.
		for (UseIter = this->GetFirstUse(); UseIter != this->GetLastUse(); ++UseIter) {
			UseOp = UseIter->GetOp();
			if (MDIsStackAccessOpnd(UseOp, UseFP)) {
				this->SetLoadFromStack();
				break;
			}
		}
	}
	return;
} // end of SMPInstr::MDFindLoadFromStack()

// Determine if instr is inherently signed load instruction.
//  True if sign or zero-extended; pass out mask bits if true.
bool SMPInstr::MDIsSignedLoad(unsigned short &SignMask) {
	unsigned short opcode = this->SMPcmd.itype;
	if (NN_movzx == opcode) {
		SignMask = FG_MASK_UNSIGNED;
	}
	else if (NN_movsx == opcode) {
		SignMask = FG_MASK_SIGNED;
	}
	else {
		return false;
	}
	return true;
}

// true if increment or addition of small positive immediate value
#define STARS_SMALL_POS_VALUE_LIMIT 16
bool SMPInstr::MDIsSmallPositiveAddition(void) {
	unsigned short opcode = this->SMPcmd.itype;
	bool found = (NN_inc == opcode);
clc5q's avatar
clc5q committed
	uval_t ImmVal;
	if (!found && ((NN_add == opcode) || (NN_adc == opcode))) {
		set<DefOrUse, LessDefUse>::iterator UseIter;
		for (UseIter = this->GetFirstUse(); UseIter != this->GetLastUse(); ++UseIter) {
			op_t UseOp = UseIter->GetOp();
			if (o_imm == UseOp.type) {
clc5q's avatar
clc5q committed
				ImmVal = UseOp.value;
				if ((ImmVal <= STARS_SMALL_POS_VALUE_LIMIT) && (0 < ImmVal)) {
					found = true;
					break;
				}
			}
		}
	}
clc5q's avatar
clc5q committed
	else if (this->MDIsLoadEffectiveAddressInstr()) {
		// See if we have the form: lea reg1,[reg2+const]
		SMPRegTransfer *CurrRT = this->RTL.GetRT(0);
		if (CurrRT->HasRightSubTree()) {
			CurrRT = CurrRT->GetRightTree();
			SMPoperator CurrOp = CurrRT->GetOperator();
			if ((SMP_ADD == CurrOp) && (!CurrRT->HasRightSubTree())) {
				op_t RightOp = CurrRT->GetRightOperand();
				if (o_imm == RightOp.type) {
					ImmVal = RightOp.value;
					if ((ImmVal <= STARS_SMALL_POS_VALUE_LIMIT) && (0 < ImmVal)) {
						found = true;
					}
				}
			}
		}
	}

	return found;
} // end of SMPInstr::MDIsSmallPositiveAddition()

// true if increment, decrement, or addition or subtraction of small immediate value
bool SMPInstr::MDIsSmallAdditionOrSubtraction(void) {
	unsigned short opcode = this->SMPcmd.itype;
	bool found = ((NN_inc == opcode) || (NN_dec == opcode));

	if ((NN_add == opcode) || (NN_adc == opcode) || (NN_sub == opcode) || (NN_sbb == opcode)) {
		set<DefOrUse, LessDefUse>::iterator UseIter;
		for (UseIter = this->GetFirstUse(); !found && (UseIter != this->GetLastUse()); ++UseIter) {
			op_t UseOp = UseIter->GetOp();
			if (o_imm == UseOp.type) {
				uval_t ImmVal = UseOp.value;
				int SignedImmVal = (int) ImmVal;
				found = ((SignedImmVal >= (-STARS_SMALL_POS_VALUE_LIMIT)) && (SignedImmVal <= STARS_SMALL_POS_VALUE_LIMIT));
			}
		}
	}

	return found;
} // end of SMPInstr::MDIsSmallAdditionOrSubtraction()

// Inst is move or register clear.
bool SMPInstr::MDIsSimpleAssignment(bool &ValueFound, uval_t &ConstValue) {
	bool Simple = false;
	if (this->IsRegClearIdiom()) {
		Simple = true;
		ValueFound = true;
		ConstValue = 0;
	}
	else if (this->MDIsMoveInstr()) {
		Simple = true;
		if (o_imm == this->MoveSource.type) {
			ValueFound = true;
			ConstValue = this->MoveSource.value;
		}
	}

	return Simple;
} // end of SMPInstr::MDIsSimpleAssignment()

// Inst clears register or adds or subtracts small immediate value, as is done with counter variables.
bool SMPInstr::IsCounterOperation(void) {
	bool CounterOperation = false;
	bool ImmedValueFound = false;
	uval_t ConstValue = 1;
	if (this->MDIsSimpleAssignment(ImmedValueFound, ConstValue)) {
		CounterOperation = (ImmedValueFound && (0 == ConstValue));
	}
	else {
		CounterOperation = this->MDIsSmallAdditionOrSubtraction();
	}

	return CounterOperation;
} // end of SMPInstr::IsCounterOperation()

clc5q's avatar
clc5q committed
// Inst does an AND, OR, XOR operation; does not do add, subtract, etc.
bool SMPInstr::MDIsNonOverflowingBitManipulation(void) const {
	unsigned short opcode = this->SMPcmd.itype;
	return ((NN_and == opcode) || (NN_or == opcode) || (NN_shl == opcode)
clc5q's avatar
clc5q committed
		|| ((NN_xor == opcode) && !this->IsRegClearIdiom()));
} // end of SMPInstr::MDIsNonOverflowingBitManipulation()

// return true if traced USE to a constant value
bool SMPInstr::FindConstantValue(set<DefOrUse, LessDefUse>::iterator UseIter, uval_t &ConstValue) {
	bool FoundConst = false;
	assert(UseIter != this->GetLastUse());
	op_t UseOp = UseIter->GetOp();
	if (UseOp.type == o_imm) {
		ConstValue = UseOp.value;
		FoundConst = true;
	}
	else {
		bool UseFP = this->GetBlock()->GetFunc()->UsesFramePointer();
		if ((o_reg == UseOp.type) || MDIsDirectStackAccessOpnd(UseOp, UseFP)) {
			// We can trace registers and stack locations through SSA chains, if the stack location is directly accessed.
			int UseSSANum = UseIter->GetSSANum();
			bool LocalName = this->GetBlock()->IsLocalName(UseOp);
			ea_t UseAddr = this->GetAddr();
			ea_t UseDefAddr = this->GetBlock()->GetDefAddrFromUseAddr(UseOp, UseAddr, UseSSANum, LocalName);
clc5q's avatar
clc5q committed
			if (UseDefAddr < this->GetBlock()->GetFunc()->GetNumBlocks()) {
				// A block number was returned. That means the DEF is in a Phi Function.
				//  We could trace all Phi USEs and see if all of them come from a single 
				//  constant value, but this is highly unlikely. Terminate search.
				;
			}
			else if ((UseDefAddr == (this->GetBlock()->GetFirstAddr() - 1)) || (BADADDR == UseDefAddr)) {
				// The DEF is in a Phi function in the current block, or is BADADDR. Terminate search.
				;
			}
			else {
				SMPInstr *DefInst = this->GetBlock()->GetFunc()->GetInstFromAddr(UseDefAddr);
				bool ValueFound = false;
				if (DefInst->MDIsSimpleAssignment(ValueFound, ConstValue)) {
					if (ValueFound) {
						FoundConst = true; // ConstValue holds the value that was found.
					}
					else {
						set<DefOrUse, LessDefUse>::iterator NewUseIter = DefInst->GetFirstUse();
						// A simple assignment should have only one USE. Recurse on that USE.
						FoundConst = DefInst->FindConstantValue(NewUseIter, ConstValue);
					}
				}
			}
		}
	}

	return FoundConst;
} // end of SMPInstr::FindConstantValue()


// Infer sign, bit width, other type info for simple cases where all the info needed is
//  within the instruction or can be read from the FineGrainedStackTable in the SMPFunction.
// NOTE: Must be called after SSA analysis is complete.
void SMPInstr::MDSetWidthSignInfo(bool UseFP) {
	set<DefOrUse, LessDefUse>::iterator UseIter;
	set<DefOrUse, LessDefUse>::iterator DefIter;
	op_t UseOp, DefOp;
	struct FineGrainedInfo FGEntry;
	unsigned short SignMask, TempSign, WidthMask;
	int DefHashValue, UseHashValue;
	ea_t DefAddr;  // for flags USE in conditional set
	int SSANum;    // for flags USE in conditional set
	bool LocalFlags;  // is flags register a local name?
	bool case1, case2, case3, case4, case5, case6, case7, case8;
	bool SignedSetOpcode = this->MDIsSignedSetValue();
	bool UnsignedSetOpcode = this->MDIsUnsignedSetValue();

	case1 = this->IsLoadFromStack();
	case2 = this->MDIsSignedLoad(SignMask); // sets value of SignMask if it returns true
	case3 = (7 == this->OptType);  // Multiplies and divides
	case4 = ((CALL == this->GetDataFlowType()) || (INDIR_CALL == this->GetDataFlowType()));
	case5 = (SignedSetOpcode || UnsignedSetOpcode); // set boolean based on flag condition
	case6 = this->MDDoublesWidth(); // convert byte to word, word to dword, etc.
	case7 = this->MDAlwaysUnsignedDEF();
	case8 = this->MDAlwaysSignedDEF();

	// Case 1: Load from stack location.
		bool success = false;
		for (UseIter = this->GetFirstUse(); UseIter != this->GetLastUse(); ++UseIter) {
			UseOp = UseIter->GetOp();
			if (MDIsStackAccessOpnd(UseOp, UseFP)) {
				// Found the stack location being loaded into a register. Now we need
				//  to get the sign and width info from the fine grained stack frame
				//  analysis.
				success = this->GetBlock()->GetFunc()->MDGetFGStackLocInfo(this->address, UseOp, FGEntry);
				assert(success);
				// Now we have signedness info in FGEntry. We need to OR it into the register target of the load.
				if (FGEntry.SignMiscInfo == 0) 
					break; // nothing to OR in; save time
				for (DefIter = this->GetFirstDef(); DefIter != this->GetLastDef(); ++DefIter) {
					DefOp = DefIter->GetOp();
					if (o_reg == DefOp.type) {
						CanonicalizeOpnd(DefOp);
						TempSign = FGEntry.SignMiscInfo & FG_MASK_SIGNEDNESS_BITS; // Get both sign bit flags
						DefHashValue = HashGlobalNameAndSSA(DefOp, DefIter->GetSSANum());
						if (this->BasicBlock->IsLocalName(DefOp)) {
							this->BasicBlock->UpdateDefSignMiscInfo(DefHashValue, TempSign);
						}
						else {
							this->BasicBlock->GetFunc()->UpdateDefSignMiscInfo(DefHashValue, TempSign);
						}
						break;  // Should be only one register target for stack load, and no flags are set.
					}
				}
				break; // Only concerned with the stack operand
			}
		}
		assert(success);
	} // end if this->IsLoadFromStack()

	// Case 2: Loads that are sign-extended or zero-extended imply signed and unsigned, respectively.
	//  NOTE: If from the stack, they were handled in Case 1, and the signedness of the stack location
	//  was recorded a long time ago in SMPFunction::FindOutgoingArgsSize();
		DefIter = this->GetFirstDef();
		while (DefIter != this->GetLastDef()) {
			// All non-memory DEFs besides the flags register should get the new SignMask ORed in.
			// On x86, there should only be one DEF for this move, and no flags, but we will generalize
			//  in case other architectures are odd.
			DefOp = DefIter->GetOp();
			if (!(IsMemOperand(DefOp) || MDIsFlagsReg(DefOp))) {
				CanonicalizeOpnd(DefOp);
				DefHashValue = HashGlobalNameAndSSA(DefOp, DefIter->GetSSANum());
				if (this->BasicBlock->IsLocalName(DefOp)) {
					this->BasicBlock->UpdateDefSignMiscInfo(DefHashValue, SignMask);
				}
				else {
					this->BasicBlock->GetFunc()->UpdateDefSignMiscInfo(DefHashValue, SignMask);
				}
			}
			++DefIter;
		}

		// If the signed load is from memory, the only USEs are the memory
		//  operand and addressing registers. We do not want to claim that
		//  EBX is signed in the instruction movsx eax,[ebx]. Only the DEF
		//  register EAX and the memory location [EBX] are signed, and we
		//  have no idea where [EBX] is, so we punt on all USEs if we have
		//  a memory source operand.
		if (!(this->HasSourceMemoryOperand())) {
			UseIter = this->GetFirstUse();
			while (UseIter != this->GetLastUse()) {
				// All non-memory USEs besides the flags register should get the new SignMask ORed in.
				UseOp = UseIter->GetOp();
				if (!(IsMemOperand(UseOp) || MDIsFlagsReg(UseOp))) {
					CanonicalizeOpnd(UseOp);
					UseHashValue = HashGlobalNameAndSSA(UseOp, UseIter->GetSSANum());
					if (this->BasicBlock->IsLocalName(UseOp)) {
						this->BasicBlock->UpdateUseSignMiscInfo(UseHashValue, SignMask);
					}
					else {
						this->BasicBlock->GetFunc()->UpdateUseSignMiscInfo(UseHashValue, SignMask);
					}
	// Case 3: multiplies and divides can be signed or unsigned.
	else if (case3) { // Multiplies and divides are type 7.
		if (this->MDIsSignedArithmetic()) {
			SignMask = FG_MASK_SIGNED;
		}
		else if (this->MDIsUnsignedArithmetic()) {
		else {
			SignMask = 0; // unknown, uninitialized
		}
		if (0 != SignMask) {
			DefIter = this->GetFirstDef();
			while (DefIter != this->GetLastDef()) {
				// All DEFs besides the flags register should get the new SignMask ORed in.
				DefOp = DefIter->GetOp();
				if ((DefOp.type == o_reg) && (!(DefOp.is_reg(X86_FLAGS_REG)))) {
					CanonicalizeOpnd(DefOp);
					DefHashValue = HashGlobalNameAndSSA(DefOp, DefIter->GetSSANum());
					if (this->BasicBlock->IsLocalName(DefOp)) {
						this->BasicBlock->UpdateDefSignMiscInfo(DefHashValue, SignMask);
					}
					else {
						this->BasicBlock->GetFunc()->UpdateDefSignMiscInfo(DefHashValue, SignMask);
					}
			UseIter = this->GetFirstUse();
			while (UseIter != this->GetLastUse()) {
				// All USEs besides the flags register should get the new SignMask ORed in.
				UseOp = UseIter->GetOp();
				if ((UseOp.type == o_reg) && (!(UseOp.is_reg(X86_FLAGS_REG)))) {
					CanonicalizeOpnd(UseOp);
					UseHashValue = HashGlobalNameAndSSA(UseOp, UseIter->GetSSANum());
					if (this->BasicBlock->IsLocalName(UseOp)) {
						this->BasicBlock->UpdateUseSignMiscInfo(UseHashValue, SignMask);
					}
					else {
						this->BasicBlock->GetFunc()->UpdateUseSignMiscInfo(UseHashValue, SignMask);
					}
		} // end if (0 != SignMask)
	} // end of case 3 (multiplies and divides)

	// Case 4: Calls to library functions can reveal the type of the return register.
	else if (case4) {
		// Get name of function called.
		string FuncName = this->GetTrimmedCalledFunctionName();

		// Get FG info, if any, for called function.
		GetLibFuncFGInfo(FuncName, FGEntry);

		// See if anything was returned in FGEntry.
		if ((FGEntry.SignMiscInfo != 0) || (FGEntry.SizeInfo != 0)) {
			// Need to update the FG info for the DEF of the return register.
			DefOp = InitOp;
			DefOp.type = o_reg;
			DefOp.reg = MD_RETURN_VALUE_REG;
			DefIter = this->FindDef(DefOp);
			assert(DefIter != this->GetLastDef());
			DefHashValue = HashGlobalNameAndSSA(DefOp, DefIter->GetSSANum());
			if (this->BasicBlock->IsLocalName(DefOp)) {
				this->BasicBlock->UpdateDefFGInfo(DefHashValue, FGEntry);
			}
			else {
				this->BasicBlock->GetFunc()->UpdateDefFGInfo(DefHashValue, FGEntry);
			}
		}
		// See if we make a call to a library function that needs signedness checks on
		//  unsigned incoming args.
		unsigned int ArgPosBits = 0;
		GetUnsignedArgPositionsForCallName(FuncName, ArgPosBits);
		if (0 < ArgPosBits) {
			// Mark our basic block as containing this type of call, so signedness checks
			//  can be done later.
			this->GetBlock()->SetCallsUnsignedArgFunc();
			// Find the argument assignments and mark them, to trigger later signedness checks.
			this->GetBlock()->MarkUnsignedArgs(this->GetAddr(), ArgPosBits);
		}
	else if (case5) { // signed or unsigned conditional set opcode
		if (UnsignedSetOpcode) {
			SignMask = FG_MASK_UNSIGNED;
		}
		else {
			assert(SignedSetOpcode);
			SignMask = FG_MASK_SIGNED;
		}
		// Find the flags USE.
		UseOp.type = o_reg; // set up a dummy op for searching
		UseOp.reg = X86_FLAGS_REG;
		UseIter = this->FindUse(UseOp);
		assert(UseIter != this->GetLastUse());
		UseOp = UseIter->GetOp(); // get full info in all fields of UseOp
		SSANum = UseIter->GetSSANum();
		LocalFlags = this->GetBlock()->IsLocalName(UseOp);

		DefAddr = this->GetBlock()->GetDefAddrFromUseAddr(UseOp, this->GetAddr(), SSANum, LocalFlags);
		// Pass DefAddr to recursive helper function to propagate signedness of the set opcode.
		this->GetBlock()->PropagateBranchSignedness(DefAddr, UseOp, SignMask);
	}
	else if (case6) { // sign extend to double the width of USE operand into DEF operand
		DefIter = this->GetFirstNonFlagsDef();
		assert(DefIter != this->GetLastDef());
		DefOp = DefIter->GetOp();
		assert(o_reg == DefOp.type);
		DefHashValue = HashGlobalNameAndSSA(DefOp, SSANum);
		UseIter = this->GetFirstUse();
		assert(UseIter != this->GetLastUse());
		UseOp = UseIter->GetOp();
		assert(o_reg == UseOp.type);
		assert(UseOp.reg == DefOp.reg);
		UseHashValue = HashGlobalNameAndSSA(UseOp, UseIter->GetSSANum()); 
		SignMask = FG_MASK_SIGNED;  // opcodes do sign extension => signed
		// Mark DEF and USE as signed.
		if (this->GetBlock()->IsLocalName(DefOp)) {
			this->GetBlock()->UpdateDefSignMiscInfo(DefHashValue, SignMask);
			this->GetBlock()->UpdateUseSignMiscInfo(UseHashValue, SignMask);
		}
		else {
			this->GetBlock()->GetFunc()->UpdateDefSignMiscInfo(DefHashValue, SignMask);
			this->GetBlock()->GetFunc()->UpdateUseSignMiscInfo(UseHashValue, SignMask);
		}
	}
	else if (case7 || case8) { // always unsigned DEF or always signed DEF.
		DefIter = this->GetFirstNonFlagsDef();
		if (DefIter != this->GetLastDef()) {
			DefOp = DefIter->GetOp();
			if (o_reg == DefOp.type) {
				SSANum = DefIter->GetSSANum();
				DefHashValue = HashGlobalNameAndSSA(DefOp, SSANum);
				if (case7)
					SignMask = FG_MASK_UNSIGNED;
				else
					SignMask = FG_MASK_SIGNED;
				// Mark DEF as signed or unsigned.
				if (this->GetBlock()->IsLocalName(DefOp)) {
					this->GetBlock()->UpdateDefSignMiscInfo(DefHashValue, SignMask);
				}
				else {
					this->GetBlock()->GetFunc()->UpdateDefSignMiscInfo(DefHashValue, SignMask);
				}
			}
		}
	}
	// For all register DEFs and USEs, we should get the obvious register width info
	//  updated. Need to use the RTL operands to get accurate widths.
	SMPRegTransfer *CurrRT;
	for (size_t index = 0; index < this->RTL.GetCount(); ++index) {
		CurrRT = this->RTL.GetRT(index);
		DefOp = CurrRT->GetLeftOperand();
		// Avoid setting def width for case 2; we leave it as zero so that
		//  later uses can determine whether the zero-extension or sign-extension
		//  bits ever got used. See more discussion in EmitIntegerErrorAnnotations()
		//  for the CHECK TRUNCATION case.
		// NOTE: case2 can be set to true even in the case1/case2 overlap case that
		//  only passes through the case1 code above. This is intentional. We want
		//  to leave the DEF width set to 0 for all of case2 including the case1 overlap.
		if (!case2) {
			if (MDIsGeneralPurposeReg(DefOp)) {
				WidthMask = ComputeOperandBitWidthMask(DefOp, 0);
				CanonicalizeOpnd(DefOp);
				DefIter = this->FindDef(DefOp);
				assert(DefIter != this->GetLastDef());
				DefHashValue = HashGlobalNameAndSSA(DefOp, DefIter->GetSSANum());
				if (this->BasicBlock->IsLocalName(DefOp)) {
					this->BasicBlock->UpdateDefWidthTypeInfo(DefHashValue, WidthMask);
				}
				else {
					this->BasicBlock->GetFunc()->UpdateDefWidthTypeInfo(DefHashValue, WidthMask);
				}
			}
		}
		if (CurrRT->HasRightSubTree()) {
			this->MDSetRTLRegWidthInfo(CurrRT->GetRightTree());
		}
		else {
			UseOp = CurrRT->GetRightOperand();
			this->SetRTLUseOpRegWidthInfo(UseOp);
		}
	}  // end for all RTLs 

	return;
} // end of SMPInstr::MDSetWidthSignInfo()

// Infer sign from the SMP types for USEs and DEFs.
void SMPInstr::InferSignednessFromSMPTypes(bool UseFP) {
	// Start with registers only, infer that all kids of pointers are UNSIGNED.
	set<DefOrUse, LessDefUse>::iterator DefIter, UseIter;
	op_t DefOp, UseOp;
	int SSANum;
	int DefHashValue, UseHashValue;
	SMPOperandType DefType, UseType;
	unsigned short DefSignMiscInfo = FG_MASK_UNSIGNED, UseSignMiscInfo = FG_MASK_UNSIGNED;
	bool GlobalName;

	for (DefIter = this->GetFirstDef(); DefIter != this->GetLastDef(); ++DefIter) {
		DefOp = DefIter->GetOp();
		if (MDIsGeneralPurposeReg(DefOp)) {
			DefType = DefIter->GetType();
			if (IsDataPtr(DefType) || (CODEPTR == DefType)) {
				GlobalName = this->BasicBlock->GetFunc()->IsGlobalName(DefOp);
				SSANum = DefIter->GetSSANum();
				DefHashValue = HashGlobalNameAndSSA(DefOp, SSANum);
				if (GlobalName) {
					this->BasicBlock->GetFunc()->UpdateDefSignMiscInfo(DefHashValue, DefSignMiscInfo);
				}
				else {
					this->BasicBlock->UpdateDefSignMiscInfo(DefHashValue, DefSignMiscInfo);
				}
			}
		}
	}

	for (UseIter = this->GetFirstUse(); UseIter != this->GetLastUse(); ++UseIter) {
		UseOp = UseIter->GetOp();
		if (MDIsGeneralPurposeReg(UseOp)) {
			UseType = UseIter->GetType();
			if (IsDataPtr(UseType) || (CODEPTR == UseType)) {
				GlobalName = this->BasicBlock->GetFunc()->IsGlobalName(UseOp);
				SSANum = UseIter->GetSSANum();
				UseHashValue = HashGlobalNameAndSSA(UseOp, SSANum);
				if (GlobalName) {
					this->BasicBlock->GetFunc()->UpdateUseSignMiscInfo(UseHashValue, UseSignMiscInfo);
				}
				else {
					this->BasicBlock->UpdateUseSignMiscInfo(UseHashValue, UseSignMiscInfo);
				}
			}
		}
	}

	return;
} // end of SMPInstr::InferSignednessFromSMPTypes()


// Helper to set width info for a UseOp from an RTL
void SMPInstr::SetRTLUseOpRegWidthInfo(op_t UseOp) {
	unsigned short WidthMask;
	set<DefOrUse, LessDefUse>::iterator UseIter;
	unsigned int UseHashValue;

	if (MDIsGeneralPurposeReg(UseOp)) {
		WidthMask = ComputeOperandBitWidthMask(UseOp, 0);
		CanonicalizeOpnd(UseOp);
		UseIter = this->FindUse(UseOp);
		assert(UseIter != this->GetLastUse());
		UseHashValue = HashGlobalNameAndSSA(UseOp, UseIter->GetSSANum());
		if (this->BasicBlock->IsLocalName(UseOp)) {
			this->BasicBlock->UpdateUseWidthTypeInfo(UseHashValue, WidthMask);
		}
		else {
			this->BasicBlock->GetFunc()->UpdateUseWidthTypeInfo(UseHashValue, WidthMask);
		}
	}

	return;
} // end of SMPInstr::SetRTLUseOpRegWidthInfo()

// Walk the RTL and update the register USE operands' width info.
void SMPInstr::MDSetRTLRegWidthInfo(SMPRegTransfer *CurrRT) {
	op_t UseOp;