From e9b30de83bc6a1e0eabd1cbbc392f435516bad1d Mon Sep 17 00:00:00 2001
From: clc5q <clc5q@git.zephyr-software.com>
Date: Fri, 21 Mar 2014 00:49:07 +0000
Subject: [PATCH] Improve stack delta analysis when tail calls are encountered.

---
 SMPDataFlowAnalysis.cpp | 12 +++++++++---
 SMPFunction.cpp         |  4 +++-
 SMPInstr.cpp            |  9 +++++++--
 3 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/SMPDataFlowAnalysis.cpp b/SMPDataFlowAnalysis.cpp
index 9f341708..971b790c 100644
--- a/SMPDataFlowAnalysis.cpp
+++ b/SMPDataFlowAnalysis.cpp
@@ -66,7 +66,7 @@
 #define STARS_DEBUG_DUMP_IDENTIFY_HIDDEN_OPERANDS 0 // print HIDDEN if operand.showed() is false
 
 #if IDA_SDK_VERSION > 560
-#define MAX_IDA_REG R_mxcsr
+#define MAX_IDA_REG R_last
 #else
 #define MAX_IDA_REG 80
 #endif
@@ -82,7 +82,10 @@ const char *RegNames[MAX_IDA_REG + 1] =
       "MMX0", "MMX1", "MMX2", "MMX3", "MMX4", "MMX5", "MMX6", "MMX7",
       "XMM0", "XMM1", "XMM2", "XMM3", "XMM4", "XMM5", "XMM6", "XMM7",
       "XMM8", "XMM9", "XMM10", "XMM11", "XMM12", "XMM13", "XMM14", "XMM15",
-      "MXCSR"
+      "MXCSR",
+      "YMM0", "YMM1", "YMM2", "YMM3", "YMM4", "YMM5", "YMM6", "YMM7",
+      "YMM8", "YMM9", "YMM10", "YMM11", "YMM12", "YMM13", "YMM14", "YMM15",
+	  "REG_ERROR"
 	};
 
 const unsigned char RegSizes[MAX_IDA_REG + 1] =
@@ -96,7 +99,10 @@ const unsigned char RegSizes[MAX_IDA_REG + 1] =
       16, 16, 16, 16, 16, 16, 16, 16,
       16, 16, 16, 16, 16, 16, 16, 16,
       16, 16, 16, 16, 16, 16, 16, 16,
-      4
+      4,
+      32, 32, 32, 32, 32, 32, 32, 32,
+      32, 32, 32, 32, 32, 32, 32, 32,
+	  4
 	};
 
 const char *ErrorStrings[1] = { "ERROR_REG" };
diff --git a/SMPFunction.cpp b/SMPFunction.cpp
index 164d4e0c..d6f3dd90 100644
--- a/SMPFunction.cpp
+++ b/SMPFunction.cpp
@@ -1350,11 +1350,13 @@ bool SMPFunction::AnalyzeStackPointerDeltas(void) {
 					}
 					SMPitype FlowType = CurrInst->GetDataFlowType();
 					IncomingDelta += CurrentDelta;
-					if ((RETURN == FlowType) && (!CurrInst->IsCondTailCall())) {
+					if ((RETURN == FlowType) && (!CurrInst->IsCondTailCall()) && (!CurrInst->IsTailCall())) {
 						// We hope to see a consistent outgoing delta from all RETURN points.
 						//  We special-case the conditional jump used as tail call, because it must be followed
 						//  by a real return instruction later. If the jump is taken, it acts as a return, but
 						//  it has not yet popped the stack.
+						// Also, a regular tail call always has the stack delta at zero and does not match
+						//  the stack delta of actual return instructions elsewhere in the function.
 						if (ReturnSeen) { // This is not the first RETURN seen.
 							if (IncomingDelta != this->NetStackDelta) { // Inconsistent
 								SMP_msg("ERROR: Inconsistent stack deltas at return instruction at %lx\n",
diff --git a/SMPInstr.cpp b/SMPInstr.cpp
index 7738f696..65099d43 100644
--- a/SMPInstr.cpp
+++ b/SMPInstr.cpp
@@ -2588,16 +2588,19 @@ sval_t SMPInstr::AnalyzeStackPointerDelta(sval_t IncomingDelta, sval_t PreAllocD
 		//  has no effect on the stack pointer.
 		; // leave InstDelta equal to negative or zero value from StackAlterationTable[]
 	}
-	else if (this->IsRecursiveCall()) {
+	else if (this->IsRecursiveCall() || TailCall) {
 		// We don't have the net stack delta for our own function yet, so we cannot
 		//  look it up. We must assume that each call has no net effect on the stack delta.
 		// Alternatively, we could call this->GetBlock()->GetFunc()->GetStackDeltaForCallee() as below.
+		// Also, a tail call happens when the stack delta is down to zero, and the callee does not
+		//  return to the caller, unlike the call cases below, so the callee's net stack delta is
+		//  irrelevant to the caller.
 		InstDelta = 0;
 	}
 	else if (this->IsAllocaCall()) {
 		InstDelta = STARS_DEFAULT_ALLOCA_SIZE;
 	}
-	else if ((CALL == FlowType) || (INDIR_CALL == FlowType) || TailCall) {
+	else if ((CALL == FlowType) || (INDIR_CALL == FlowType)) {
 		// A real call instruction, which pushes a return address on the stack,
 		//  not a call used as a branch within the function. A return instruction
 		//  will usually cancel out the stack push that is implicit in the call, which 
@@ -2608,9 +2611,11 @@ sval_t SMPInstr::AnalyzeStackPointerDelta(sval_t IncomingDelta, sval_t PreAllocD
 		//  in which case we assume +4. !!!!****!!!! In the future, we could analyze
 		//  the code around an unresolved indirect call to see if it seems to be
 		//  removing items left on the stack by the callee.
+#if 0
 		// SPECIAL CASE: A jump used as a tail call will have a stack ptr effect that is equal
 		//  to the net stack ptr effect of its target function, usually +4, whereas a jump
 		//  would otherwise have a net stack ptr effect of 0.
+#endif
 		ea_t CalledFuncAddr = this->GetCallTarget();
 		if ((BADADDR == CalledFuncAddr) || (0 == CalledFuncAddr)) {
 			InstDelta = 0;
-- 
GitLab