From c06c5317e606b6f57446e9bf58a7b1604b50a6da Mon Sep 17 00:00:00 2001
From: clc5q <clc5q@git.zephyr-software.com>
Date: Sat, 17 May 2008 01:05:36 +0000
Subject: [PATCH] Clean up and complete MDFindPointerType().

---
 SMPInstr.cpp | 161 ++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 113 insertions(+), 48 deletions(-)

diff --git a/SMPInstr.cpp b/SMPInstr.cpp
index 7b67204d..6085406d 100644
--- a/SMPInstr.cpp
+++ b/SMPInstr.cpp
@@ -1114,13 +1114,20 @@ void SMPInstr::MDFixupDefUseLists(void) {
 // If we can definitely identify which part of the addressing expression
 //  used in MemOp is the POINTER type, and it is not a STACKPTR or GLOBALPTR
 //  immediate, set the USE type for that register to POINTER and return true.
+//  If we can find definite NUMERIC addressing registers that are not already
+//  typed as NUMERIC, set their USE types to NUMERIC and return true.
 bool SMPInstr::MDFindPointerUse(op_t MemOp, bool UseFP) {
 	bool changed = false;
 	int BaseReg;
 	int IndexReg;
+	op_t BaseOp;
+	op_t IndexOp;
+	SMPOperandType BaseType = UNKNOWN;
+	SMPOperandType IndexType = UNKNOWN;
 	ushort ScaleFactor;
 	ea_t offset;
-	set<DefOrUse, LessDefUse>::iterator UseIter;
+	set<DefOrUse, LessDefUse>::iterator BaseIter;
+	set<DefOrUse, LessDefUse>::iterator IndexIter;
 
 	if (NN_lea == this->SMPcmd.itype)
 		return false;  // lea instruction really has no memory operands
@@ -1128,28 +1135,74 @@ bool SMPInstr::MDFindPointerUse(op_t MemOp, bool UseFP) {
 		return false;  // SSA marker instruction
 
 	MDExtractAddressFields(MemOp, BaseReg, IndexReg, ScaleFactor, offset);
-	if ((R_sp == BaseReg) || (R_sp == IndexReg))
-		return false; // stack accesses will get STACKPTR type in SetImmedTypes()
-	if (UseFP && ((R_bp == BaseReg) || (R_bp == IndexReg)))
-		return false;
-	if (IsImmedGlobalAddress(offset))
-		return false;  // handled in SetImmedTypes()
+	if (R_none != IndexReg) {
+		IndexOp.type = o_reg;
+		IndexOp.reg = MDCanonicalizeSubReg(IndexReg);
+		IndexIter = this->FindUse(IndexOp);
+		assert(IndexIter != this->GetLastUse());
+		IndexType = IndexIter->GetType();
+	}
+	if (R_none != BaseReg) {
+		BaseOp.type = o_reg;
+		BaseOp.reg = MDCanonicalizeSubReg(BaseReg);
+		BaseIter = this->FindUse(BaseOp);
+		assert(BaseIter != this->GetLastUse());
+		BaseType = BaseIter->GetType();
+	}
+	if ((R_sp == BaseReg) || (UseFP && (R_bp == BaseReg))) {
+		if ((R_none != IndexReg) && (!IsNumeric(IndexType))) {
+			// We have an indexed access into the stack frame.
+			//  Set IndexReg USE type to NUMERIC.
+			changed = true;
+			IndexIter = this->SetUseType(IndexOp, NUMERIC);
+			assert(IndexIter != this->GetLastUse());
+		}
+		return changed; // stack accesses will get STACKPTR type in SetImmedTypes()
+	}
+	if ((R_sp == IndexReg) || (UseFP && (R_bp == IndexReg))) {
+		if ((R_none != BaseReg) && (!IsNumeric(BaseType))) {
+			// We have an indexed access into the stack frame.
+			//  Set BaseReg USE type to NUMERIC.
+			// Note that BaseReg is really an IndexReg and vice versa.
+			changed = true;
+			BaseIter = this->SetUseType(BaseOp, NUMERIC);
+			assert(BaseIter != this->GetLastUse());
+			msg("WARNING: BaseReg is index, IndexReg is base: %s\n",
+				this->GetDisasm());
+		}
+		return changed; // stack accesses will get STACKPTR type in SetImmedTypes()
+	}
+	if (IsImmedGlobalAddress(offset)) {
+		if ((R_none != IndexReg) && (!IsNumeric(IndexType))) {
+			// We have an indexed access into a global.
+			//  Set IndexReg USE type to NUMERIC.
+			changed = true;
+			IndexIter = this->SetUseType(IndexOp, NUMERIC);
+			assert(IndexIter != this->GetLastUse());
+		}
+		if ((R_none != BaseReg) && (!IsNumeric(BaseType))) {
+			// We have an indexed access into a global.
+			//  Set BaseReg USE type to NUMERIC.
+			// Note that BaseReg is really an index register.
+			changed = true;
+			BaseIter = this->SetUseType(BaseOp, NUMERIC);
+			assert(BaseIter != this->GetLastUse());
+			msg("WARNING: BaseReg used as index: %s\n", this->GetDisasm());
+		}
+		return changed;  // handled in SetImmedTypes()
+	}
 
-	// At this point, we must have a base address in a register.
+	// At this point, we must have a base address in a register, not used
+	//  to directly address the stack or a global.
 	if ((0 < ScaleFactor) || (R_none == IndexReg)) {
 		// IndexReg is scaled, meaning it is NUMERIC, so BaseReg must
 		//  be a POINTER; or IndexReg is not present, so BaseReg is the
 		//  only possible holder of an address.
 		if (R_none != BaseReg) {
-			op_t BaseOp;
-			BaseOp.type = o_reg;
-			BaseOp.reg = MDCanonicalizeSubReg(BaseReg);
-			UseIter = this->FindUse(BaseOp);
-			assert(UseIter != this->GetLastUse());
-			if (UNINIT == UseIter->GetType()) {
+			if (UNINIT == BaseIter->GetType()) {
 				changed = true;
-				UseIter = this->SetUseType(BaseOp, POINTER);
-				assert(UseIter != this->GetLastUse());
+				BaseIter = this->SetUseType(BaseOp, POINTER);
+				assert(BaseIter != this->GetLastUse());
 			}
 		}
 	}
@@ -1157,48 +1210,54 @@ bool SMPInstr::MDFindPointerUse(op_t MemOp, bool UseFP) {
 		// We have an unscaled IndexReg and no BaseReg and offset was
 		//  not a global offset, so IndexReg must be a POINTER.
 		if (R_none != IndexReg) {
-			op_t IndexOp;
-			IndexOp.type = o_reg;
-			IndexOp.reg = MDCanonicalizeSubReg(IndexReg);
-			UseIter = this->FindUse(IndexOp);
-			assert(UseIter != this->GetLastUse());
-			if (UNINIT == UseIter->GetType()) {
+			if (UNINIT == IndexType) {
 				changed = true;
-				UseIter = this->SetUseType(IndexOp, POINTER);
-				assert(UseIter != this->GetLastUse());
+				IndexIter = this->SetUseType(IndexOp, POINTER);
+				assert(IndexIter != this->GetLastUse());
 			}
 		}
 	}
 	else { // We have BaseReg and an unscaled IndexReg.
 		// The only hope for typing something like [ebx+edx] is for
 		//  one register to already be typed NUMERIC, in which case
-		//  the other one must be a POINTER.
-		op_t IndexOp;
-		IndexOp.type = o_reg;
-		IndexOp.reg = MDCanonicalizeSubReg(IndexReg);
-		op_t BaseOp;
-		BaseOp.type = o_reg;
-		BaseOp.reg = MDCanonicalizeSubReg(BaseReg);
-		UseIter = this->FindUse(BaseOp);
-		assert(UseIter != this->GetLastUse());
-		if (IsNumeric(UseIter->GetType())) {
-			UseIter = this->FindUse(IndexOp);
-			assert(UseIter != this->GetLastUse());
-			if (UNINIT == UseIter->GetType()) {
+		//  the other one must be a POINTER, or if one register is
+		//  already POINTER, then the other one must be NUMERIC.
+		if (IsNumeric(BaseType)) {
+			if (UNINIT == IndexType) {
 				// Set to POINTER or PROF_POINTER
 				changed = true;
-				UseIter = this->SetUseType(IndexOp, POINTER);
-				assert(UseIter != this->GetLastUse());
+				IndexIter = this->SetUseType(IndexOp, POINTER);
+				assert(IndexIter != this->GetLastUse());
+			}
+			else if (IsNumeric(IndexType)) {
+				msg("ERROR: BaseReg and IndexReg both NUMERIC at %x: %s\n",
+					this->address, this->GetDisasm());
 			}
 		}
 		else { // BaseReg was not NUMERIC
-			if (UNINIT == UseIter->GetType()) { // BaseReg is UNINIT
-				UseIter = this->FindUse(IndexOp);
-				assert(UseIter != this->GetLastUse());
-				if (IsNumeric(UseIter->GetType())) {
+			if (UNINIT == BaseType) { // BaseReg is UNINIT
+				if (IsNumeric(IndexType)) {
+					changed = true;
+					BaseIter = this->SetUseType(BaseOp, POINTER);
+					assert(BaseIter != this->GetLastUse());
+				}
+				else if (IsDataPtr(IndexType)) {
+					// IndexReg is POINTER, so make BaseReg NUMERIC.
 					changed = true;
-					UseIter = this->SetUseType(BaseOp, POINTER);
-					assert(UseIter != this->GetLastUse());
+					BaseIter = this->SetUseType(BaseOp, NUMERIC);
+					assert(BaseIter != this->GetLastUse());
+				}
+			}
+			else if (IsDataPtr(BaseType)) {
+				// BaseReg was a pointer type. IndexReg must be NUMERIC.
+				if (UNINIT == IndexType) {
+					changed = true;
+					IndexIter = this->SetUseType(IndexOp, NUMERIC);
+					assert(IndexIter != this->GetLastUse());
+				}
+				else if (IsDataPtr(IndexType)) {
+					msg("ERROR: BaseReg and IndexReg both POINTER at %x: %s\n",
+						this->address, this->GetDisasm());
 				}
 			}
 		}
@@ -1390,15 +1449,21 @@ bool SMPInstr::InferTypes(void) {
 	}
 	if ((DFAType >= JUMP) && (DFAType <= INDIR_CALL)) {
 		// All USEs are either the flags (NUMERIC) or the target address (CODEPTR).
-		//  The exception is the USE list for interrupt calls, which includes
-		//  the caller-saved regs.
+		//  The exceptions are the USE list for interrupt calls, which includes
+		//  the caller-saved regs, and indirect calls through a memory
+		//  operand, such as call [ebx+esi+20h], where the memory operand
+		//  is a CODEPTR but the addressing registers are a BaseReg and
+		//  IndexReg as in any other memory addressing.
 		CurrUse = this->GetFirstUse();
 		while (CurrUse != this->GetLastUse()) {
 			UseOp = CurrUse->GetOp();
 			if (UseOp.is_reg(X86_FLAGS_REG))
 				CurrUse = this->SetUseType(UseOp, NUMERIC);
 			else if ((CurrUse->GetType() != CODEPTR)
-				&& (!(this->MDIsInterruptCall() && (o_reg == UseOp.type)))) {
+				&& (!(this->MDIsInterruptCall() && (o_reg == UseOp.type)))
+				&& (!(this->HasSourceMemoryOperand() 
+					&& (INDIR_CALL == this->GetDataFlowType())
+					&& (o_reg == UseOp.type)))) {
 				CurrUse = this->SetUseType(UseOp, CODEPTR);
 			}
 			++CurrUse;
-- 
GitLab