/*
 * SMPFunction.cpp - <see below>.
 *
 * Copyright (c) 2000, 2001, 2010 - University of Virginia 
 *
 * This file is part of the Memory Error Detection System (MEDS) infrastructure.
 * This file may be used and modified for non-commercial purposes as long as 
 * all copyright, permission, and nonwarranty notices are preserved.  
 * Redistribution is prohibited without prior written consent from the University 
 * of Virginia.
 *
 * Please contact the authors for restrictions applying to commercial use.
 *
 * THIS SOURCE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 *
 * Author: University of Virginia
 * e-mail: jwd@virginia.com
 * URL   : http://www.cs.virginia.edu/
 *
 * Additional copyrights 2010, 2011, 2012, 2013 by Zephyr Software LLC
 * e-mail: {clc,jwd}@zephyr-software.com
 * URL   : http://www.zephyr-software.com/
 *
 */

//
// SMPFunction.cpp
//
// This module performs the fundamental data flow analyses needed for the
//   SMP project (Software Memory Protection) at the function level.
//

using namespace std;

#include <utility>
#include <list>
#include <set>
#include <vector>
#include <algorithm>

#include <cstring>
#include <cstdlib>

#include <pro.h>
#include <assert.h>
#include <ida.hpp>
#include <ua.hpp>
#include <idp.hpp>
#include <auto.hpp>
#include <bytes.hpp>
#include <funcs.hpp>
#include <intel.hpp>
#include <name.hpp>
#include <struct.hpp>

#include "SMPDBInterface.h"
#include "SMPDataFlowAnalysis.h"
#include "SMPStaticAnalyzer.h"
#include "SMPFunction.h"
#include "SMPBasicBlock.h"
#include "SMPInstr.h"
#include "SMPProgram.h"

// Set to 1 for debugging output
#define SMP_DEBUG 1
#define SMP_DEBUG2 0   // verbose
#define SMP_DEBUG3 0   // verbose
#define SMP_DEBUG_CONTROLFLOW 0  // tells what processing stage is entered
#define SMP_DEBUG_XOR 0
#define SMP_DEBUG_CHUNKS 1  // tracking down tail chunks for functions
#define SMP_DEBUG_FRAMEFIXUP 1
#define SMP_DEBUG_FRAMEFIXUP_VERBOSE 0
#define SMP_DEBUG_DATAFLOW 0
#define SMP_DEBUG_DATAFLOW_VERBOSE 0
#define SMP_DEBUG_TYPE_INFERENCE 0
#define SMP_DEBUG_PROFILED_TYPE_INFERENCE 0
#define SMP_DEBUG_STACK_GRANULARITY 0
#define SMP_DEBUG_FUNC 0
#define SMP_DEBUG_FUNC_SAFETY 1
#define SMP_VERBOSE_DEBUG_FUNC 0
#define SMP_DEBUG_BUILD_RTL 1   // leave this on; serious errors reported
#define SMP_DEBUG_UNINITIALIZED_SSA_NAMES 1
#define SMP_WARN_UNUSED_DEFS 0
#define SMP_DEBUG_SWITCH_TABLE_INFO 0
#define SMP_OPTIMIZE_BLOCK_PROFILING 0
#define SMP_DECLARE_INDIRECT_TARGETS_UNSAFE 1
#define SMP_AUDIT_STACK_POINTER_DELTAS 0
#define SMP_COMPARE_IDA_STARS_STACK_POINTER_DELTAS 1
#define STARS_AGGRESSIVE_SIGNEDNESS_PROPAGATION 1
#define STARS_BUILD_LOOP_BITSET 1  // Build bitset in this->FuncLoopsByBlock
#define STARS_DEBUG_MEMORY_CORRUPTION 0

// Compute LVA/SSA or not? Turn it off for NICECAP demo on 31-JAN-2008
#define SMP_COMPUTE_LVA_SSA 1

// Compute fine-grained stack boundaries?
#define SMP_COMPUTE_STACK_GRANULARITY 1

// Use conditional type propagation on phi functions
#define SMP_CONDITIONAL_TYPE_PROPAGATION 1

// Kludges to fix IDA Pro 5.2 errors in cc1.ncexe
#define SMP_IDAPRO52_WORKAROUND 0

// Basic block number 0 is the top of the CFG lattice.
#define SMP_TOP_BLOCK 0 

// Set SharedTailChunks to TRUE for entire printf family
//  After we restructure the parent/tail structure of the database, this
//  will go away.
#define KLUDGE_VFPRINTF_FAMILY 1

// Used for binary search by function number in SMPStaticAnalyzer.cpp
//  to trigger debugging output and find which instruction in which
//  function is causing a crash.
bool SMPBinaryDebug = false;

using namespace std;


// helper function to determine if an object is in a vector
template <class T>	
bool vector_exists(const T &item, const vector<T> &vec) {
	for (size_t i = 0; i < vec.size(); ++i) {
		if (vec[i] == item)
			return true;
	}
	return false;
}

// Comparison function for sorting.
bool LocalVarCompare(const LocalVar &LV1, const LocalVar &LV2) {
	return (LV1.offset < LV2.offset);
}

// *****************************************************************
// Class SMPFunction
// *****************************************************************

// Constructor
SMPFunction::SMPFunction(func_t *Info, SMPProgram* pgm) {
	this->Program = pgm;
	this->FuncInfo = *Info;
	this->FirstEA = this->FuncInfo.startEA;
#if 0
	this->FuncName[0] = '\0';
#endif
	this->BlockCount = 0;
	this->LoopCount = 0;
	this->FuncProcessed = false;
	this->UseFP = false;
	this->StaticFunc = false;
	this->LibFunc = false;
	this->HasReturnInst = false;
	this->IndirectCalls = false;
	this->UnresolvedIndirectCalls = false;
	this->IndirectJumps = false;
	this->UnresolvedIndirectJumps = false;
	this->DirectlyRecursive = false;
	this->SharedChunks = false;
	this->UnsharedChunks = false;
	this->CallsAlloca = false;
	this->PushAfterLocalVarAlloc = false;
	this->AnalyzedSP = false;
	this->STARSStackPtrAnalysisPerformed = false;
	this->StackAdjustmentComputed = false;
	this->BuiltRTLs = false;
#if 1  // default to unsafe
	this->SafeFunc = false;
	this->SpecSafeFunc = false;
	this->SafeCallee = false;
	this->SpecSafeCallee = false;
#else // default to safe
	this->SafeFunc = true;
	this->SpecSafeFunc = true;
	this->SafeCallee = true;
	this->SpecSafeCallee = true;
#endif
	this->WritesAboveRA = false;
	this->NeedsStackReferent = true;
	this->SpecNeedsStackReferent = true;
	this->HasIndirectWrites = false;
	this->PossibleIndirectCallTarget = false;
	this->PossibleTailCallTarget = false;
	this->OutgoingArgsComputed = false;
	this->GoodLocalVarTable = false;
	this->OutgoingArgsSize = 0;
	this->TypedDefs = 0;
	this->UntypedDefs = 0;
	this->TypedPhiDefs = 0;
	this->UntypedPhiDefs = 0;
	this->SafeBlocks = 0;
	this->UnsafeBlocks = 0;
	this->Size = 0;
	this->LocalVarsSize = 0;
	this->CalleeSavedRegsSize = 0;
	this->RetAddrSize = 0;
	this->IncomingArgsSize = 0;
	this->OutgoingArgsSize = 0;
	this->LocalVarsAllocInstr = BADADDR;
	this->LocalVarsDeallocInstr = BADADDR;
	this->AllocPointDelta = 0;
	this->MinStackDelta = 0;
	this->MaxStackDelta = 0;
	this->MinStackAccessOffset = 0;
	this->MaxStackAccessLimit = 0;
	this->NetStackDelta = CALLING_CONVENTION_DEFAULT_FUNCTION_STACK_DELTA;
	this->PreAllocStackDelta = CALLING_CONVENTION_DEFAULT_PREFRAMEALLOC_STACK_DELTA;
	this->FramePointerStackDelta = 0;
	this->GlobalStackAdjustment = 0;
	this->LocalVarOffsetLimit = 0;
	this->IDAReturnAddressOffset = 0;

	this->ReturnAddrStatus = FUNC_UNKNOWN;
	this->SetIsSpeculative(false);

	this->Instrs.clear();
	this->Blocks.clear();
	this->DirectCallTargets.clear();
	this->IndirectCallTargets.clear();
	this->AllCallTargets.clear();
	this->AllCallSources.clear();
	this->InstBlockMap.clear();
	this->RPOBlocks.clear();
	this->IDom.clear();
	this->DomTree.clear();
	this->GlobalNames.clear();
	this->BlocksDefinedIn.clear();
	this->SSACounter.clear();
	this->SSAStack.clear();
	this->LocalVarTable.clear();
	this->StackFrameMap.clear();
	this->FineGrainedStackTable.clear();
	this->SavedRegLoc.clear();
	this->ReturnRegTypes.clear();
	this->LiveInSet.clear();
	this->LiveOutSet.clear();
	this->KillSet.clear();
	this->GlobalDefAddrBySSA.clear();

	for (int RegIndex = R_ax; RegIndex <= R_di; ++RegIndex) {
		this->SavedRegLoc.push_back(0); // zero offset means reg not saved
		this->ReturnRegTypes.push_back(UNINIT);
	}

	// The sizes of the three regions of the stack frame other than the
	//  return address are stored in the function structure.
	this->LocalVarsSize = this->FuncInfo.frsize;
	this->CalleeSavedRegsSize = this->FuncInfo.frregs;
	this->IncomingArgsSize = this->FuncInfo.argsize;

	// The return address size can be obtained in a machine independent
	//  way by calling get_frame_retsize(). 
	this->RetAddrSize = get_frame_retsize(this->GetFuncInfo());

	return;
} // end of SMPFunction() constructor

SMPFunction::~SMPFunction() {
	list<SMPInstr *>::iterator InstIter;
	for (InstIter = this->Instrs.begin(); InstIter != this->Instrs.end(); ++InstIter) {
		SMPInstr *CurrInst = (*InstIter);
		if (NULL != CurrInst) delete CurrInst;
	}

	list<SMPBasicBlock *>::iterator BlockIter;
	for (BlockIter = this->Blocks.begin(); BlockIter != this->Blocks.end(); ++BlockIter) {
		SMPBasicBlock *CurrBlock = (*BlockIter);
		if (NULL != CurrBlock) delete CurrBlock;
	}
}

// Get a non-stale pointer to the func_t info for the current function.
func_t *SMPFunction::GetFuncInfo(void) {
	func_t *myPtr = SMP_get_func(this->FirstEA);
	assert(NULL != myPtr);
	return myPtr;
}

// Reset the Processed flags in all blocks to false.
void SMPFunction::ResetProcessedBlocks(void) {
	list<SMPBasicBlock *>::iterator CurrBlock;
	for (CurrBlock = this->Blocks.begin(); CurrBlock != this->Blocks.end(); ++CurrBlock) {
		(*CurrBlock)->SetProcessed(false);
	}
	return;
} // end of SMPFunction::ResetProcessedBlocks()

// Set SCCPVisited flag to false in all blocks
void SMPFunction::ResetSCCPVisitedBlocks(void) {
	list<SMPBasicBlock *>::iterator CurrBlock;
	for (CurrBlock = this->Blocks.begin(); CurrBlock != this->Blocks.end(); ++CurrBlock) {
		(*CurrBlock)->SetSCCPVisited(false);
	}
	return;
} // end of SMPFunction::ResetSCCPVisitedBlocks()

// Return an iterator for the beginning of the LiveInSet. 
set<op_t, LessOp>::iterator SMPFunction::GetFirstLiveIn(void) {
	return this->LiveInSet.begin();
} // end of SMPBasicBlock::GetFirstLiveIn()

// Get termination iterator marker for the LiveIn set, for use by predecessors.
set<op_t, LessOp>::iterator SMPFunction::GetLastLiveIn(void) {
	return this->LiveInSet.end();
}

// Get iterator for the start of the LiveOut set.
set<op_t, LessOp>::iterator SMPFunction::GetFirstLiveOut(void) {
	return this->LiveOutSet.begin();
}

// Get termination iterator marker for the LiveOut set.
set<op_t, LessOp>::iterator SMPFunction::GetLastLiveOut(void) {
	return this->LiveOutSet.end();
}

// Get iterator for the start of the VarKill set.
set<op_t, LessOp>::iterator SMPFunction::GetFirstVarKill(void) {
	return this->KillSet.begin();
}

// Get termination iterator marker for the VarKill set.
set<op_t, LessOp>::iterator SMPFunction::GetLastVarKill(void) {
	return this->KillSet.end();
}

// Four methods to get values from the maps of global reg/SSA to FG info.
//  For local names, see corresponding methods in SMPBasicBlock.
unsigned short SMPFunction::GetDefSignMiscInfo(int DefHashValue) {
	map<int, struct FineGrainedInfo>::iterator MapIter;
	pair<map<int, struct FineGrainedInfo>::iterator, bool> MapResult;

	MapIter = this->GlobalDefFGInfoBySSA.find(DefHashValue);
	if (MapIter != this->GlobalDefFGInfoBySSA.end())
		return MapIter->second.SignMiscInfo;
	else
		return 0;
} // end of SMPFunction::GetDefSignMiscInfo()

unsigned short SMPFunction::GetStackDefSignMiscInfo(ea_t InstAddr) {
	map<ea_t, struct FineGrainedInfo>::iterator MapIter;

	MapIter = this->StackDefFGInfo.find(InstAddr);
	assert(MapIter != this->StackDefFGInfo.end());

	return MapIter->second.SignMiscInfo;
}

unsigned short SMPFunction::GetUseSignMiscInfo(int UseHashValue) {
	map<int, struct FineGrainedInfo>::iterator MapIter;
	pair<map<int, struct FineGrainedInfo>::iterator, bool> MapResult;

	MapIter = this->GlobalUseFGInfoBySSA.find(UseHashValue);
	if (MapIter != this->GlobalUseFGInfoBySSA.end())
		return MapIter->second.SignMiscInfo;
	else
		return 0;
} // end of SMPFunction::GetUseSignMiscInfo()

unsigned short SMPFunction::GetStackUseSignMiscInfo(ea_t InstAddr) {
	map<ea_t, struct FineGrainedInfo>::iterator MapIter;

	MapIter = this->StackUseFGInfo.find(InstAddr);
	assert(MapIter != this->StackUseFGInfo.end());

	return MapIter->second.SignMiscInfo;
}

unsigned short SMPFunction::GetDefWidthTypeInfo(int DefHashValue) {
	map<int, struct FineGrainedInfo>::iterator MapIter;
	pair<map<int, struct FineGrainedInfo>::iterator, bool> MapResult;

	MapIter = this->GlobalDefFGInfoBySSA.find(DefHashValue);
	if (MapIter != this->GlobalDefFGInfoBySSA.end())
		return MapIter->second.SizeInfo;
	else
		return 0;
} // end of SMPFunction::GetDefWidthTypeInfo()

unsigned short SMPFunction::GetUseWidthTypeInfo(int UseHashValue) {
	map<int, struct FineGrainedInfo>::iterator MapIter;
	pair<map<int, struct FineGrainedInfo>::iterator, bool> MapResult;

	MapIter = this->GlobalUseFGInfoBySSA.find(UseHashValue);
	if (MapIter != this->GlobalUseFGInfoBySSA.end())
		return MapIter->second.SizeInfo;
	else
		return 0;
} // end of SMPFunction::GetUseWidthTypeInfo()

struct FineGrainedInfo SMPFunction::GetDefFGInfo(int DefHashValue) {
	map<int, struct FineGrainedInfo>::iterator MapIter;
	pair<map<int, struct FineGrainedInfo>::iterator, bool> MapResult;

	MapIter = this->GlobalDefFGInfoBySSA.find(DefHashValue);
	if (MapIter != this->GlobalDefFGInfoBySSA.end())
		return MapIter->second;
	else {
		struct FineGrainedInfo EmptyFG;
		EmptyFG.SignMiscInfo = 0;
		EmptyFG.SizeInfo = 0;
		return EmptyFG;
	}
} // end of SMPFunction::GetDefFGInfo()

struct FineGrainedInfo SMPFunction::GetUseFGInfo(int UseHashValue) {
	map<int, struct FineGrainedInfo>::iterator MapIter;
	pair<map<int, struct FineGrainedInfo>::iterator, bool> MapResult;

	MapIter = this->GlobalUseFGInfoBySSA.find(UseHashValue);
	if (MapIter != this->GlobalUseFGInfoBySSA.end())
		return MapIter->second;
	else {
		struct FineGrainedInfo EmptyFG;
		EmptyFG.SignMiscInfo = 0;
		EmptyFG.SizeInfo = 0;
		return EmptyFG;
	}
} // end of SMPFunction::GetUseFGInfo()

// Add a caller to the list of all callers of this function.
void SMPFunction::AddCallSource(ea_t addr) {
	// Convert call instruction address to beginning address of the caller.
	func_t *FuncInfo = SMP_get_func(addr);
	if (NULL == FuncInfo) {
		SMP_msg("SERIOUS WARNING: Call location %lx not in a function.\n", (unsigned long) addr);
		return;
	}
	ea_t FirstAddr = FuncInfo->startEA;
	assert(BADADDR != FirstAddr);
	this->AllCallSources.insert(FirstAddr);
	this->AllCallSites.insert(addr);
	return;
} // end of SMPFunction::AddCallSource()

// add map entry to LeaInstOpMap
void SMPFunction::AddLeaOperand(ea_t addr, op_t LeaOperand) {
	pair<ea_t, op_t> InsertValue(addr, LeaOperand);
	pair<map<ea_t, op_t>::iterator, bool> InsertResult;
	InsertResult = this->LeaInstOpMap.insert(InsertValue);
	if (!(InsertResult.second)) { // already existed; replace
		map<ea_t, op_t>::iterator FindIter = this->LeaInstOpMap.find(addr);
		assert(FindIter != this->LeaInstOpMap.end());
		FindIter->second = LeaOperand;
	}
	return;
}

// Add input arguments to the NormalizedStackOpsMap.
void SMPFunction::AddNormalizedStackOperand(op_t OldOp, ea_t InstAddr, op_t NormalizedOp) {
	bool DuplicateCase = false; // e.g. inc [esp+8] will have [esp+8] as a DEF and a USE and maps will see [esp+8] twice
	bool DebugFlag = (InstAddr == 0xb79b);
	pair<map<pair<op_t, ea_t>, op_t, LessDefinition>::iterator, bool> InsertResult;
	pair<map<pair<op_t, ea_t>, map<pair<op_t, ea_t>, op_t, LessDefinition>::iterator, LessDefinition>::iterator, bool> InverseInsertResult;
	pair<op_t, ea_t> OldValue(OldOp, InstAddr);
	pair<op_t, ea_t> InverseValue(OldOp, InstAddr); // OldOp was NormalizedOp when it was inserted previously
	pair<pair<op_t, ea_t>, op_t> InsertValue(OldValue, NormalizedOp);
	pair<op_t, ea_t> InverseInsertValue(NormalizedOp, InstAddr);
	map<pair<op_t, ea_t>, op_t, LessDefinition>::iterator OldIter = this->NormalizedStackOpsMap.begin();
	pair<pair<op_t, ea_t>, map<pair<op_t, ea_t>, op_t, LessDefinition>::iterator> InverseInsertTriple(InverseInsertValue, OldIter);
	map<pair<op_t, ea_t>, map<pair<op_t, ea_t>, op_t, LessDefinition>::iterator>::iterator InverseIter;

	// If this function calls alloca(), stack operands could be normalized more than once.
	//  Before we proceed, we update an old entry instead of inserting a new entry.
	if (this->CallsAlloca || this->HasPushAfterFrameAlloc()) {
		InverseIter = this->InverseNormalizedStackOpsMap.find(InverseValue);
		if (InverseIter != this->InverseNormalizedStackOpsMap.end()) {
			// We have our alloca() update case. We formerly mapped <A, InstAddr> to B.
			//  Now B is being normalized to C. All we want to do is change the original
			//  map entry so that we map <A, InstAddr> to C. In this manner, A is always the
			//  original un-normalized stack op, available for lookup from an RTL.
			OldIter = InverseIter->second; // OldIter points at map of <A, InstAddr> to B.
			OldIter->second = NormalizedOp; // Change B to C
			// Now we want to erase the Inverse map entry and insert a new one that maps
			//  <C, InstAddr> to OldIter instead of mapping <B, InstAddr> to OldIter.
			(void) this->InverseNormalizedStackOpsMap.erase(InverseIter);
			InverseInsertTriple.second = OldIter;
			InverseInsertResult = this->InverseNormalizedStackOpsMap.insert(InverseInsertTriple);
			assert(InverseInsertResult.second);
			return;
		}
		else {
			// We might have the final difficult case: We have a combination of CallsAlloca and the
			//  DuplicateCase described below (e.g. an increment of a stack location produces a DEF
			//  and a USE of the same location, causing duplicate mappings to be attempted). We need
			//  to detect the duplicate case here. What will happen is that, on the first call to this
			//  method, we will map <A, InstAddr> to B, and reverse-map <B, InstAddr> to A. On the second
			//  call to this method, we will detect the duplicate case and exit. On the third call, caused
			//  by CallsAlloca, we are asked to map <B, InstAddr> to C, and we will correctly hit the code
			//  just above, in the if-clause, to fix the A->B mapping to be an A->C mapping, and we will
			//  erase the reverse mapping of B->A and replace it with the C->A reverse mapping. On the
			//  fourth call to this method, we will not find a reverse mapping B->A any more, so the if-clause
			//  does not execute. We can only detect this case by finding an existing C->A reverse mapping
			//  and an existing A->C mapping to confirm our inference.
			pair<op_t, ea_t> TestInverseValue(NormalizedOp, InstAddr);
			InverseIter = this->InverseNormalizedStackOpsMap.find(TestInverseValue);
			if (InverseIter != this->InverseNormalizedStackOpsMap.end()) {
				// Found existing C->A inverse mapping. Is there an A->C mapping to confirm
				//  our interpretation of the situation?
				pair<op_t, ea_t> TestOldValue(InverseIter->second->first.first, InstAddr);
				map<pair<op_t, ea_t>, op_t, LessDefinition>::iterator TestOldIter;
				TestOldIter = this->NormalizedStackOpsMap.find(TestOldValue);
				if (TestOldIter != this->NormalizedStackOpsMap.end()) {
					// We found a mapping from <A, InstAddr>.
					if (IsEqOp(NormalizedOp, TestOldIter->second)) {
						// The mapping is A->C as suspected.
						return; // duplication; nothing to do in either map.
					}
				}
			}
		}
	}
	// At this point, we have no inverse map entry to worry about, because we are
	//  normalizing this operand for the first time.
	InsertResult = this->NormalizedStackOpsMap.insert(InsertValue);
	OldIter = InsertResult.first;
	if (!(InsertResult.second)) {
		// Already had an entry. That should mean a rare case such as "inc [esp+8]" which
		//  produces a USE and a DEF of the same address. We can confirm that the map has
		//  the same normalized operand we were trying to insert. Otherwise, the collision
		//  is fatal.
		op_t OldOldOp = InsertResult.first->first.first;
		op_t OldNormalizedOp = InsertResult.first->second;
		assert(IsEqOp(OldOldOp, OldOp) && IsEqOp(OldNormalizedOp, NormalizedOp));
		DuplicateCase = true;
	}
	if (this->CallsAlloca || this->HasPushAfterFrameAlloc()) {
		// We need to add an entry to the inverse map.
		InverseInsertTriple.second = OldIter;
		InverseInsertResult = this->InverseNormalizedStackOpsMap.insert(InverseInsertTriple);
		assert(InverseInsertResult.second || DuplicateCase);
	}
	if (DebugFlag) {
		map<pair<op_t, ea_t>, op_t, LessDefinition>::iterator StackMapIter;
		SMP_msg("DEBUG: NormalizedStackOpsMap size: %zd\n", this->NormalizedStackOpsMap.size());
		for (StackMapIter = this->NormalizedStackOpsMap.begin(); StackMapIter != this->NormalizedStackOpsMap.end(); ++ StackMapIter) {
			op_t OldOp = StackMapIter->first.first;
			ea_t InstAddr = StackMapIter->first.second;
			SMP_msg("DEBUG: NormalizedStackOps: ");
			PrintOperand(OldOp);
			SMP_msg(" addr: %lx\n", (unsigned long) InstAddr);
		}
	}
	return;
} // SMPFunction::AddNormalizedStackOperand()

// Insert SCCP value for global name; change old entry if already found.
map<int, struct STARS_SCCP_Const_Struct>::iterator SMPFunction::InsertGlobalConstValue(int DefHashValue, struct STARS_SCCP_Const_Struct NewConstEntry) {
	map<int, struct STARS_SCCP_Const_Struct>::iterator MapIter = this->FindConstValue(DefHashValue);
	if (MapIter == this->GetLastConstValueIter()) { // no old entry; insert
		pair<int, struct STARS_SCCP_Const_Struct> InsertPair(DefHashValue, NewConstEntry);
		pair<map<int, struct STARS_SCCP_Const_Struct>::iterator, bool> InsertResult = this->ConstantDefs.insert(InsertPair);
		assert(InsertResult.second);
		MapIter = InsertResult.first;
	}
	else { // old entry found; update
		MapIter->second = NewConstEntry;
	}
	return MapIter;
} // end of SMPFunction::InsertGlobalConstValue()


// Return RTLop if not stack opnd; return normalized RTLop otherwise.
op_t SMPFunction::GetNormalizedOperand(ea_t InstAddr, op_t RTLop) {
	op_t NormOp;
	bool DebugFlag = (0xb79b == InstAddr);
	if (DebugFlag) {
		map<pair<op_t, ea_t>, op_t, LessDefinition>::iterator StackMapIter;
		SMP_msg("DEBUG: NormalizedStackOpsMap size: %zd\n", this->NormalizedStackOpsMap.size());
		for (StackMapIter = this->NormalizedStackOpsMap.begin(); StackMapIter != this->NormalizedStackOpsMap.end(); ++ StackMapIter) {
			op_t OldOp = StackMapIter->first.first;
			ea_t InstAddr = StackMapIter->first.second;
			SMP_msg("DEBUG: NormalizedStackOps: ");
			PrintOperand(OldOp);
			SMP_msg(" addr: %lx\n", (unsigned long) InstAddr);
		}
	}
	if (MDIsStackAccessOpnd(RTLop, this->UsesFramePointer())) {
		pair<op_t, ea_t> OldDefn(RTLop, InstAddr);
		map<pair<op_t, ea_t>, op_t, LessDefinition>::iterator FindIter = this->NormalizedStackOpsMap.find(OldDefn);
		assert(this->NormalizedStackOpsMap.end() != FindIter);
		NormOp = FindIter->second;
	}
	else {
		NormOp = RTLop;
	}
	return NormOp;
} // end of SMPFunction::GetNormalizedOperand()


// Eight methods to set values into the maps of global reg/stack/SSA to FG info.
//  For local names, see corresponding methods in SMPBasicBlock.
void SMPFunction::UpdateDefSignMiscInfo(int DefHashValue, unsigned short NewInfo) {
	map<int, struct FineGrainedInfo>::iterator MapIter;
	pair<map<int, struct FineGrainedInfo>::iterator, bool> MapResult;

	MapIter = this->GlobalDefFGInfoBySSA.find(DefHashValue);
	if (MapIter == this->GlobalDefFGInfoBySSA.end()) {
		// Not found; insert first.
		struct FineGrainedInfo NewFGInfo;
		NewFGInfo.SignMiscInfo = NewInfo;
		NewFGInfo.SizeInfo = 0;
		pair<int, struct FineGrainedInfo> MapItem(DefHashValue, NewFGInfo);
		MapResult = this->GlobalDefFGInfoBySSA.insert(MapItem);
		assert(MapResult.second); // Was not previously found, insertion must work.
	}
	else { // found; just OR in the new bits.
		MapIter->second.SignMiscInfo |= NewInfo;
	}

	return;
} // end of SMPFunction::UpdateDefSignMiscInfo()

void SMPFunction::UpdateStackDefSignMiscInfo(ea_t InstAddr, unsigned short NewInfo) {
	map<ea_t, struct FineGrainedInfo>::iterator MapIter;

	MapIter = this->StackDefFGInfo.find(InstAddr);
	assert(MapIter != this->StackDefFGInfo.end());
	// found; just OR in the new bits.
	MapIter->second.SignMiscInfo |= NewInfo;

	return;
} // end of SMPFunction::UpdateStackDefSignMiscInfo()

void SMPFunction::UpdateUseSignMiscInfo(int UseHashValue, unsigned short NewInfo) {
	map<int, struct FineGrainedInfo>::iterator MapIter;
	pair<map<int, struct FineGrainedInfo>::iterator, bool> MapResult;

	MapIter = this->GlobalUseFGInfoBySSA.find(UseHashValue);
	if (MapIter == this->GlobalUseFGInfoBySSA.end()) {
		// Not found; insert first.
		struct FineGrainedInfo NewFGInfo;
		NewFGInfo.SignMiscInfo = NewInfo;
		NewFGInfo.SizeInfo = 0;
		pair<int, struct FineGrainedInfo> MapItem(UseHashValue, NewFGInfo);
		MapResult = this->GlobalUseFGInfoBySSA.insert(MapItem);
		assert(MapResult.second); // Was not previously found, insertion must work.
	}
	else { // found; just OR in the new bits.
		MapIter->second.SignMiscInfo |= NewInfo;
	}

	return;
} // end of SMPFunction::UpdateUseSignMiscInfo()

void SMPFunction::UpdateStackUseSignMiscInfo(ea_t InstAddr, unsigned short NewInfo) {
	map<ea_t, struct FineGrainedInfo>::iterator MapIter;

	MapIter = this->StackUseFGInfo.find(InstAddr);
	assert(MapIter != this->StackUseFGInfo.end());
	// found; just OR in the new bits.
	MapIter->second.SignMiscInfo |= NewInfo;

	return;
} // end of SMPFunction::UpdateStackUseSignMiscInfo()

void SMPFunction::UpdateDefWidthTypeInfo(int DefHashValue, unsigned short NewInfo) {
	map<int, struct FineGrainedInfo>::iterator MapIter;
	pair<map<int, struct FineGrainedInfo>::iterator, bool> MapResult;

	MapIter = this->GlobalDefFGInfoBySSA.find(DefHashValue);
	if (MapIter == this->GlobalDefFGInfoBySSA.end()) {
		// Not found; insert first.
		struct FineGrainedInfo NewFGInfo;
		NewFGInfo.SignMiscInfo = 0;
		NewFGInfo.SizeInfo = NewInfo;
		pair<int, struct FineGrainedInfo> MapItem(DefHashValue, NewFGInfo);
		MapResult = this->GlobalDefFGInfoBySSA.insert(MapItem);
		assert(MapResult.second); // Was not previously found, insertion must work.
	}
	else { // found; just OR in the new bits.
		MapIter->second.SizeInfo |= NewInfo;
	}

	return;
} // end of SMPFunction::UpdateDefWidthTypeInfo()

void SMPFunction::UpdateUseWidthTypeInfo(int UseHashValue, unsigned short NewInfo) {
	map<int, struct FineGrainedInfo>::iterator MapIter;
	pair<map<int, struct FineGrainedInfo>::iterator, bool> MapResult;

	MapIter = this->GlobalUseFGInfoBySSA.find(UseHashValue);
	if (MapIter == this->GlobalUseFGInfoBySSA.end()) {
		// Not found; insert first.
		struct FineGrainedInfo NewFGInfo;
		NewFGInfo.SignMiscInfo = 0;
		NewFGInfo.SizeInfo = NewInfo;
		pair<int, struct FineGrainedInfo> MapItem(UseHashValue, NewFGInfo);
		MapResult = this->GlobalUseFGInfoBySSA.insert(MapItem);
		assert(MapResult.second); // Was not previously found, insertion must work.
	}
	else { // found; just OR in the new bits.
		MapIter->second.SizeInfo |= NewInfo;
	}

	return;
} // end of SMPFunction::UpdateUseWidthTypeInfo()

void SMPFunction::UpdateDefFGInfo(int DefHashValue, struct FineGrainedInfo NewFG) {
	map<int, struct FineGrainedInfo>::iterator MapIter;
	pair<map<int, struct FineGrainedInfo>::iterator, bool> MapResult;

	MapIter = this->GlobalDefFGInfoBySSA.find(DefHashValue);
	if (MapIter == this->GlobalDefFGInfoBySSA.end()) {
		// Not found; insert it.
		pair<int, struct FineGrainedInfo> MapItem(DefHashValue, NewFG);
		MapResult = this->GlobalDefFGInfoBySSA.insert(MapItem);
		assert(MapResult.second); // Was not previously found, insertion must work.
	}
	else { // found; just put in the new bits.
		MapIter->second.SignMiscInfo |= NewFG.SignMiscInfo;
		MapIter->second.SizeInfo |= NewFG.SizeInfo;
	}

	return;
} // end of SMPFunction::UpdateDefFGInfo()

void SMPFunction::UpdateUseFGInfo(int UseHashValue, struct FineGrainedInfo NewFG) {
	map<int, struct FineGrainedInfo>::iterator MapIter;
	pair<map<int, struct FineGrainedInfo>::iterator, bool> MapResult;

	MapIter = this->GlobalUseFGInfoBySSA.find(UseHashValue);
	if (MapIter == this->GlobalUseFGInfoBySSA.end()) {
		// Not found; insert it.
		pair<int, struct FineGrainedInfo> MapItem(UseHashValue, NewFG);
		MapResult = this->GlobalUseFGInfoBySSA.insert(MapItem);
		assert(MapResult.second); // Was not previously found, insertion must work.
	}
	else { // found; just put in the new bits.
		MapIter->second.SignMiscInfo |= NewFG.SignMiscInfo;
		MapIter->second.SizeInfo |= NewFG.SizeInfo;
	}

	return;
} // end of SMPFunction::UpdateUseFGInfo()

// Reset the signedness bits to zero for DEF.
void SMPFunction::ClearDefSignedness(int DefHashValue) {
	map<int, struct FineGrainedInfo>::iterator MapIter;

	MapIter = this->GlobalDefFGInfoBySSA.find(DefHashValue);
	if (MapIter != this->GlobalDefFGInfoBySSA.end()) {
		MapIter->second.SignMiscInfo &= (~FG_MASK_SIGNEDNESS_BITS);
	}
	return;
} // end of SMPFunction::ClearDefSignedness()

// Erase a range of instructions from the Instrs list, usually corresponding
//  the the range of a basic block.
void SMPFunction::EraseInstRange(ea_t FirstAddr, ea_t LastAddr) {
	list<SMPInstr *>::iterator InstIter = this->Instrs.begin();
	SMPInstr *CurrInst;
	ea_t InstAddr;

	while (InstIter != this->Instrs.end()) {
		CurrInst = (*InstIter);
		InstAddr = CurrInst->GetAddr();
		if ((InstAddr >= FirstAddr) && (InstAddr <= LastAddr)) {
			InstIter = this->Instrs.erase(InstIter);
		}
		else {
			++InstIter;
		}
	}
} // end of SMPFunction::EraseInstRange()

// For instruction address UseAddr, compute the reaching defs for operand TempOp,
//  placing them into the TempReachingDefs list.
void SMPFunction::ComputeTempReachingDefs(op_t TempOp, ea_t UseAddr) {
	this->TempReachingDefs.clear();
	SMPBasicBlock *CurrBlock = this->GetBlockFromInstAddr(UseAddr);
	assert(NULL != CurrBlock);
	set<pair<op_t, ea_t>, LessDefinition>::iterator ReachesInIter;
	pair<set<ea_t, LessAddr>::iterator, bool> InsertResult;

	// Start with the matching members of the ReachesIn set for the current basic block.
	for (ReachesInIter = CurrBlock->GetFirstReachesIn(); ReachesInIter != CurrBlock->GetLastReachesIn(); ++ReachesInIter) {
		pair<op_t, ea_t> ReachesInDef = *ReachesInIter;
		if (IsEqOp(TempOp, ReachesInDef.first)) {
			InsertResult = this->TempReachingDefs.insert(ReachesInDef.second);
			assert(InsertResult.second);
		}
	}

	// Now, see if any def in the block hides the ReachesIn defs before we get to UseAddr.
	vector<SMPInstr *>::iterator InstIter;
	for (InstIter = CurrBlock->GetFirstInst(); InstIter != CurrBlock->GetLastInst(); ++InstIter) {
		SMPInstr *CurrInst = *InstIter;
		ea_t InstAddr = CurrInst->GetAddr();
		if (InstAddr >= UseAddr)
			break;
		set<DefOrUse, LessDefUse>::iterator DefIter = CurrInst->FindDef(TempOp);
		if (DefIter != CurrInst->GetLastDef()) {
			// Found a def. All previous defs are hidden from UseAddr by this def.
			this->TempReachingDefs.clear();
			InsertResult = this->TempReachingDefs.insert(InstAddr);
			assert(InsertResult.second);
		}
	}
	return;
} // end of SMPFunction::ComputeTempReachingDefs()

// Find all the saved stack deltas (if any) for the def addrs in the TempReachesDefs list for TempOp.
//  Put the entries matching TempOp into TempStackDeltaReachesList.
void SMPFunction::ComputeTempStackDeltaReachesList(op_t TempOp) {
	bool FoundOperand = false;
	set<pair<op_t, pair<ea_t, sval_t> >, LessStackDeltaCopy>::iterator CopyIter;
	this->TempStackDeltaReachesList.clear();
	for (CopyIter = this->StackPtrCopySet.begin(); CopyIter != this->StackPtrCopySet.end(); ++CopyIter) {
		pair<op_t, pair<ea_t, sval_t> > CopyEntry = *CopyIter;
		if (IsEqOp(TempOp, CopyEntry.first)) {
			set<ea_t, LessAddr>::iterator FindReachDefIter;
			FoundOperand = true; // help us save time later by exiting loop
			// Match address at which stack ptr copy was made to a reaching def address for TempOp.
			FindReachDefIter = this->TempReachingDefs.find(CopyEntry.second.first);
			if (FindReachDefIter != this->TempReachingDefs.end()) {
				// Found a StackPtrCopySet entry for TempOp, AND we found the DefAddr
				//  in the TempReachingDefs set. 
				this->TempStackDeltaReachesList.push_back(CopyEntry.second); // push back a pair<ea_t, sval_t>
			}
		}
		else if (FoundOperand) {
			// We have found the operand, but have now moved past it in the iteration of StackPtrCopySet.
			//  Save time by exiting the loop.
			break;
		}
	}
	return;
} // end of SMPFunction::ComputeTempStackDeltaReachesList()

// Find the largest stack delta in the TempStackDeltaReachesList.
// Return true if only one value was found in the list.
bool SMPFunction::FindReachingStackDelta(sval_t &StackDelta) {
	bool UniqueDelta = true;

	if (this->TempStackDeltaReachesList.empty()) {
		StackDelta = 0;
		return false;
	}
	else {
		StackDelta = this->TempStackDeltaReachesList.front().second;
	}

	list<pair<ea_t, sval_t> >::iterator DeltaIter;
	for (DeltaIter = this->TempStackDeltaReachesList.begin(); DeltaIter != this->TempStackDeltaReachesList.end(); ++DeltaIter) {
		sval_t NewDelta = DeltaIter->second;
		if (NewDelta != StackDelta) {
			UniqueDelta = false;
			if (NewDelta > StackDelta) {
				StackDelta = NewDelta;
			}
		}
	}
	return UniqueDelta;
} // end of SMPFunction::FindReachingStackDelta()

// Find any apparent stack adjustment after the call instruction at CallAddr,
//  confining our search to the basic block containing CallAddr.
sval_t SMPFunction::GetStackAdjustmentForCallee(ea_t CallAddr) {
	sval_t CalleeAdjustment = 0;

	SMPBasicBlock *CallBlock = this->GetBlockFromInstAddr(CallAddr);
	assert(NULL != CallBlock);
	sval_t BlockAnalysisDelta = CallBlock->ComputeStackAdjustmentAfterCall(CallAddr);
	if (0 != BlockAnalysisDelta) {
		CalleeAdjustment = BlockAnalysisDelta;
		SMP_msg("INFO: Block analysis produced callee adjustment of %ld bytes after %lx\n", 
			(long) CalleeAdjustment, (unsigned long) CallAddr);
	}

	return CalleeAdjustment;
} // end of SMPFunction::GetStackAdjustmentForCallee()

// Get stack delta from a callee function that is unable to provide the info from
//  its own analyses (e.g. analyses failed or have not been performed yet, due to
//  a mutually recursive clique in the call graph). We have three approaches in
//  this case: Use a default value, consult IDA Pro's analyses, or see if we can
//  detect a stack adjustment after the call instruction, from which we could infer
//  the stack delta of the callee. We choose the latter approach, and find the smallest
//  adjustment among all call sites for the callee.
sval_t SMPFunction::GetStackDeltaForCallee(ea_t CallTargetAddr) {
	sval_t CalleeDelta = CALLING_CONVENTION_DEFAULT_FUNCTION_STACK_DELTA;

	SMPFunction *CalleeFunc = this->GetProg()->FindFunction(CallTargetAddr);
	if (NULL != CalleeFunc) {
		sval_t GlobalAdjustment = CalleeFunc->ComputeGlobalStackAdjustment();
		if (0 != GlobalAdjustment) {
			CalleeDelta -= GlobalAdjustment;
			SMP_msg("INFO: Global stack adjustment analysis produced callee delta of %ld bytes after %lx\n",
				(long) CalleeDelta, (unsigned long) CallTargetAddr);
		}
	}

	return CalleeDelta;
} // end of SMPFunction::GetStackDeltaForCallee()

// Compute a consistent (or smallest) stack adjustment seen program-wide after all calls to the current function.
//  Do not return a non-zero value unless more than one call site can be used as evidence.
sval_t SMPFunction::ComputeGlobalStackAdjustment(void) {
	bool FoundZeroAdjustment = false;
	sval_t GlobalAdjustment = 0;
	sval_t NegativeAdjustment = -10000; // record negative adjustments detected
	sval_t PositiveAdjustment = 10000; // record positive adjustments detected
	size_t NumCallSites = this->AllCallSites.size();

	// Use cached value if already computed.
	if (this->StackAdjustmentComputed) {
		return this->GlobalStackAdjustment;
	}

	if (1 < NumCallSites) { // if only one call site, it is dangerous to draw conclusions about seeming "adjustments."
		set<ea_t>::iterator CallSiteIter;
		for (CallSiteIter = this->AllCallSites.begin(); CallSiteIter != this->AllCallSites.end(); ++CallSiteIter) {
			ea_t CallSiteAddr = (*CallSiteIter);
			func_t *CurrFunc = SMP_get_func(CallSiteAddr);
			assert(NULL != CurrFunc);
			ea_t CallerFirstAddr = CurrFunc->startEA;
			SMPFunction *CallerFunc = this->GetProg()->FindFunction(CallerFirstAddr);
			assert(NULL != CallerFunc);
			sval_t CurrentAdjustment = CallerFunc->GetStackAdjustmentForCallee(CallSiteAddr);
			// See if CurrentAdjustment is a new, lowest positive value for GlobalAdjustment.
			if ((0 < CurrentAdjustment) && (CurrentAdjustment < PositiveAdjustment)) {
				PositiveAdjustment = CurrentAdjustment;
			}
			else if ((0 > CurrentAdjustment) && (CurrentAdjustment > NegativeAdjustment)) {
				NegativeAdjustment = CurrentAdjustment;
			}
			else if (0 == CurrentAdjustment) {
				FoundZeroAdjustment = true;
				break; // Any zero adjustment found invalidates non-zero inferences
			}
		}
	}

	// See if we consistently had positive or negative adjustments
	if (FoundZeroAdjustment) {
		GlobalAdjustment = 0; // cannot be a clear non-zero indication if we found any zeroes
	}
	else if (PositiveAdjustment < 10000) { // found at least one positive adjustment
		if (NegativeAdjustment > -10000) { // found at least one negative adjustment; bad
			GlobalAdjustment = 0; // inconsistent; reset to zero
		}
		else {
			GlobalAdjustment = PositiveAdjustment;
		}
	}
	else if (NegativeAdjustment > -10000) { // found negative but no positive adjustments
		GlobalAdjustment = NegativeAdjustment;
	}
	else { // did not find negative or positive adjustments
		GlobalAdjustment = 0;
	}

	this->StackAdjustmentComputed = true; // signal caching of the value for future speed
	this->GlobalStackAdjustment = GlobalAdjustment; // cache the value
	return GlobalAdjustment;
} // end of SMPFunction::ComputeGlobalStackAdjustment()

// Use IDA Pro stack pointer deltas instead of doing our own analysis.
bool SMPFunction::UseIDAStackPointerDeltas(void) {
	list<SMPInstr *>::iterator InstIter;
	SMPInstr *CurrInst;
#if SMP_COMPARE_IDA_STARS_STACK_POINTER_DELTAS
	bool IDATraceFlag = (0 == strcmp("do_length", this->GetFuncName()));
#endif

	InstIter = this->Instrs.begin();
#if SMP_USE_SSA_FNOP_MARKER
	++InstIter; // skip marker pseudo-instruction
#endif
	while (InstIter != this->Instrs.end()) {
		CurrInst = *InstIter;
		sval_t IDAProDelta = get_spd(this->GetFuncInfo(), CurrInst->GetAddr());
		CurrInst->SetStackPtrOffset(IDAProDelta);
		++InstIter;
		if (IDATraceFlag) {
			SMP_msg("INFO: IDA Pro stack delta trace: %ld at %lx\n", (long) IDAProDelta, (unsigned long) CurrInst->GetAddr());
		}
	}
	return true;
} // end of SMPFunction::UseIDAStackPointerDeltas()

// Analyze changes to the stack pointer over all instructions.
bool SMPFunction::AnalyzeStackPointerDeltas(void) {
	list<pair<SMPBasicBlock *, sval_t> > WorkList;
	vector<SMPInstr *>::iterator InstIter;
	SMPInstr *CurrInst;
	sval_t CurrentDelta = 0;
	sval_t DeltaIncrement = 0; // change when reprocessing a block in alloca()-calling function
	bool ConsistentNetDelta = true; // Net change to stack pointer is consistent at all RETURN locations
	bool ConflictingValuesSeen = false; // At least one block was entered with multiple deltas
	bool StackPointerRestoreSeen = false; // Stack pointer restored; must become true if ConflictingValuesSeen
	bool ReturnSeen = false;
	bool IDAProSucceeded = this->AnalyzedSP;

#if SMP_COMPARE_IDA_STARS_STACK_POINTER_DELTAS
	bool DebugFlag = (0 == strcmp("_aesni_set_encrypt_key", this->GetFuncName()));
	bool TraceFlag = (0 == strcmp("_aesni_set_encrypt_key", this->GetFuncName()));
#endif

	if (!this->HasGoodRTLs()) {
		SMP_msg("INFO: Using IDA Pro stack pointer deltas for BADRTLS function %s .\n", this->GetFuncName());
		(void) this->UseIDAStackPointerDeltas();
		this->AnalyzedSP = false;
		return false; // leave it unsolved
	}

#if 0
	// Temporarily pull the functions that call alloca out of the stack pointer delta computations, so
	//  that we can focus on solving other problems.
	if (this->CallsAlloca || this->HasPushAfterFrameAlloc()) {
		if (!this->AnalyzedSP) {
			(void) this->UseIDAStackPointerDeltas();
			return false; // leave it unsolved
		}
		else {
			SMP_msg("INFO: Using IDA Pro stack pointer deltas for alloca-calling function %s .\n", this->GetFuncName());
			return this->UseIDAStackPointerDeltas();
		}
	}
#endif

	// In order to precisely track stack deltas, we need to deal with instruction sequences that save the stack pointer
	//  and then restore it later. This requires a reaching definitions data flow analysis that includes, at a minimum,
	//  all stack definitions (normalized by stack delta, so that we do not confuse [esp+20] and [esp+20] where the values
	//  of esp are not the same). We also need to keep track of stack pointer saves in both registers and in stack locations.
	// In order for the information about saved stack pointer copies to be available as soon as we need them in the stack
	//  delta analysis, we have to perform both stack delta analysis and reaching definitions analysis at the same time. Luckily,
	//  both analyses are well suited to being performed as forward analyses starting from the entry basic block.
	//
	// Data structures for the reaching definitions analysis include a ReachesIn and a ReachesOut set for each basic block, a
	//  VarKill set for each block, and a DownExposedDefs set for each block. The VarKill set is shared with the later Live Variable
	//  Analysis (LVA), so we compute the VarKill and the UpExposed sets (UpExposed is only used by LVA) on the first pass through
	//  each block. The VarKill and all other LVA sets are sets of operands. The ReachesIn, ReachesOut, and DownExposedDefs sets
	//  are sets of definitions, where a definition is a pair<operand, instruction address>. The StackPtrCopySet is a triple of
	//   <operand, instruction address, stack delta>, arranged as a pair of pairs <operand, <addr, delta> >
	//
	// Algorithm: We maintain a WorkList of pairs <basic block pointer, incoming stack delta to that block>
	//
	// All sets are empty at the beginning.
	// Add the entry basic block to the WorkList, with IncomingDelta of zero.
	// while (WorkList is not empty) do
	//    de-queue first block from WorkList, obtain IncomingDelta
	//    Compute ReachesIn as the union of the ReachesOut of all predecesssor blocks
	//    if (block has not already been processed) then
	//       mark block as processed
	//       for each inst in block (forward iteration) do
	//           for each USE in inst do
	//              if USE operand not in VarKill set for block then
	//                  add USE operand to UpExposed set for block
	//              endif
	//              if USE operand is a stack pointer value AND it will produce DEF that is a stack pointer value then
	//                  if DEF is stack pointer register then  { a stack pointer value that was saved is being restored }
	//                      retrieve new stack pointer delta from saved value in StackPtrCopySet, looking it up in
	//                          that set using the reaching definitions for the USE operand. If inconsistent  ******
	//                  else { stack pointer value is being saved somewhere besides the stack pointer register }
	//                      add stack delta to StackPtrCopySet for DEF that is receiving it in current inst
	//                  endif
	//               endif
	//            endfor { each USE }
	//            for each DEF in inst do
	//               if register or stack operand then 
	//                  add to VarKill set
	//                  update DownExposedDefs set (insert, or replace current def for this operand)
	//               endif
	//            endfor { each DEF }
	//            Store IncomingDelta for current instruction
	//            Get change in delta for current instruction
	//            Add current change to IncomingDelta
	//       endfor { each inst }
	//       At end of block, make ReachesOut set be (ReachesIn minus VarKill) union DownExposedDefs
	//       For each successor block, add pairs <block pointer, IncomingDelta> to end of WorkList
	//    else { block has already been processed at least once}
	//       if IncomingDelta from WorkList is inconsistent with old IncomingDelta then
	//          if function calls alloca() then
	//             if new IncomingDelta makes stack frame look larger than old IncomingDelta then
	//                ignore new IncomingDelta and just process reaching definitions sets below
	//             else
	//                use new IncomingDelta and re-process deltas in this block to converge to
	//                 smallest stack frame, which means we are basically ignoring alloca()'s as much as possible.
	//             endif
	//          else
	//             Set AnalyzedSP to false, emit error message, clear WorkList and bail out of this function.
	//          endif
	//       endif { inconsistent IncomingDelta values }
	//       Recompute ReachesIn as union of ReachesOut of all predecessor blocks
	//       if ReachesIn set changed then
	//          recompute ReachesOut without examining instructions unless alloca() case requires iterating through instructions
	//       endif
	//       if any change in deltas or reaching definitions sets, then add block to end of WorkList along with all successor blocks.
	//    endif
	// end while

	// Mark all blocks as unprocessed
	this->ResetProcessedBlocks();

	this->AnalyzedSP = true;

	// Put the entry block on the work list.
	assert(0 < this->Blocks.size());
	pair<SMPBasicBlock *, sval_t> WorkingPair (this->Blocks.front(), CurrentDelta);
	WorkList.push_back(WorkingPair);

	// While blocks exist on the work list
	//  if block already processed, confirm that we are re-entering
	//    the block with the same stack pointer delta as previously,
	//    and pop it off the work list
	//    otherwise declare the stack pointer to be un-analyzeable;
	//  else
	//     iterate through all instructions in the block, analyzing
	//     the stack pointer delta of each inst and accumulating current delta
	//     At the end of the block, put the successor blocks on the work list.
	// For both cases, maintain and update reaching definitions sets, and the
	//  UpExposed and VarKill sets that are used by LVA as well as reaching defs analysis.
	bool ReprocessingAllocaBlocks = false;
	bool ReachesInChanged;
	bool ReachesOutChanged = false;
	do {
		SMPBasicBlock *CurrBlock = WorkList.front().first;
		sval_t IncomingDelta = WorkList.front().second;

		if (0 < IncomingDelta) {
			SMP_msg("ERROR: Stack delta of %ld implies stack underflow in func at %lx\n",
				(long) IncomingDelta, (unsigned long) this->FirstEA);
			this->AnalyzedSP = false;
			WorkList.clear();
			break;
		}

		if (CurrBlock->IsProcessed()) { // already processed
			ReachesOutChanged = false;
#if 0
			ReachesInChanged = CurrBlock->ComputeReachesInSet();
			if (ReachesInChanged) {
				ReachesOutChanged = CurrBlock->ComputeReachesOutSet();
			}
#else
			if (CurrBlock->IsReachesOutStale()) {
				ReachesOutChanged = CurrBlock->ComputeReachesOutSet();
			}
#endif
			if (ReachesOutChanged) {
				// Push the successor blocks onto the work list
				sval_t SuccIncomingDelta = CurrBlock->GetOutgoingStackDelta();
				list<SMPBasicBlock *>::iterator SuccIter;
				for (SuccIter = CurrBlock->GetFirstSucc(); SuccIter != CurrBlock->GetLastSucc(); ++SuccIter) {
					pair<SMPBasicBlock *, sval_t> SuccPair (*SuccIter, SuccIncomingDelta);
					WorkList.push_back(SuccPair);
				}
			}
			InstIter = CurrBlock->GetFirstInst();
			sval_t PrevIncomingDelta = (*InstIter)->GetStackPtrOffset();
			if (IncomingDelta == PrevIncomingDelta) {
				// No error, already processed.
				WorkList.pop_front(); // discard already processed block.
			}
#if 1
			else if (this->CallsAlloca || this->HasPushAfterFrameAlloc()) {
#else
			else {
#endif
				ConflictingValuesSeen = true;
				// Calls to alloca() become additional stack allocations, which can produce
				//  multiple possible stack deltas for an instruction if different paths
				//  to the instruction do not hit the same alloca() calls, so it is not
				//  an error to have conflicting deltas in the functions that call alloca().
				//  We want to converge to the smallest magnitude deltas, which are the greatest
				//  values because the deltas are negative. This is the opposite of IDA Pro, which
				//  seems to use the largest stack deltas it has seen.
				if (PrevIncomingDelta >= IncomingDelta) {
					// Old incoming delta should be retained.
					WorkList.pop_front(); // discard already processed block.
				}
				else {
					CurrBlock->SetProcessed(false);
					ReprocessingAllocaBlocks = true;
					DeltaIncrement = IncomingDelta - PrevIncomingDelta;
					continue;  // Make the loop come around and process this block again, using
							   //  the new incoming delta. Because we do this only when it decreases
							   //  the stack size as seen by this block, no infinite loop is possible.
				}
			}
#if 1
			else {
				this->AnalyzedSP = false;
				SMP_msg("ERROR: Stack delta: PrevIncoming is %ld NewIncoming is %ld at %lx\n",
					(long) PrevIncomingDelta, (long) IncomingDelta, (unsigned long) (*InstIter)->GetAddr());
				WorkList.clear();
			}
#endif
		}
		else { // not already processed
			// ReprocessingAllocaBlocks => Reaching definitions sets have already been computed; just need to do stack delta analysis
			ReachesOutChanged = false;
#if 0
			ReachesInChanged = CurrBlock->ComputeReachesInSet();
			if (ReachesInChanged && ReprocessingAllocaBlocks) {
				// Because block is not truly being processed for the first time, the ReachesOut set can be
				//  recomputed without processing instructions, as the DEDefs set and VarKill set will never
				//  change after the first pass through the block.
				ReachesOutChanged = CurrBlock->ComputeReachesOutSet();
			}

			if (CurrBlock->IsReachesOutStale()) {
				ReachesOutChanged = CurrBlock->ComputeReachesOutSet();
			}
#endif
			CurrBlock->SetProcessed(true);
			WorkList.pop_front();
			for (InstIter = CurrBlock->GetFirstInst(); InstIter != CurrBlock->GetLastInst(); ++InstIter) {
				CurrInst = (*InstIter);
				if (CurrInst->IsFloatNop()) {
					continue; // skip marker instruction
				}
				ea_t InstAddr = CurrInst->GetAddr();
				if (InstAddr == this->GetFirstFrameAllocInstAddr()) {
					// Record the reset point for frame deallocations
					this->PreAllocStackDelta = IncomingDelta;
				}

				CurrInst->SetStackPtrOffset(IncomingDelta);

				// Search for tail calls, defined strictly as having an incoming stack delta of zero and
				//  being jumps to far chunks.
				if ((0 == IncomingDelta) && (CurrInst->IsBranchToFarChunk())) {
					CurrInst->SetTailCall();
#if 0
					SMP_msg("Found tail call at %lx from %s: %s\n", (unsigned long) InstAddr, this->GetFuncName(),
							CurrInst->GetDisasm());
#endif
				}

#if SMP_COMPARE_IDA_STARS_STACK_POINTER_DELTAS
				if (DebugFlag && IDAProSucceeded && !(this->CallsAlloca || this->HasPushAfterFrameAlloc())) {
					sval_t IDAProDelta = get_spd(this->GetFuncInfo(), InstAddr);
					if ((IDAProDelta != IncomingDelta) && (!CurrInst->MDIsHaltInstr())) {
						// IDA Pro special-cases the HALT instruction to make it appear that the
						//  incoming stack delta is zero. We do no such special case delta adjudstment,
						//  so we suppress error messages, as our delta will be non-zero.
						SMP_msg("ERROR: At %lx IDA Pro has stack pointer delta of %ld and we compute %ld\n", (unsigned long) InstAddr,
							(long) IDAProDelta, (long) IncomingDelta);
					}
				}
				if (TraceFlag) {
					SMP_msg("INFO: Stack delta trace: %ld at %lx\n",
						(unsigned long) IncomingDelta, (unsigned long) InstAddr);
				}
#endif

				// As soon as the stack ptr offset has been set for the current instruction, we can normalize
				//  all of its stack DEFs and USEs.
				bool StackOpsChanged = CurrInst->MDNormalizeStackOps(UseFP, this->GetFramePtrStackDelta(), ReprocessingAllocaBlocks, DeltaIncrement);

				// Dataflow equation for upward exposed variables: If a variable has not been
				//  killed yet in this block, starting from the top of the block, and it is used
				//  in the current instruction, then it is upwardly exposed.
				set<DefOrUse, LessDefUse>::iterator CurrUse;
				if (!ReprocessingAllocaBlocks) { // Only compute on first pass through block
					for (CurrUse = CurrInst->GetFirstUse(); CurrUse != CurrInst->GetLastUse(); ++CurrUse) {
						op_t UseOp = CurrUse->GetOp();
						CanonicalizeOpnd(UseOp);
						if (MDIsDataFlowOpnd(UseOp, this->UsesFramePointer())) {
							// We have a register or stack operand. If stack operand, it is normalized, i.e. EBP-4 might be ESP-8,
							//  where the ESP-8 refers to the value of ESP upon entry to the function, not its current value.
							//  This normalization makes each stack location uniquely named (no aliases at different code locations due
							//  to different values of ESP at different code locations).
							// We only track certain kinds of operands in our data flow analyses.
							// Only add non-immediate operands that are not already killed in this block.
							//  o_near and o_far operands are code addresses in immediate form, e.g.
							//  call _printf might be call 0x8048040, with o_near = 0x8048040.
							if (!(CurrBlock->MDAlreadyKilled(UseOp))) {
								CurrBlock->AddUpExposed(UseOp);
							}
						}
					}
				}

				// Find stack pointer saves and restores.
				bool StackPtrSaved;
				sval_t SavedDelta;
				op_t CopyOperand;
				bool SavedDeltaHasNewValue = false;
				bool ErrorFlag = false;
				if (CurrInst->MDIsStackPtrSaveOrRestore(this->UsesFramePointer(), this->GetFramePtrStackDelta(), StackPtrSaved, SavedDelta, CopyOperand, ErrorFlag)) {
					// NOTE: If CopyOperand is a stack location, it is normalized.
					if (StackPtrSaved) {
						// Insert new entry into the StackPtrCopySet. For the ReprocessingAllocaBlocks case, this might be
						//  just a tricky update of the delta for an existing item in the set.
						bool DeltaInserted = this->AddToStackPtrCopySet(CopyOperand, InstAddr, SavedDelta);
						if (TraceFlag) {
							SMP_msg("INFO: Stack delta saved: %ld at %lx\n", (long) SavedDelta, (unsigned long) InstAddr);
						}
					}
					else { // stack pointer was restored from saved value
						StackPointerRestoreSeen = true;
						SavedDeltaHasNewValue = true; // no need to compute effect of restore instruction later
						if (ReprocessingAllocaBlocks) {
							// Now that the stack pointer has been restored, the effect of the alloca() should
							//  be undone. We no longer need to adjust delta values for the rest of the block.
							DeltaIncrement = 0;
						}
					}
				} // end if (CurrInst->MDIsStackPtrSaveOrRestore())
				else if (ErrorFlag) {
					this->AnalyzedSP = false;
					WorkList.clear();
					SMP_msg("ERROR: ErrorFlag=true from MDIsStackPtrSaveOrRestore() at %lx\n",
						(unsigned long) InstAddr);
					break;
				}
				else if (CurrInst->MDIsLeaveInstr()) {
					// LEAVE is a restoration of a stack pointer, not processed by CurrInst->MDIsStackPtrSaveOrRestore()
					StackPointerRestoreSeen = true; 
				}

				// Update VarKill and DownExposedDefs sets for DEFs in current instruction.
				// Dataflow equation for killed variables: If a variable is defined in any
				//  instruction in the block, it is killed by this block (i.e. prior definitions
				//  of that variable will not make it through the block).
				if (!ReprocessingAllocaBlocks) { // Only compute on first pass through block
					set<DefOrUse, LessDefUse>::iterator CurrDef;
					for (CurrDef = CurrInst->GetFirstDef(); CurrDef != CurrInst->GetLastDef(); ++CurrDef) {
						op_t DefOp = CurrDef->GetOp();
						if (MDIsDataFlowOpnd(DefOp, this->UsesFramePointer())) {
							// We have a register or stack operand. If stack operand, it is normalized, i.e. EBP-4 might be ESP-8,
							//  where the ESP-8 refers to the value of ESP upon entry to the function, not its current value.
							//  This normalization makes each stack location uniquely named (no aliases at different code locations due
							//  to different values of ESP at different code locations).
							CurrBlock->AddVarKill(DefOp);
							CurrBlock->UpdateDownExposedDefs(DefOp, InstAddr);
						}
					}
				}

				if (SavedDeltaHasNewValue) {
					IncomingDelta = SavedDelta; // from restore instruction
				}
				else {
					CurrentDelta = CurrInst->AnalyzeStackPointerDelta(IncomingDelta, this->GetFramePtrStackDelta());
					if (SMP_STACK_POINTER_BITWISE_AND_CODE == CurrentDelta) {
						// For now, we ignore instructions that AND a constant into the stack pointer.
						CurrentDelta = 0;
						SMP_msg("WARNING: Stack pointer bitwise AND ignored at %lx\n",
							(unsigned long) CurrInst->GetAddr());
					}
					else if (SMP_STACK_DELTA_ERROR_CODE == CurrentDelta) {
						this->AnalyzedSP = false;
						SMP_msg("ERROR: Stack delta unanalyzeable at %lx\n", (unsigned long) InstAddr);
						WorkList.clear();
						break;
					}
					SMPitype FlowType = CurrInst->GetDataFlowType();
					IncomingDelta += CurrentDelta;
					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",
									(unsigned long) CurrInst->GetAddr());
								ConsistentNetDelta = false;
								this->AnalyzedSP = false;
								WorkList.clear();
								break;
							}
						}
						else { // First RETURN statement seen.
							ReturnSeen = true;
							this->NetStackDelta = IncomingDelta;
#if SMP_AUDIT_STACK_POINTER_DELTAS
							if (CALLING_CONVENTION_DEFAULT_FUNCTION_STACK_DELTA != IncomingDelta) {
								SMP_msg("WARNING: Stack delta not %d after return instruction at %lx\n", 
									CALLING_CONVENTION_DEFAULT_FUNCTION_STACK_DELTA, (unsigned long) CurrInst->GetAddr());
							}
#endif
						}
						// If we permitted inconsistent stack deltas previously, then the stack pointer has to
						//  have been restored, e.g. if we allocate a frame with sub esp,32 and then we later
						//  have paths that pass through an alloca() call, a push, etc., then the alloca() or
						//  push will not be undone by add esp,32. It must be undone by something like mov esp,ebp.
						if (ConflictingValuesSeen && !StackPointerRestoreSeen) {
							SMP_msg("ERROR: Inconsistent stack deltas seen, no stack pointer restore before return instruction at %lx\n",
								(unsigned long) CurrInst->GetAddr());
							this->AnalyzedSP = false;
							WorkList.clear();
							break;
						}
					}
				} // end if (SavedDeltaHasNewValue) ... else ...
			} // end for each instruction in WorkList block
			if (CurrBlock->IsReachesOutStale()) {
				ReachesOutChanged = CurrBlock->ComputeReachesOutSet();
			}
			// Push the successor blocks onto the work list if anything changed
			if (this->AnalyzedSP) { // if we do not have an error already
				CurrBlock->SetOutgoingStackDelta(IncomingDelta); // record incoming delta for all successors
				if (ReachesOutChanged || (!ReprocessingAllocaBlocks)) { // if anything changed (deltas or reaching defs ReachOut set)
					list<SMPBasicBlock *>::iterator SuccIter;
					if (DebugFlag && (0 == IncomingDelta)) {
						SMP_msg("ERROR: Pushing WorkList items with IncomingDelta of zero. Dumping Block:\n");
						CurrBlock->Dump();
					}
					for (SuccIter = CurrBlock->GetFirstSucc(); SuccIter != CurrBlock->GetLastSucc(); ++SuccIter) {
						pair<SMPBasicBlock *, sval_t> SuccPair (*SuccIter, IncomingDelta);
						WorkList.push_back(SuccPair);
					}
				}
			}
		} // end if block already processed ... else ...
		ReprocessingAllocaBlocks = false; // reset to default before processing next worklist element
	} while (!WorkList.empty());

	this->STARSStackPtrAnalysisPerformed = true;
	if (this->AnalyzedSP) {
		if (CALLING_CONVENTION_DEFAULT_FUNCTION_STACK_DELTA != this->NetStackDelta) {
			SMP_msg("WARNING: Non-default stack ptr delta %ld for function: %s\n", (long) this->NetStackDelta, this->GetFuncName());
		}
		if (this->StackAdjustmentComputed 
			&& (this->GlobalStackAdjustment != (CALLING_CONVENTION_DEFAULT_FUNCTION_STACK_DELTA - this->NetStackDelta))) {
			// Oops. When program graph cycles caused us to try to compute the GlobalStackAdjustment as our best guess
			//  for this function's effect on the stack delta, we told our callers that these three values would cancel out.
			//  They do not. Our callers have now been using a bad stack delta for their call instructions. Too late for
			//  anything but a diagnostic message.
				SMP_msg("ERROR: Earlier GlobalStackAdjustment computation %ld does not agree with current NetStackDelta result for function: %s\n",
					(long) this->GlobalStackAdjustment, this->GetFuncName());
		}
	}


	if (IDAProSucceeded) {
		if (!this->AnalyzedSP) {
			SMP_msg("ERROR: Stack Ptr Delta Analysis succeeded in IDA, failed in STARS for %lx : %s\n", 
				(unsigned long) this->FirstEA, this->GetFuncName());
		}
	}
	else {
		if (this->AnalyzedSP) {
			SMP_msg("SUCCESS: Stack Ptr Delta Analysis failed in IDA, succeeded in STARS for %lx : %s\n",
				(unsigned long) this->FirstEA, this->GetFuncName());
		}
	}
	if (!this->AnalyzedSP) {
		(void) this->UseIDAStackPointerDeltas();
	}

	// Cannot keep the reaching defs around on huge benchmarks, or we run out of memory.
	//  Once we have SSA form, we can obtain reaching defs info on the fly if we want it.
	list<SMPBasicBlock *>::iterator BlockIter;
	for (BlockIter = this->Blocks.begin(); BlockIter != this->Blocks.end(); ++BlockIter) {
		(*BlockIter)->FreeReachingDefsMemory();
	}

	return this->AnalyzedSP;
} // end of SMPFunction::AnalyzeStackPointerDeltas()

// Insert the arguments into the StackPtrCopySet; or, if a matching entry already exists
//  with a StackDelta of greater magnitude than StackDelta, update just the StackDelta.
// Return true if StackDelta was inserted, false if it was used to update an old entry.
bool SMPFunction::AddToStackPtrCopySet(op_t CopyOp, ea_t InstAddr, sval_t StackDelta) {
	bool NewInsertion;
	pair<ea_t, sval_t> InsertStackDefn(InstAddr, StackDelta);
	pair<op_t, pair<ea_t, sval_t> > InsertStackDefnOp(CopyOp, InsertStackDefn);
	set<pair<op_t, pair<ea_t, sval_t> >, LessStackDeltaCopy>::iterator FindIter;
	pair<set<pair<op_t, pair<ea_t, sval_t> >, LessStackDeltaCopy>::iterator, bool> InsertResult;

	FindIter = this->StackPtrCopySet.find(InsertStackDefnOp);
	if (FindIter == this->StackPtrCopySet.end()) {
		// Not already present; insert new triple.
		NewInsertion = true;
		InsertResult = this->StackPtrCopySet.insert(InsertStackDefnOp);
		assert(InsertResult.second);
	}
	else {
		// Already there; see if delta needs to be updated.
		NewInsertion = false;
		pair<op_t, pair<ea_t, sval_t> > OldStackDefnOp(*FindIter);
		// Favor a smaller stack frame for the alloca-calling functions, e.g. favor -24 over -32 as a delta.
		if (StackDelta > OldStackDefnOp.second.second) {
			// Replace the old entry with a new one.
			this->StackPtrCopySet.erase(FindIter);
			InsertResult = this->StackPtrCopySet.insert(InsertStackDefnOp);
			assert(InsertResult.second);
		}
	}

	return NewInsertion;
} // end of SMPFunction::AddToStackPtrCopySet()

void SMPFunction::FindAllAllocsAndDeallocs(void) {
	bool FoundAllocInstr = false;
	bool FoundDeallocInstr = false;
	bool DebugFlag = false;
#if SMP_DEBUG_FRAMEFIXUP
	DebugFlag |= (0 == strcmp("frame_dummy", this->GetFuncName()));
#endif

	// Now, if LocalVarsSize is not zero, we need to find the instruction
	//  in the function prologue that allocates space on the stack for
	//  local vars. This code could be made more robust in the future
	//  by matching LocalVarsSize to the immediate value in the allocation
	//  instruction. However, IDA Pro is sometimes a little off on this
	//  number. **!!**
	if (0 < this->LocalVarsSize) {
		if (DebugFlag) SMP_msg("Searching for alloc and dealloc\n");
		list<SMPInstr *>::iterator InstIter = this->Instrs.begin();
#if SMP_USE_SSA_FNOP_MARKER
		++InstIter;  // skip marker instruction
#endif
		for ( ; InstIter != this->Instrs.end(); ++InstIter) {
			SMPInstr *CurrInst = (*InstIter);
			ea_t addr = CurrInst->GetAddr();

			// Keep the most recent instruction in the DeallocInstr
			//  in case we reach the return without seeing a dealloc.
			if (!FoundDeallocInstr) {
				this->LocalVarsDeallocInstr = addr;
			}

			if (!FoundAllocInstr
				&& CurrInst->MDIsFrameAllocInstr()) {
#if SMP_DEBUG_CONTROLFLOW
				SMP_msg("Returned from MDIsFrameAllocInstr()\n");
#endif
				this->LocalVarsAllocInstr = addr;
				FoundAllocInstr = true;
				if (DebugFlag) SMP_msg("Found alloc: %s\n", CurrInst->GetDisasm());
				// As soon as we have found the local vars allocation,
				//  we can try to fix incorrect sets of UseFP by IDA.
				// NOTE: We might want to extend this in the future to
				//  handle functions that have no locals.  **!!**
				bool FixedUseFP = MDFixUseFP();
#if SMP_DEBUG_FRAMEFIXUP
				if (FixedUseFP) {
					SMP_msg("Fixed UseFP in %s\n", this->GetFuncName());
				}
#endif
				if (this->UsesFramePointer()) { // now that MDFixUseFP() has validated this flag ...
					this->FindFramePointerDelta(); // find stack delta that is saved in frame pointer in function prologue
				}
			}
			else if (FoundAllocInstr) {
				// We can now start searching for the DeallocInstr.
				if (CurrInst->MDIsFrameDeallocInstr(UseFP, this->LocalVarsSize)) {
					// Keep saving the most recent addr that looks
					//  like the DeallocInstr until we reach the
					//  end of the function. Last one to look like
					//  it is used as the DeallocInstr.
#if SMP_DEBUG_CONTROLFLOW
					SMP_msg("Returned from MDIsFrameDeallocInstr()\n");
#endif
					this->LocalVarsDeallocInstr = addr;
					FoundDeallocInstr = true;
				}
				else {
					if (DebugFlag) SMP_msg("Not dealloc: %s\n", CurrInst->GetDisasm());
				}
			}
		} // end for (list<SMPInstr *>::iterator InstIter ... )
		if (!FoundAllocInstr) {
			// Could not find the frame allocating instruction.  Bad.
			// See if we can find the point at which the stack allocation reaches
			//  a total of FuncInfo.frsize+frregs, regardless of whether it happened by push
			//  instructions or some other means.
			this->LocalVarsAllocInstr = this->FindAllocPoint(this->FuncInfo.frsize + this->FuncInfo.frregs);
#if SMP_DEBUG_CONTROLFLOW
			SMP_msg("Returned from FindAllocPoint()\n");
#endif
#if SMP_DEBUG_FRAMEFIXUP
			if (BADADDR == this->LocalVarsAllocInstr) {
				SMP_msg("WARNING: Could not find stack frame allocation in %s\n",
					this->GetFuncName());
				SMP_msg("LocalVarsSize: %lu  SavedRegsSize: %u ArgsSize: %lu\n",
					(unsigned long) LocalVarsSize, CalleeSavedRegsSize, (unsigned long) IncomingArgsSize);
			}
			else {
				SMP_msg("FindAllocPoint found %lx for function %s\n",
					(unsigned long) this->LocalVarsAllocInstr, this->GetFuncName());
			}
#endif
		}
#if SMP_DEBUG_FRAMEFIXUP
		if (!FoundDeallocInstr) {
			// Could not find the frame deallocating instruction.  Bad.
			// Emit diagnostic and use the last instruction in the
			// function.
			SMP_msg("WARNING: Could not find stack frame deallocation in %s\n",
				this->GetFuncName());
		}
#endif
	}
	// else LocalVarsSize was zero, meaning that we need to search 
	//  for the end of the function prologue code and emit stack frame
	//  annotations from that address (i.e. this method returns that
	//  address). We will approximate this by finding the end of the
	//  sequence of PUSH instructions at the beginning of the function.
	//  The last PUSH instruction should be the last callee-save-reg
	//  instruction. We can make this more robust in the future by
	//  making sure that we do not count a PUSH of anything other than
	//  a register. **!!**
	// NOTE: 2nd prologue instr is usually mov ebp,esp
	// THE ASSUMPTION THAT WE HAVE ONLY PUSH INSTRUCTIONS BEFORE
	// THE ALLOCATING INSTR IS ONLY TRUE WHEN LOCALVARSSIZE == 0;
	else {
		ea_t SaveAddr = this->FuncInfo.startEA;
		list<SMPInstr *>::iterator InstIter = this->Instrs.begin();
#if SMP_USE_SSA_FNOP_MARKER
		++InstIter;  // skip marker instruction
#endif
		for ( ;	InstIter != this->Instrs.end(); ++InstIter) {
			SMPInstr *CurrInst = (*InstIter);
			insn_t CurrCmd = CurrInst->GetCmd();
			ea_t addr = CurrInst->GetAddr();
			if (CurrCmd.itype == NN_push)
				SaveAddr = addr;
			else
				break;
		}
		this->LocalVarsAllocInstr = SaveAddr;
		this->LocalVarsDeallocInstr = 0;
		// As soon as we have found the local vars allocation,
		//  we can try to fix incorrect sets of UseFP by IDA.
		// NOTE: We might want to extend this in the future to
		//  handle functions that have no locals.  **!!**
		bool FixedUseFP = this->MDFixUseFP();
#if SMP_DEBUG_FRAMEFIXUP
		if (FixedUseFP) {
			SMP_msg("Fixed UseFP in %s\n", this->GetFuncName());
		}
#endif
		if (this->UsesFramePointer()) { // now that MDFixUseFP() has validated this flag ...
			this->FindFramePointerDelta(); // find stack delta that is saved in frame pointer in function prologue
		}
	} // end if (LocalVarsSize > 0) ... else ...

	return;
} // end of SMPFunction::FindAllAllocsAndDeallocs()

// Compute FramePointerStackDelta as soon as possible so that it is available for SyncAllRTs().
void SMPFunction::FindFramePointerDelta(void) {
	bool FirstBlockProcessed = false;
	bool FPSaved = false;  // have seen push of frame pointer reg
	bool SPintoFP = false; // have seen copy of stack pointer into frame pointer
	sval_t IncomingDelta = 0;
	sval_t CurrentDelta;
	list<SMPInstr *>::iterator InstIter = this->Instrs.begin();
#if SMP_USE_SSA_FNOP_MARKER
	++InstIter;  // skip marker instruction
#endif
	while (!FirstBlockProcessed && (InstIter != this->Instrs.end())) {
		SMPInstr *CurrInst = (*InstIter);
		// Accumulate stack delta values.
		CurrentDelta = CurrInst->AnalyzeStackPointerDelta(IncomingDelta, this->GetFramePtrStackDelta());
		if (SMP_STACK_POINTER_BITWISE_AND_CODE == CurrentDelta) {
			// For now, we ignore instructions that AND a constant into the stack pointer.
			CurrentDelta = 0;
		}
		else if (SMP_STACK_DELTA_ERROR_CODE == CurrentDelta) {
			this->AnalyzedSP = false;
			break; // error exit
		}
		// Look for initialization of frame pointer, record its stack delta
		FirstBlockProcessed = CurrInst->IsLastInBlock();
		if (!FPSaved) { // still looking for "push <framepointerreg>"
			if (CurrInst->MDIsPushInstr() && CurrInst->GetCmd().Operands[0].is_reg(MD_FRAME_POINTER_REG)) {
				FPSaved = true;
			}
		}
		else if (!SPintoFP) { // found "push <framepointerreg>", looking for "fp := sp"
			insn_t CurrCmd = CurrInst->GetCmd();
			if ((CurrCmd.itype == MD_MOVE_INSTRUCTION) 
				&& (CurrInst->GetFirstDef()->GetOp().is_reg(MD_FRAME_POINTER_REG))
				&& (CurrInst->GetFirstUse()->GetOp().is_reg(MD_STACK_POINTER_REG))) {
				SPintoFP = true;
				this->FramePointerStackDelta = IncomingDelta;
				FirstBlockProcessed = true; // stop looking
				assert(this->UsesFramePointer());
			}
		}
		IncomingDelta += CurrentDelta;
		++InstIter;
	}

	return;
} // end of SMPFunction::FindFramePointerDelta()

// Figure out the different regions of the stack frame, and find the
//  instructions that allocate and deallocate the local variables space
//  on the stack frame.
// The stack frame info will be used to emit stack
//  annotations when Analyze() reaches the stack allocation
//  instruction that sets aside space for local vars.
// Set the address of the instruction at which these
//  annotations should be emitted. This should normally
//  be an instruction such as:  sub esp,48
//  However, for a function with no local variables at all,
//  we will need to determine which instruction should be
//  considered to be the final instruction of the function
//  prologue and return its address.
// Likewise, we find the stack deallocating instruction in
//  the function epilogue.
void SMPFunction::SetStackFrameInfo(void) {

#if SMP_COMPUTE_STACK_GRANULARITY
	// Now, find the boundaries between local variables.
	this->BuildLocalVarTable();
#endif

	// Get callee-saved regs info for remediation use.
	if (BADADDR != this->GetFirstFrameAllocInstAddr()) {
		this->MDFindSavedRegs();
	}

	return;
} // end of SMPFunction::SetStackFrameInfo()

// IDA Pro defines the sizes of regions in the stack frame in a way
//  that suits its purposes but not ours. The frsize field of the func_info_t
//  structure measures the distance between the stack pointer and the
//  frame pointer (ESP and EBP in the x86). This region includes some
//  of the callee-saved registers. So, the frregs field only includes
//  the callee-saved registers that are above the frame pointer.
//  x86 standard prologue on gcc/linux:
//    push ebp      ; save old frame pointer
//    mov ebp,esp   ; new frame pointer = current stack pointer
//    push esi      ; callee save reg
//    push edi      ; callee save reg
//    sub esp,34h   ; allocate 52 bytes for local variables
//
//  Notice that EBP acquires its final frame pointer value AFTER the
//  old EBP has been pushed. This means that, of the three callee saved
//  registers, one is above where EBP points and two are below.
//  IDA Pro is concerned with generating readable addressing expressions
//  for items on the stack. None of the callee-saved regs will ever
//  be addressed in the function; they will be dormant until they are popped
//  off the stack in the function epilogue. In order to create readable
//  disassembled code, IDA defines named constant offsets for locals. These
//  offsets are negative values (x86 stack grows downward from EBP toward
//  ESP). When ESP_relative addressing occurs, IDA converts a statement:
//    mov eax,[esp+12]
//  into the statement:
//    mov eax,[esp+3Ch+var_30]
//  Here, 3Ch == 60 decimal is the distance between ESP and EBP, and
//  var_30 is defined to have the value -30h == -48 decimal. So, the
//  "frame size" in IDA Pro is 60 bytes, and a certain local can be
//  addressed in ESP-relative manner as shown, or as [ebp+var_30] for
//  EBP-relative addressing. The interactive IDA user can then edit
//  the name var_30 to something mnemonic, such as "virus_size", and IDA
//  will replace all occurrences with the new name, so that code references
//  automatically become [ebp+virus_size]. As the user proceeds
//  interactively, he eventually produces very understandable code.
// This all makes sense for producing readable assembly text. However,
//  our analyses have a compiler perspective as well as a memory access
//  defense perspective. SMP distinguishes between callee saved regs,
//  which should not be overwritten in the function body, and local
//  variables, which can be written. We view the stack frame in logical
//  pieces: here are the saved regs, here are the locals, here is the
//  return address, etc. We don't care which direction from EBP the
//  callee-saved registers lie; we don't want to lump them in with the
//  local variables. We also don't like the fact that IDA Pro will take
//  the function prologue code shown above and declare frregs=4 and
//  frsize=60, because frsize no longer matches the stack allocation
//  statement sub esp,34h == sub esp,52. We prefer frsize=52 and frregs=12.
// So, the task of this function is to fix these stack sizes in our
//  private data members for the function, while leaving the IDA database
//  alone because IDA needs to maintain its own definitions of these
//  variables.
// Fixing means we will update the data members LocalVarsSize and
//  CalleeSavedRegsSize.
// NOTE: This function is both machine dependent and platform dependent.
//  The prologue and epilogue code generated by gcc-linux is as discussed
//  above, while on Visual Studio and other Windows x86 compilers, the
//  saving of registers other than EBP happens AFTER local stack allocation.
//  A Windows version of the function would expect to see the pushing
//  of ESI and EDI AFTER the sub esp,34h statement.
bool SMPFunction::MDFixFrameInfo(void) {
	int SavedRegsSize = 0;
	int OtherPushesSize = 0;  // besides callee-saved regs
	int NewLocalsSize = 0;
	int OldFrameTotal = this->CalleeSavedRegsSize + this->LocalVarsSize;
	bool Changed = false;
	bool DebugFlag = (0 == strcmp("__libc_csu_init", this->GetFuncName()));

	// Iterate through the first basic block in the function. If we find
	//  a frame allocating Instr in it, then we have local vars. If not,
	//  we don't, and LocalVarsSize should have been zero. Count the callee
	//  register saves leading up to the local allocation. Set data members
	//  according to what we found if the values of the data members would
	//  change.
	SMPBasicBlock *CurrBlock = this->Blocks.front();
	vector<SMPInstr *>::iterator CurrIter = CurrBlock->GetFirstInst();
#if SMP_USE_SSA_FNOP_MARKER
	++CurrIter;  // skip marker instruction
#endif
	for ( ; CurrIter != CurrBlock->GetLastInst(); ++CurrIter) {
		SMPInstr *CurrInstr = (*CurrIter);
		if (CurrInstr->MDIsPushInstr()) {
			// We will make the gcc-linux assumption that a PUSH in
			//  the first basic block, prior to the stack allocating
			//  instruction, is a callee register save. To make this
			//  more robust, we ensure that the register is from
			//  the callee saved group of registers, and that it has
			//  not been defined thus far in the function (else it might
			//  be a push of an outgoing argument to a call that happens
			//  in the first block when there are no locals). **!!!!**
			if (CurrInstr->MDUsesCalleeSavedReg()
				&& !CurrInstr->HasSourceMemoryOperand()) {
				SavedRegsSize += 4; // **!!** should check the size
				if (DebugFlag) SMP_msg("libc_csu_init SavedRegsSize: %d  %s\n", SavedRegsSize,
					CurrInstr->GetDisasm());
			}
			else {
				// Pushes of outgoing args can be scheduled so that
				//  they are mixed with the pushes of callee saved regs.
				OtherPushesSize += 4;
				if (DebugFlag) SMP_msg("libc_csu_init OtherPushesSize: %d  %s\n", OtherPushesSize,
					CurrInstr->GetDisasm());
			}
		}
		else if (CurrInstr->MDIsFrameAllocInstr()) {
			if (DebugFlag) SMP_msg("libc_csu_init allocinstr: %s\n", CurrInstr->GetDisasm());
			SavedRegsSize += OtherPushesSize;
			// Get the size being allocated.
			set<DefOrUse, LessDefUse>::iterator CurrUse;
			for (CurrUse = CurrInstr->GetFirstUse(); CurrUse != CurrInstr->GetLastUse(); ++CurrUse) {
				// Find the immediate operand.
				if (o_imm == CurrUse->GetOp().type) {
					// Get its value into LocalVarsSize.
					long AllocValue = (signed long) CurrUse->GetOp().value;
					// One compiler might have sub esp,24 and another
					//  might have add esp,-24. Take the absolute value.
					if (0 > AllocValue)
						AllocValue = -AllocValue;
					if (AllocValue != (long) this->LocalVarsSize) {
						Changed = true;
#if SMP_DEBUG_FRAMEFIXUP
						if (AllocValue + SavedRegsSize != OldFrameTotal)
							SMP_msg("Total frame size changed: %s OldTotal: %d NewTotal: %ld\n",
								this->GetFuncName(), OldFrameTotal, (AllocValue + SavedRegsSize));
#endif
						this->LocalVarsSize = (asize_t) AllocValue;
						this->CalleeSavedRegsSize = (ushort) SavedRegsSize;
						NewLocalsSize = this->LocalVarsSize;
					}
					else { // Old value was correct; no change.
						NewLocalsSize = this->LocalVarsSize;
						if (SavedRegsSize != this->CalleeSavedRegsSize) {
							this->CalleeSavedRegsSize = (ushort) SavedRegsSize;
							Changed = true;
#if SMP_DEBUG_FRAMEFIXUP
							SMP_msg("Only callee regs size changed: %s\n", this->GetFuncName());
#endif
						}
					}
				} // end if (o_imm == ...)
			} // end for all uses
			break; // After frame allocation instr, we are done
		} // end if (push) .. elsif frame allocating instr
	} // end for all instructions in the first basic block

	// If we did not find an allocating instruction, see if it would keep
	//  the total size the same to set LocalVarsSize to 0 and to set
	//  CalleeSavedRegsSize to SavedRegsSize. If so, do it. If not, we
	//  might be better off to leave the numbers alone.
	if (!Changed && (NewLocalsSize == 0)) {
		if (DebugFlag) SMP_msg("libc_csu_init OldFrameTotal: %d \n", OldFrameTotal);
		if (OldFrameTotal == SavedRegsSize) {
			this->CalleeSavedRegsSize = (ushort) SavedRegsSize;
			this->LocalVarsSize = 0;
			Changed = true;
		}
#if SMP_DEBUG_FRAMEFIXUP
		else {
			SMP_msg("Could not update frame sizes: %s\n", this->GetFuncName());
		}
#endif
	}

#if SMP_DEBUG_FRAMEFIXUP
	if ((0 < OtherPushesSize) && (0 < NewLocalsSize))
		SMP_msg("Extra pushes found of size %d in %s\n", OtherPushesSize,
			this->GetFuncName());
#endif

#if SMP_DEBUG_FRAMEFIXUP
	if (Changed) {
		SMP_msg("Fixed stack frame size info: %s\n", this->GetFuncName());
#if SMP_DEBUG_FRAMEFIXUP_VERBOSE
		SMPBasicBlock *CurrBlock = this->Blocks.front();
		SMP_msg("First basic block:\n");
		vector<SMPInstr *>::iterator InstIter = CurrBlock->GetFirstInst();
#if SMP_USE_SSA_FNOP_MARKER
		++InstIter;
#endif
		while (InstIter != CurrBlock->GetLastInst()) {
			SMP_msg("%s\n", (*InstIter)->GetDisasm());
			++InstIter;
		}
#endif
	}
#endif

	return Changed;
} // end of SMPFunction::MDFixFrameInfo()

// Some functions have difficult to find stack allocations. For example, in some
//  version of glibc, strpbrk() zeroes out register ECX and then pushes it more than
//  100 times in order to allocate zero-ed out local vars space for a character translation
//  table. We will use the stack pointer analysis of IDA to find out if there is a point
//  in the first basic block at which the stack pointer reaches the allocation total
//  that IDA is expecting for the local vars region.
// If so, we return the address of the instruction at which ESP reaches its value, else
//  we return BADADDR.
ea_t SMPFunction::FindAllocPoint(asize_t OriginalLocSize) {
	sval_t TargetSize = - ((sval_t) OriginalLocSize);  // negate; stack grows down 

#if SMP_DEBUG_FRAMEFIXUP
	bool DebugFlag = (0 == strcmp("_dl_runtime_resolve", this->GetFuncName()));
	if (DebugFlag)
		SMP_msg("%s OriginalLocSize: %lu\n", this->GetFuncName(), (unsigned long) OriginalLocSize);
#endif

	if (this->AnalyzedSP) {
		// Limit our analysis to the first basic block in the function.
		list<SMPInstr *>::iterator InstIter = this->Instrs.begin();
#if SMP_USE_SSA_FNOP_MARKER
		++InstIter;  // skip marker instruction
#endif
		for ( ; InstIter != this->Instrs.end(); ++InstIter) {
			SMPInstr *CurrInst = (*InstIter);
			ea_t addr = CurrInst->GetAddr();
			// get_spd() returns a cumulative delta of ESP
			sval_t sp_delta = get_spd(this->GetFuncInfo(), addr);
#if SMP_DEBUG_FRAMEFIXUP
			if (DebugFlag)
				SMP_msg("%s delta: %ld at %lx\n", this->GetFuncName(), (long) sp_delta, (unsigned long) addr);
#endif
			if (sp_delta == TargetSize) { // <= instead of == here?  **!!**
				// Previous instruction hit the frame size.
				if (InstIter == this->Instrs.begin()) {
					return BADADDR;  // cannot back up from first instruction
				}
				else {
					ea_t PrevAddr = (*(--InstIter))->GetAddr();
#if SMP_USE_SSA_FNOP_MARKER
					if ((*(this->Instrs.begin()))->GetAddr() == PrevAddr)
						return BADADDR;  // don't return marker instruction
					else
						return PrevAddr;
#else
					return PrevAddr;
#endif
				}
			}
			if (CurrInst->IsLastInBlock()) {
				// It could be that the current instruction will cause the stack pointer
				//  delta to reach the TargetSize. sp_delta is not updated until after the
				//  current instruction, so we need to look ahead one instruction if the
				//  current block falls through. On the other hand, if the current block
				//  ends with a jump or return, we cannot hit TargetSize.
				if (CurrInst->IsBasicBlockTerminator())
					return BADADDR;
				list<SMPInstr *>::iterator NextInstIter = InstIter;
				++NextInstIter;
				if (NextInstIter == this->Instrs.end())
					return BADADDR;
				sp_delta = get_spd(this->GetFuncInfo(), (*NextInstIter)->GetAddr());
				if (sp_delta == TargetSize) {
					// CurrInst will cause stack pointer delta to hit TargetSize.
					return addr;
				}
				else {
					return BADADDR;
				}
			} // end if LastInBlock
		} // end for all instructions
	} // end if (this->AnalyzedSP)
#if SMP_DEBUG_FRAMEFIXUP
	else {
		SMP_msg("AnalyzedSP is false for %s\n", this->GetFuncName());
	}
#endif
	return BADADDR;
} // end of SMPFunction::FindAllocPoint()

// IDA Pro is sometimes confused by a function that uses the frame pointer
//  register for other purposes. For the x86, a function that uses EBP
//  as a frame pointer would begin with: push ebp; mov ebp,esp to save
//  the old value of EBP and give it a new value as a frame pointer. The
//  allocation of local variable space would have to come AFTER the move
//  instruction. A function that begins: push ebp; push esi; sub esp,24
//  is obviously not using EBP as a frame pointer. IDA is apparently
//  confused by the push ebp instruction being the first instruction
//  in the function. We will reset UseFP to false in this case.
// The inverse problem happens with a function that begins with instructions
//  other than push ebp; mov ebp,esp; ... etc. but eventually has those
//  instructions in the first basic block. For example, a C compiler generates
//  for the first block of main():
//    lea ecx,[esp+arg0]
//    and esp, 0xfffffff0
//    push dword ptr [ecx-4]
//    push ebp
//    mov ebp,esp
//    push ecx
//    sub esp,<framesize>
//
//  This function is obviously using EBP as a frame pointer, but IDA Pro marks
//  the function as not using a frame pointer. We will reset UseFP to true in
//  this case.
// NOTE: This logic should work for both Linux and Windows x86 prologues.
bool SMPFunction::MDFixUseFP(void) {
	bool OldUseFP = this->UsesFramePointer();
	bool HasLocals = (0 < this->LocalVarsSize);
	list<SMPInstr *>::iterator InstIter = this->Instrs.begin();
	ea_t addr;

#if SMP_USE_SSA_FNOP_MARKER
	++InstIter;  // skip marker instruction
#endif
	SMPInstr *CurrInst;

#if 0
	if (!(this->UseFP)) {
#endif
		// See if we can detect the instruction "push ebp" followed by the instruction
		//  "mov ebp,esp" in the first basic block. The instructions do not have to be
		//  consecutive. If we find them, we will reset UseFP to true.
		bool FirstBlockProcessed = false;
		bool EBPSaved = false;
		bool ESPintoEBP = false;
		do {
			CurrInst = (*InstIter);
			addr = CurrInst->GetAddr();
			FirstBlockProcessed = CurrInst->IsLastInBlock();
			if (!EBPSaved) { // still looking for "push ebp"
				if (CurrInst->MDIsPushInstr() && CurrInst->GetCmd().Operands[0].is_reg(MD_FRAME_POINTER_REG)) {
					EBPSaved = true;
				}
			}
			else if (!ESPintoEBP) { // found "push ebp", looking for "mov ebp,esp"
				insn_t CurrCmd = CurrInst->GetCmd();
				if ((CurrCmd.itype == NN_mov) 
					&& (CurrInst->GetFirstDef()->GetOp().is_reg(MD_FRAME_POINTER_REG))
					&& (CurrInst->GetFirstUse()->GetOp().is_reg(MD_STACK_POINTER_REG))) {
					ESPintoEBP = true;
					FirstBlockProcessed = true; // exit loop
				}
			}
			// We must get EBP set to its frame pointer value before we reach the
			//  local frame allocation instruction (i.e. the subtraction of locals space
			//   from the stack pointer).
			if (HasLocals) {
				FirstBlockProcessed |= (addr >= this->LocalVarsAllocInstr);
			}
			++InstIter;
		} while (!FirstBlockProcessed);
		// If we found ESPintoEBP, we also found EBPSaved first, and we need to change
		//  this->UseFP to true and return true. Otherwise, return false.
		this->UseFP = ESPintoEBP;
		bool changed = (ESPintoEBP != OldUseFP);
		if (changed)
			SMP_msg("INFO: MDFixUseFP toggled UseFP for %s\n", this->GetFuncName());
		return (changed);
#if 0
	} // end if (!(this->UseFP))

	// At this point, this->UseFP must have been true on entry to this method and we will
	//  check whether it should be reset to false.
	while (addr <= this->LocalVarsAllocInstr) {
		set<DefOrUse, LessDefUse>::iterator CurrDef = CurrInst->GetFirstDef();
		while (CurrDef != CurrInst->GetLastDef()) {
			if (CurrDef->GetOp().is_reg(MD_FRAME_POINTER_REG))
				return false; // EBP got set before locals were allocated
			++CurrDef;
		}
		++InstIter;
		CurrInst = (*InstIter);
		addr = CurrInst->GetAddr();
	}
	// If we found no defs of the frame pointer before the local vars
	//  allocation, then the frame pointer register is not being used
	//  as a frame pointer, just as a general callee-saved register.
	this->UseFP = false;
	SMP_msg("INFO: MDFixUseFP reset UseFP to false for %s\n", this->GetFuncName());
	return true;
#endif
} // end of SMPFunction::MDFixUseFP()

// Find the callee-saved reg offsets (negative offset from return address)
//  for all registers pushed onto the stack before the stack frame allocation
//  instruction.
void SMPFunction::MDFindSavedRegs(void) {
	list<SMPInstr *>::iterator InstIter;
	int RegIndex;
	func_t *CurrFunc = SMP_get_func(this->GetStartAddr());
	assert(NULL != CurrFunc);

	for (InstIter = this->Instrs.begin(); InstIter != this->Instrs.end(); ++InstIter) {
		SMPInstr *CurrInst = (*InstIter);
		if (CurrInst->GetAddr() > this->LocalVarsAllocInstr)
			break;
		if (!(CurrInst->MDIsPushInstr()))
			continue;

		sval_t CurrOffset = get_spd(CurrFunc, CurrInst->GetAddr());
		if (CurrInst->GetCmd().itype == NN_push) {
			op_t PushedReg = CurrInst->GetPushedOpnd();
			if (o_reg == PushedReg.type) {
				RegIndex = (int) PushedReg.reg;
				if (RegIndex > R_di) {
					SMP_msg("WARNING: Skipping save of register %d\n", RegIndex);
					continue;
				}
				if (this->SavedRegLoc.at((size_t) RegIndex) == 0) {
					this->SavedRegLoc[(size_t) RegIndex] = CurrOffset - 4;
				}
				else {
					SMP_msg("WARNING: Multiple saves of register %d\n", RegIndex);
				}
			} // end if register push operand
		} // end if PUSH instruction
		else if (NN_pusha == CurrInst->GetCmd().itype) {
			// **!!** Handle pushes of all regs.
			this->SavedRegLoc[(size_t) R_ax] = CurrOffset - 4;
			this->SavedRegLoc[(size_t) R_cx] = CurrOffset - 8;
			this->SavedRegLoc[(size_t) R_dx] = CurrOffset - 12;
			this->SavedRegLoc[(size_t) R_bx] = CurrOffset - 16;
			this->SavedRegLoc[(size_t) R_sp] = CurrOffset - 20;
			this->SavedRegLoc[(size_t) R_bp] = CurrOffset - 24;
			this->SavedRegLoc[(size_t) R_si] = CurrOffset - 28;
			this->SavedRegLoc[(size_t) R_di] = CurrOffset - 32;
			break; // all regs accounted for
		}
		else if (CurrInst->MDIsEnterInstr()) {
			this->SavedRegLoc[(size_t) R_bp] = CurrOffset - 4;
		}
	} // end for all instructions

	return;
} // end of SMPFunction::MDFindSavedRegs()

// Compute the ReturnRegTypes[] as the meet over all register types
//  at all return instructions.
void SMPFunction::MDFindReturnTypes(void) {
	list<SMPBasicBlock *>::iterator BlockIter;
	SMPBasicBlock *CurrBlock;
	vector<SMPInstr *>::iterator InstIter;
	vector<SMPOperandType> RegTypes;
	SMPInstr *CurrInst;

	for (BlockIter = this->Blocks.begin(); BlockIter != this->Blocks.end(); ++BlockIter) {
		CurrBlock = (*BlockIter);
		if (CurrBlock->HasReturn()) {
			// Get the types of all registers at the RETURN point.
			//  Calculate the meet function over them.
			InstIter = CurrBlock->GetLastInst();
			--InstIter;
			CurrInst = (*InstIter);
			assert(RETURN == CurrInst->GetDataFlowType());
			set<DefOrUse, LessDefUse>::iterator CurrUse;
			for (CurrUse = CurrInst->GetFirstUse();
				CurrUse != CurrInst->GetLastUse();
				++CurrUse) {

				op_t UseOp = CurrUse->GetOp();
				if ((o_reg != UseOp.type) || (R_di < UseOp.reg))
					continue;
				this->ReturnRegTypes[UseOp.reg]
					= SMPTypeMeet(this->ReturnRegTypes.at(UseOp.reg),
						CurrUse->GetType());
			} // for all USEs in the RETURN instruction
		} // end if current block has a RETURN
	} // end for all blocks
	return;
} // end of SMPFunction::MDFindReturnTypes()

// Determine local variable boundaries in the stack frame.
void SMPFunction::BuildLocalVarTable(void) {
	// Currently we just use the info that IDA Pro has inferred from the direct
	//  addressing of stack locations.
	this->SemiNaiveLocalVarID();
	return;
} // end of SMPFunction::BuildLocalVarTable()

// Limit damage from garbage stack offset values produced by IDA Pro.
#define IDAPRO_KLUDGE_STACK_FRAME_SIZE_LIMIT 5000000

// Use the local variable offset list from IDA's stack frame structure to compute
//  the table of local variable boundaries.
void SMPFunction::SemiNaiveLocalVarID(void) {
	// NOTE: We use IDA Pro's offsets from this->FuncInfo (e.g. frsize) and NOT
	//  our own corrected values in our private data members. The offsets we
	//  read from the stack frame structure returned by get_frame() are consistent
	//  with other IDA Pro values, not with our corrected values.
	list<SMPInstr *>::iterator InstIter;
	bool DebugFlag = false;
	bool FoundReturnAddress = false;
	this->LocalVarOffsetLimit = -20000;
#if SMP_DEBUG_STACK_GRANULARITY
	DebugFlag |= (0 == strcmp("qSort3", this->GetFuncName()));
#endif
	func_t *FuncPtr = SMP_get_func(this->FuncInfo.startEA);
	if (NULL == FuncPtr) {
		SMP_msg("ERROR in SMPFunction::SemiNaiveLocalVarID; no func ptr\n");
	}
	assert(NULL != FuncPtr);
	struc_t *StackFrame = get_frame(FuncPtr);

	if (NULL == StackFrame) {
		SMP_msg("WARNING: No stack frame info from get_frame for %s\n", this->GetFuncName());
		return;
	}

	member_t *Member = StackFrame->members;
	for (size_t i = 0; i < StackFrame->memqty; ++i, ++Member) {
		long offset;
		char MemberName[MAXSMPVARSTR] = {'\0'};
		if (NULL == Member) {
			SMP_msg("NULL stack frame member pointer in %s\n", this->GetFuncName());
			break;
		}
		get_member_name(Member->id, MemberName, MAXSMPVARSTR - 1);
		if (MemberName == NULL) {
#if SMP_DEBUG_STACK_GRANULARITY
			SMP_msg("NULL stack frame member in %s\n", this->GetFuncName());
#endif
			continue;
		}
		if (Member->unimem()) {
			// Not a separate variable; name for member of a union.
			// The union itself should have a separate entry, so we skip this.
			SMP_msg("STACK INFO: Skipping union member %s frame member %zu in stack frame for %s\n",
				MemberName, i, this->GetFuncName());
			continue;
		}
		offset = (long) Member->get_soff(); // Would be 0 for union member, so we skipped them above.
		if (DebugFlag) {
			SMP_msg("%s local var %s at offset %ld\n", this->GetFuncName(), MemberName, offset);
		}
		if (offset > IDAPRO_KLUDGE_STACK_FRAME_SIZE_LIMIT) {
			SMP_msg("ERROR: Rejected enormous stack offset %ld for var %s in func %s\n", offset, MemberName, this->GetFuncName());
			continue;
		}
		if (!FoundReturnAddress && (2 == strlen(MemberName)) && (0 == strncmp(" r", MemberName, 2))) {
			FoundReturnAddress = true;
			this->IDAReturnAddressOffset = offset;
		}
		struct LocalVar TempLocal;
		TempLocal.offset = offset;
		TempLocal.size = Member->eoff - Member->soff; // audit later
		SMP_strncpy(TempLocal.VarName, MemberName, sizeof(TempLocal.VarName) - 1);
		this->LocalVarTable.push_back(TempLocal);
		if ((offset + (long) TempLocal.size) >= this->LocalVarOffsetLimit) {
			this->LocalVarOffsetLimit = (long) (TempLocal.offset + TempLocal.size);
		}
	} // end for all stack frame members

	// If AnalyzedSP is false, that is all we can do.
	if (!this->AnalyzedSP) {
		this->OutgoingArgsSize = 0;
		this->MinStackDelta = 0;
		this->AllocPointDelta = 0;
		return;
	}

	// Calculate min and max stack point deltas.
	this->MinStackDelta = 20000; // Final value should be negative or zero
	this->MaxStackDelta = -1000; // Final value should be zero.
	InstIter = this->Instrs.begin();
#if SMP_USE_SSA_FNOP_MARKER
	if ((*InstIter)->IsFloatNop())
		++InstIter;  // skip marker instruction
#endif
	for ( ; InstIter != this->Instrs.end(); ++InstIter) {
		SMPInstr *CurrInst = (*InstIter);
		ea_t addr = CurrInst->GetAddr();
		sval_t sp_delta = CurrInst->GetStackPtrOffset();
		if (sp_delta < this->MinStackDelta)
			this->MinStackDelta = sp_delta;
		if (sp_delta > this->MaxStackDelta)
			this->MaxStackDelta = sp_delta;
		if (addr == this->LocalVarsAllocInstr) {
			// Total stack pointer delta is sp_delta for the next instruction,
			//  because IDA updates the sp delta AFTER each instruction.
			list<SMPInstr *>::iterator NextInstIter = InstIter;
			++NextInstIter;
			if (NextInstIter != this->Instrs.end()) {
				sp_delta = (*NextInstIter)->GetStackPtrOffset();
				this->AllocPointDelta = sp_delta;
			}
		}
	}

	// Calculate min and max stack operand offsets accessed.
	InstIter = this->Instrs.begin();
#if SMP_USE_SSA_FNOP_MARKER
	if ((*InstIter)->IsFloatNop())
		++InstIter;  // skip marker instruction
#endif
	for ( ; InstIter != this->Instrs.end(); ++InstIter) {
		SMPInstr *CurrInst = (*InstIter);
		ea_t addr = CurrInst->GetAddr();
		// Find the min and max stack offsets in DEFs and USEs.
		op_t TempOp;
		if (CurrInst->HasDestMemoryOperand() || CurrInst->MDIsPushInstr() || CurrInst->MDIsEnterInstr()) {
			set<DefOrUse, LessDefUse>::iterator CurrDef;
			for (CurrDef = CurrInst->GetFirstDef(); CurrDef != CurrInst->GetLastDef(); ++CurrDef) {
				TempOp = CurrDef->GetOp();
				if (TempOp.type != o_phrase && TempOp.type != o_displ)
					continue;
				this->UpdateMinMaxStackOffsets(CurrInst, TempOp);
			} // end for all DEFs
		}
		if (CurrInst->HasSourceMemoryOperand() || CurrInst->MDIsPopInstr() || CurrInst->MDIsLeaveInstr() || CurrInst->MDIsLoadEffectiveAddressInstr()) {
			if (CurrInst->MDIsLoadEffectiveAddressInstr()) {
				TempOp = CurrInst->GetLeaMemUseOp();
				if (((TempOp.type == o_phrase) || (TempOp.type == o_displ)) && (!(CurrInst->IsRegClearIdiom() || CurrInst->IsNop())))  {
					this->UpdateMinMaxStackOffsets(CurrInst, TempOp);
				}
			}
			else {
				set<DefOrUse, LessDefUse>::iterator CurrUse;
				for (CurrUse = CurrInst->GetFirstUse(); CurrUse != CurrInst->GetLastUse(); ++CurrUse) {
					TempOp = CurrUse->GetOp();
					if ((TempOp.type != o_phrase) && (TempOp.type != o_displ))
						continue;
					this->UpdateMinMaxStackOffsets(CurrInst, TempOp);
				} // end for all USEs
			}
		}
	}
	if (0 == this->MaxStackAccessLimit) {
		// Never accessed any incoming args. However, we know the return address is on the stack,
		//  and it is almost never accessed, so we want to record its presence.
		this->MaxStackAccessLimit = MD_DEFAULT_RETURN_ADDRESS_SIZE;
	}
	if (this->MinStackAccessOffset > this->MinStackDelta) {
		// Some functions allocate space that is not visibly accessed. We still want to make
		//  our stack frame maps of maximum size, and MinStackDelta is used for normalizing offsets.
		this->MinStackAccessOffset = this->MinStackDelta;
	}
	else if (this->MinStackAccessOffset < this->MinStackDelta) {
		// x86-64 leaf functions are often optimized by not allocating a stack frame. Instead,
		//  negative displacements from the stack pointer are used to access locals. So the
		//  stack pointer (reflected in MinStackDelta) never goes down as far as the bottom of
		//  the frame (reflected by MinStackAccessOffset). We need to record that such a function
		//  has been detected so that we don't fail assertions unnecessarily later.
		this->SetStackFrameExtendsPastStackTop();
	}

	// IDA Pro sometimes fails to add stack frame members for all incoming args, etc.
	//  Find and correct these omissions by examining stack accesses in instructions
	//  and extend the LocalVarTable to cover whatever is out of range.
	if (!this->AuditLocalVarTable()) {
		// Catastrophic error must have occurred, probably due to errors in IDA's
		//  stack pointer analysis, despite AnalyzedSP being true.
		return;
	}

	if (!(this->LocalVarTable.empty())) {
		this->GoodLocalVarTable = true;

		// Sort the LocalVarTable so that we do not depend on IDA Pro
		//  presenting the stack frame members in order.
		std::sort(this->LocalVarTable.begin(), this->LocalVarTable.end(), LocalVarCompare);
	}

#if SMP_DEBUG_STACK_GRANULARITY
	SMP_msg("Computing %d local var sizes\n", this->LocalVarTable.size());
#endif
	// Now we want to audit the size field for each local
	if (this->GoodLocalVarTable) {
		size_t VarLimit = this->LocalVarTable.size() - 1;
		assert(this->LocalVarTable.size() > 0);
		for (size_t VarIndex = 0; VarIndex < VarLimit; ++VarIndex) {
			struct LocalVar TempLocEntry = this->LocalVarTable[VarIndex];
			bool AboveLocalsRegion = (TempLocEntry.offset >= this->LocalVarsSize);
			size_t TempSize = this->LocalVarTable[VarIndex + 1].offset - TempLocEntry.offset;
			int DiffSize = ((int) TempSize) - ((int) TempLocEntry.size);
			// We don't have IDA Pro stack frame members for callee saved registers. This
			//  omission can make it seem that there is a gap between the uppermost local
			//  variable and the return address or saved frame pointer. Avoid expanding the
			//  last local variable into the callee saved registers region.
			if (DiffSize > 0) { // We are expanding the size.
				if (!AboveLocalsRegion && ((TempLocEntry.offset + TempLocEntry.size + DiffSize) > this->LocalVarsSize)) {
					// Current local does not start above the locals region, but its new size will
					//  carry it above the locals region.
					if ((TempLocEntry.offset + TempLocEntry.size) > this->LocalVarsSize) {
						// Weird. It already overlapped the callee saved regs region.
						SMP_msg("WARNING: Local var at offset %ld size %zu in %s extends above local vars region.\n",
							TempLocEntry.offset, TempLocEntry.size, this->GetFuncName());
					}
					// Limit DiffSize to avoid overlapping callee saved regs.
					DiffSize = this->LocalVarsSize - (TempLocEntry.offset + TempLocEntry.size);
					if (DiffSize < 0)
						DiffSize = 0; // started out positive, cap it at zero.
				}
			}
			if (DiffSize < 0)
				DiffSize = 0; // should not happen with sorted LocalVarTable unless duplicate entries.
			if (DiffSize != 0)  {
#if SMP_DEBUG_STACK_GRANULARITY
				SMP_msg("STACK INFO: Adjusted size for stack frame member at %ld in %s\n",
					TempLocEntry.offset, this->GetFuncName());
#endif
				this->LocalVarTable[VarIndex].size += DiffSize;
			}
		}
#if 0 // Using Member->eoff seems to be working for all members, including the last one.
#if SMP_DEBUG_STACK_GRANULARITY
		SMP_msg("Computing last local var size for frsize %d\n", this->FuncInfo.frsize);
#endif
		// Size of last local is total frsize minus savedregs in frame minus offset of last local
		size_t SavedRegsSpace = 0; // portion of frsize that is saved regs, not locals.
		if (this->CalleeSavedRegsSize > this->FuncInfo.frregs) {
			// IDA Pro counts the save of EBP in frregs, but then EBP gets its new
			//  value and callee saved regs other than the old EBP push get counted
			//  in frsize rather than frregs. CalleeSavedRegsSize includes all saved
			//  regs on the stack, both above and below the current EBP offset.
			// NOTE: For windows, this has to be done differently, as callee saved regs
			//  happen at the bottom of the local frame, not the top.
#if 0
			SavedRegsSpace = this->CalleeSavedRegsSize - this->FuncInfo.frregs;
#else
			SavedRegsSpace = this->FuncInfo.frsize - this->LocalVarsSize;
#endif
		}

		this->LocalVarTable.back().size = this->FuncInfo.frsize
			- SavedRegsSpace - this->LocalVarTable.back().offset;
		this->LocalVarOffsetLimit = this->LocalVarTable.back().offset 
			+ (adiff_t) this->LocalVarTable.back().size;
#endif
	}

#if 0 // AboveLocalsSize is not a reliable number.
	// IDA Pro can have difficulty with some irregular functions such as are found
	//  in the C startup code. The frsize value might be bogus. Just punt on the
	//  local variable ID if that is the case.
	if ((this->LocalVarOffsetLimit - AboveLocalsSize) > (adiff_t) this->FuncInfo.frsize) {
		this->LocalVarTable.clear();
		this->GoodLocalVarTable = false;
		SMP_msg("WARNING: Bad frsize %d for %s OffsetLimit: %d AboveLocalsSize: %d LocalVarsSize: %d ; abandoning SemiNaiveLocalVarID.\n",
			this->FuncInfo.frsize, this->GetFuncName(), this->LocalVarOffsetLimit, AboveLocalsSize, this->LocalVarsSize);
		return;
	}
	assert((this->LocalVarOffsetLimit - AboveLocalsSize) <= (adiff_t) this->FuncInfo.frsize);
#endif

	// Find out how many of the locals are really outgoing args.
	if (this->AnalyzedSP && !this->CallsAlloca && (BADADDR != this->LocalVarsAllocInstr)) {
		this->FindOutgoingArgsSize();
	}
	else {
		SMP_msg("FindOutgoingArgsSize not called for %s ", this->GetFuncName());
		SMP_msg("AnalyzedSP: %d CallsAlloca: %d LocalVarsAllocInstr: %lx \n",
			this->AnalyzedSP, this->CallsAlloca, (unsigned long) this->LocalVarsAllocInstr);
	}
	return;
} // end of SMPFunction::SemiNaiveLocalVarID()

// Update MinStackAccessOffset and MaxStackAccessLimit if TempOp is stack access
void SMPFunction::UpdateMinMaxStackOffsets(SMPInstr *CurrInst, op_t TempOp) {
	ea_t offset;
	size_t DataSize;
	bool UsedFramePointer;
	bool IndexedAccess;
	bool SignedMove;
	bool UnsignedMove;

	if (this->MDGetStackOffsetAndSize(CurrInst, TempOp, this->MinStackDelta, offset, DataSize, UsedFramePointer,
		IndexedAccess, SignedMove, UnsignedMove)) {
		int SignedOffset = (int) offset + (int) this->MinStackDelta; // Don't want zero-based for min/max finding
		if (((sval_t) SignedOffset) < this->MinStackAccessOffset) {
			this->MinStackAccessOffset = (sval_t) SignedOffset;
		}
		if (((sval_t)(SignedOffset + (int) DataSize)) > this->MaxStackAccessLimit) {
			this->MaxStackAccessLimit = (sval_t)(SignedOffset + (int) DataSize);
		}
	}
	return;
} // end of SMPFunction::UpdateMinMaxStackOffsets()

// Check and correct the LocalVarTable derived from IDA Pro stack frame members.
//  Examine each instruction and see if any stack accesses are beyond the LocalVarTable
//  and create new entries in the LocalVarTable if so.
bool SMPFunction::AuditLocalVarTable(void) {
	list<SMPInstr *>::iterator InstIter;

	// For some functions, IDA Pro does not base its stack frame at the MinStackDelta. This
	//  is detected by noting that the offset field for the saved return address is not
	//  the negation of the MinStackDelta, e.g. offset is 12 and MinStackDelta is -16
	//  for a function such as call_gmon_start, which has a temporary 4-byte decrease
	//  in the stack delta for an internal thunk call that IDA Pro excludes from the
	//  stack frame analysis, because it does not represent any local variable:
	//     call next_instruction
	//     pop ebx
	// Instead, IDA Pro typically bases its stack frame at the AllocPointDelta. For many
	//  functions, the MinStackDelta and the AllocPointDelta are the same. For some, they
	//  are not the same, and for some functions, IDA Pro has a stack frame that is not
	//  even based at the AllocPointDelta, because IDA Pro makes a mistake in its analyses
	//  when the first basic block is interrupted by odd code such as a function call
	//  before it reaches the frame allocation instruction.
	// So, we need to align the local var table so that the base of the table is at the
	//  AllocPointDelta and the saved return address falls at normalized address zero, i.e.
	//  if AllocPointDelta is -28, then the LocalVarTable will start at offset zero as IDA
	//  computes offsets, and the saved return address will fall at offset 28, the negation
	//  of the AllocPointDelta. If the LocalVarTable does not conform to this pattern, we will
	//  need to add 4-byte entries at the bottom of the table and adjust offsets until the return address
	//  falls at the correct offset.
	long IDAFrameAdjustment = (0 - this->IDAReturnAddressOffset - this->AllocPointDelta);
	if (IDAFrameAdjustment != 0) {
		SMP_msg("WARNING: %ld bytes IDAFrameAdjustment needed: Func at: %lx RetAddrOffset: %ld AllocPointDelta: %lld\n",
			IDAFrameAdjustment, (unsigned long) this->FirstEA, this->IDAReturnAddressOffset, (int64) this->AllocPointDelta);
		// We need to subtract (IDAReturnAddressOffset + this->AllocPointDelta) from the local var table offsets.
		//  this->AllocPointDelta is negative, e.g. -44 for libc_csu_init in toy.exe, and IDAReturnAddressOffset
		//  should be its negation (44 in that example), but is a smaller number (20 in the toy.exe example),
		//  so we are subtracting (20 + -44) from each offset, meaning we are adding 24. We also add 24 to the 
		//  value of this->LocalVarOffsetLimit, and create an entry at the bottom of the frame with a size of
		//  24 in this example.
		long LocalVarIncrement = (0 - (this->IDAReturnAddressOffset + this->AllocPointDelta));
		if (LocalVarIncrement <= 0) {
			SMP_msg("SERIOUS WARNING: Unexpected non-positive value for LocalVarIncrement: %ld Func at: %lx\n",
				LocalVarIncrement, (unsigned long) this->FirstEA);
		}
		else {
			for (size_t i = 0; i < this->LocalVarTable.size(); ++i) {
				this->LocalVarTable[i].offset += LocalVarIncrement;
			}
			// Add dummy placeholders at bottom of LocalVarTable, four bytes each.
			size_t TotalFillerSize = 0;
			do {
				struct LocalVar TempLocal;
				char TempStr[20];
				TempLocal.offset = (long) TotalFillerSize;
				TempLocal.size = 4;
				if (((long)(TempLocal.size + TotalFillerSize)) > LocalVarIncrement) {
					TempLocal.size = (size_t)(LocalVarIncrement - (long) TotalFillerSize);
				}
				TotalFillerSize += TempLocal.size;
				SMP_strncpy(TempLocal.VarName, "SMP_IDA_FixVar", sizeof(TempLocal.VarName) - 1);
				(void) SMP_snprintf(TempStr, 18, "%ld", TempLocal.offset);
				SMP_strncat(TempLocal.VarName, TempStr, sizeof(TempLocal.VarName) - 1);
				this->LocalVarTable.push_back(TempLocal);
			} while (((long)TotalFillerSize) < LocalVarIncrement);
			this->LocalVarOffsetLimit += LocalVarIncrement;
			this->FuncInfo.frsize += (asize_t) LocalVarIncrement;
		}
	}

	// We cannot depend on IDA Pro making Member
	//  entries for everything that is accessed on the stack.
	//  When an incoming arg is accessed but no Member is
	//  created, then LocalVarOffsetLimit will be too small
	//  and we will get ERROR messages. We already looped through the
	//  instructions to find the MaxStackAccessLimit. If LocalVarOffsetLimit
	//  is not big enough to reach from AllocPointDelta to MaxStackAccessLimit,
	//  then add 4-byte incoming arg entries until it reaches.
	while (this->LocalVarOffsetLimit < (long) this->MaxStackAccessLimit) {
		// Extend LocalVarTable.
		struct LocalVar TempLocal;
		char TempStr[20];
		TempLocal.offset = this->LocalVarOffsetLimit;
		TempLocal.size = STARS_ISA_Bytewidth;
		if ((TempLocal.size + TempLocal.offset) > ((long) this->MaxStackAccessLimit)) {
			TempLocal.size = ((long) this->MaxStackAccessLimit) - TempLocal.offset;
		}
		SMP_strncpy(TempLocal.VarName, "SMP_InArg", sizeof(TempLocal.VarName) - 1);
		(void) SMP_snprintf(TempStr, 18, "%ld", TempLocal.offset);
		SMP_strncat(TempLocal.VarName, TempStr, sizeof(TempLocal.VarName) - 1);
		this->LocalVarTable.push_back(TempLocal);
		this->LocalVarOffsetLimit += TempLocal.size;
	}

	// Fill in the gaps with new variables as well. SHOULD WE? WHY?

	return true;
} // end of SMPFunction::AuditLocalVarTable()


// Determine how many bytes at the bottom of the stack frame (i.e. at bottom of
//  this->LocalVarsSize) are used for outgoing args. This is the case when the cdecl
//  calling convention is used, e.g. gcc/linux allocates local var space + out args space
//  in a single allocation and then writes outarg values directly to ESP+0, ESP+4, etc.
void SMPFunction::FindOutgoingArgsSize(void) {
	// Compute the lowest value reached by the stack pointer.
	list<SMPInstr *>::iterator InstIter;
	unsigned short BitWidthMask;
	bool DebugFlag = false;
	int SignedOffset;
#if SMP_DEBUG_STACK_GRANULARITY
	DebugFlag = (0 == strcmp("BZ2_blockSort", this->GetFuncName()));
#endif

	this->OutgoingArgsComputed = true;

	if (DebugFlag) {
		SMP_msg("DEBUG: Entered FindOutgoingArgsSize for %s\n", this->GetFuncName());
#if SMP_IDAPRO52_WORKAROUND
		this->OutgoingArgsSize = 16;
		return;
#endif
	}

#if SMP_DEBUG_STACK_GRANULARITY
	SMP_msg("AllocPointDelta: %d MinStackDelta: %d\n", this->AllocPointDelta, this->MinStackDelta);
#endif
	if ((0 <= this->MinStackDelta) || (0 <= this->AllocPointDelta)) {
		// No allocations; sometimes happens in library functions.
		this->OutgoingArgsSize = 0;
		this->AllocPointDelta = 0;
		if ((this->MinStackDelta > this->MaxStackDelta) || (0 < this->MinStackDelta)) {
			this->MinStackDelta = 0;
		}
	}
	assert(0 >= this->MinStackDelta);

	// Allocate a vector of stack frame entries, one for each byte of the stack frame.
	//  This will be our memory map for analyzing stack usage.
	for (int i = this->MinStackAccessOffset; i < this->MaxStackAccessLimit; ++i) {
		struct StackFrameEntry TempEntry;
		TempEntry.VarPtr = NULL;
		TempEntry.offset = (long) i;
		TempEntry.Read = false;
		TempEntry.Written = false;
		TempEntry.AddressTaken = false;
		TempEntry.ESPRelativeAccess = false;
		TempEntry.EBPRelativeAccess = false;
		TempEntry.IndexedAccess = false;
		this->StackFrameMap.push_back(TempEntry);
		struct FineGrainedInfo TempFineGrained;
		TempFineGrained.SignMiscInfo = 0;
		TempFineGrained.SizeInfo = 0;
		this->FineGrainedStackTable.push_back(TempFineGrained);
	}
#if 0
	for (int i = 0; i < this->LocalVarOffsetLimit; ++i) {
		struct FineGrainedInfo TempFineGrained;
		TempFineGrained.SignMiscInfo = 0;
		TempFineGrained.SizeInfo = 0;
		this->FineGrainedStackTable.push_back(TempFineGrained);
	}
#endif

	// Fill in the VarPtr fields for each StackFrameMap entry.
	if (0 < this->AllocPointDelta) {
		SMP_msg("FATAL ERROR: AllocPointDelta = %ld in %s\n", (long) this->AllocPointDelta, this->GetFuncName());
	}
	assert(0 >= this->AllocPointDelta);

	// We were not able to adjust the LocalVarTable for a negative IDAFrameAdjustment back
	//  in AuditLocalVarTable(), but we can use the negative adjustment value in this loop
	//  to properly match the StackFrameMap entries to the LocalVarTable entries and avoid
	//  an out of range error.
	long IDAFrameAdjustment = (0 - this->IDAReturnAddressOffset - this->AllocPointDelta);
	if (0 < IDAFrameAdjustment) {
		IDAFrameAdjustment = 0; // only handling the negative case; positive was handled in AuditLocalVarTable()
	}
	for (size_t i = 0; i < this->LocalVarTable.size(); ++i) {
		assert(this->LocalVarTable.at(i).offset >= 0);
		// Picture that AllocPointDelta is -200, MinStackAccessOffset is -210, and
		//  the LocalVarTable[i].offset is +8 (i.e. 8 bytes above alloc point).
		//  Then base = 8 + (-200 - -210) = 8 + 10 = 18, the proper offset into
		//  the StackFrameMap.
		size_t base = (size_t) (this->LocalVarTable.at(i).offset
			+ (this->AllocPointDelta - this->MinStackAccessOffset) + IDAFrameAdjustment);
		size_t limit = base + this->LocalVarTable.at(i).size;
		if (limit > this->StackFrameMap.size()) {
			SMP_msg("WARNING: FindOutArgsSize: Unaccessed IDA Pro local var or inarg %s base = %zu limit = %zu in %s\n",
				this->LocalVarTable.at(i).VarName, base, limit, this->GetFuncName());
		}
		else {
			assert(limit <= this->StackFrameMap.size());
			for (size_t MapIndex = base; MapIndex < limit; ++MapIndex) {
				this->StackFrameMap[MapIndex].VarPtr = &(this->LocalVarTable.at(i));
			}
		}
	}

	// Iterate through all instructions and record stack frame accesses in the StackFrameMap.
	InstIter = this->Instrs.begin();
#if SMP_USE_SSA_FNOP_MARKER
	if ((*InstIter)->IsFloatNop())
		++InstIter;  // skip marker instruction
#endif
	for ( ; InstIter != this->Instrs.end(); ++InstIter) {
		SMPInstr *CurrInst = (*InstIter);
		ea_t InstAddr = CurrInst->GetAddr();
		sval_t sp_delta = CurrInst->GetStackPtrOffset();
		if (0 < sp_delta) {
			// Stack underflow.
			SMP_msg("ERROR: Stack underflow at %lx %s sp_delta: %ld\n", (unsigned long) InstAddr,
				CurrInst->GetDisasm(), (long) sp_delta);
			this->OutgoingArgsComputed = false;
			this->OutgoingArgsSize = 0;
			return;
		}
		assert(0 >= sp_delta);
		ea_t offset;
		size_t DataSize;
		bool UsedFramePointer;
		bool IndexedAccess;
		bool SignedMove;
		bool UnsignedMove;
		if (CurrInst->HasDestMemoryOperand()) {
			set<DefOrUse, LessDefUse>::iterator CurrDef;
			for (CurrDef = CurrInst->GetFirstDef(); CurrDef != CurrInst->GetLastDef(); ++CurrDef) {
				op_t TempOp = CurrDef->GetOp();
				if (TempOp.type != o_phrase && TempOp.type != o_displ)
					continue;
				if (this->MDGetStackOffsetAndSize(CurrInst, TempOp, this->MinStackAccessOffset, offset, DataSize, UsedFramePointer,
					IndexedAccess, SignedMove, UnsignedMove)) {
					SignedOffset = (int) offset;
					if (IndexedAccess && ((0 > SignedOffset) || ((SignedOffset + DataSize) > this->StackFrameMap.size()))) {
						continue; // Indexed expressions can be within frame even when offset is outside frame
					}
					assert(0 <= SignedOffset);
#if 0
					if (offset >= this->FuncInfo.frsize)
						continue;  // limit processing to outgoing args and locals
#endif
					if ((offset + DataSize) > this->StackFrameMap.size()) {
						SMP_msg("ERROR: offset = %lu DataSize = %zu FrameMapSize = %zu\n",
							(unsigned long) offset, DataSize, this->StackFrameMap.size());
						continue;
					}
					assert((offset + DataSize) <= this->StackFrameMap.size());
					bool ESPRelative = (!(UsedFramePointer || CurrInst->HasFPNormalizedToSP()));
					for (int j = 0; j < (int) DataSize; ++j) {
						this->StackFrameMap[offset + j].Written = true;
						this->StackFrameMap[offset + j].IndexedAccess = IndexedAccess;
						if (ESPRelative) {
							this->StackFrameMap[offset + j].ESPRelativeAccess = true;
						}
						else {
							this->StackFrameMap[offset + j].EBPRelativeAccess = true;
						}
					}
					struct FineGrainedInfo StackDefFG;
					BitWidthMask = ComputeOperandBitWidthMask(TempOp, DataSize);
					this->FineGrainedStackTable.at(offset).SizeInfo |= BitWidthMask;
					StackDefFG.SizeInfo = BitWidthMask;
					this->FineGrainedStackTable.at(offset).SignMiscInfo |= FG_MASK_WRITTEN;
					StackDefFG.SignMiscInfo = FG_MASK_WRITTEN;
					if (IndexedAccess) {
						this->FineGrainedStackTable.at(offset).SignMiscInfo |= FG_MASK_INDEXED_ACCESS;
						StackDefFG.SignMiscInfo |= FG_MASK_INDEXED_ACCESS;
					}
					if (ESPRelative) {
						this->FineGrainedStackTable.at(offset).SignMiscInfo |= FG_MASK_SP_RELATIVE;
						StackDefFG.SignMiscInfo |= FG_MASK_SP_RELATIVE;
					}
					else {
						this->FineGrainedStackTable.at(offset).SignMiscInfo |= FG_MASK_FP_RELATIVE;
						StackDefFG.SignMiscInfo |= FG_MASK_FP_RELATIVE;
					}
					// We will process the signedness of stores later, so that loads can take precedence
					//  over stores in determining signedness in the table. We go ahead and process
					//  signedness for the separate DEF and USE maps by InstAddr.
					if (SignedMove) {
						StackDefFG.SignMiscInfo |= FG_MASK_SIGNED;
					}
					else if (UnsignedMove) {
						StackDefFG.SignMiscInfo |= FG_MASK_UNSIGNED;
					}
					// Insert the StackDefFG into the map of InstAddr to DEF FG info.
					pair<map<ea_t, struct FineGrainedInfo>::iterator, bool> InsertResult;
					pair<ea_t, struct FineGrainedInfo> InsertValue(InstAddr, StackDefFG);
					InsertResult = this->StackDefFGInfo.insert(InsertValue);
					assert(InsertResult.second);
				} // end if MDGetStackOffsetAndSize()
			} // end for all DEFs
		} // end if DestMemoryOperand

		if (CurrInst->HasSourceMemoryOperand()) {
			set<DefOrUse, LessDefUse>::iterator CurrUse;
			for (CurrUse = CurrInst->GetFirstUse(); CurrUse != CurrInst->GetLastUse(); ++CurrUse) {
				op_t TempOp = CurrUse->GetOp();
				if (TempOp.type != o_phrase && TempOp.type != o_displ)
					continue;
				if (this->MDGetStackOffsetAndSize(CurrInst, TempOp, this->MinStackAccessOffset, offset, DataSize, UsedFramePointer,
					IndexedAccess, SignedMove, UnsignedMove)) {
					SignedOffset = (int) offset;
					if (IndexedAccess && ((0 > SignedOffset) || ((SignedOffset + DataSize) > this->StackFrameMap.size()))) {
						continue; // Indexed expressions can be within frame but offset is outside frame
					}
					assert(0 <= SignedOffset);
#if 0
					if (offset >= this->FuncInfo.frsize)
						continue;  // limit processing to outgoing args and locals
#endif
					if ((SignedOffset + DataSize) > this->StackFrameMap.size()) {
						SMP_msg("ERROR: offset = %lu DataSize = %zu FrameMapSize = %zu\n",
							(unsigned long) offset, DataSize, this->StackFrameMap.size());
						continue;
					}
					assert((SignedOffset + DataSize) <= this->StackFrameMap.size());
					bool ESPRelative = (!(UsedFramePointer || CurrInst->HasFPNormalizedToSP()));
					for (int j = 0; j < (int) DataSize; ++j) {
						this->StackFrameMap[offset + j].Read = true;
						this->StackFrameMap[offset + j].IndexedAccess |= IndexedAccess;
						if (ESPRelative)
							this->StackFrameMap[offset + j].ESPRelativeAccess = true;
						else
							this->StackFrameMap[offset + j].EBPRelativeAccess = true;
					}
					struct FineGrainedInfo StackUseFG;
					BitWidthMask = ComputeOperandBitWidthMask(TempOp, DataSize);
					this->FineGrainedStackTable.at(offset).SizeInfo |= BitWidthMask;
					StackUseFG.SizeInfo = BitWidthMask;
					this->FineGrainedStackTable.at(offset).SignMiscInfo |= FG_MASK_READ;
					StackUseFG.SignMiscInfo = FG_MASK_READ;
					if (IndexedAccess) {
						this->FineGrainedStackTable.at(offset).SignMiscInfo |= FG_MASK_INDEXED_ACCESS;
						StackUseFG.SignMiscInfo |= FG_MASK_INDEXED_ACCESS;
					}
					if (ESPRelative) {
						this->FineGrainedStackTable.at(offset).SignMiscInfo |= FG_MASK_SP_RELATIVE;
						StackUseFG.SignMiscInfo |= FG_MASK_SP_RELATIVE;
					}
					else {
						this->FineGrainedStackTable.at(offset).SignMiscInfo |= FG_MASK_FP_RELATIVE;
						StackUseFG.SignMiscInfo |= FG_MASK_FP_RELATIVE;
					}
					if (SignedMove) {
						this->FineGrainedStackTable.at(offset).SignMiscInfo |= FG_MASK_SIGNED;
						StackUseFG.SignMiscInfo |= FG_MASK_SIGNED;
					}
					else if (UnsignedMove) {
						this->FineGrainedStackTable.at(offset).SignMiscInfo |= FG_MASK_UNSIGNED;
						StackUseFG.SignMiscInfo |= FG_MASK_UNSIGNED;
					}
					// Insert the StackUseFG into the map of InstAddr to USE FG info.
					pair<map<ea_t, struct FineGrainedInfo>::iterator, bool> InsertResult;
					pair<ea_t, struct FineGrainedInfo> InsertValue(InstAddr, StackUseFG);
					InsertResult = this->StackUseFGInfo.insert(InsertValue);
					assert(InsertResult.second);
				} // end if MDGetStackOffsetAndSize()
			} // end for all USEs
		} // end if SourceMemoryOperand
		// NOTE: Detect taking the address of stack locations. **!!**
	} // end for all instructions

	// If function is a leaf function, set OutgoingArgsSize to zero and return.
	// If function has no local frame allocation, ditto.
	if ((this->IsLeaf() && !(this->IsDirectlyRecursive()))
		|| (this->AllocPointDelta == 0)) {
		this->OutgoingArgsSize = 0;
		return;
	}

	// For non-leaf functions, set the OutgoingArgsSize to the write-only, ESP-relative
	//  region of the bottom of the StackFrameMap.
	bool OutgoingArgsRegionFinished = false;
	bool IndexedOutgoingArgs = false; // Any indexed accesses to outgoing args?
	size_t FramePadSize = 0;
	size_t AlignmentPadSize = 0; // bottom of frame, unused space below outargs
	for (size_t MapIndex = 0; MapIndex < this->StackFrameMap.size(); ++MapIndex) {
		// Some of the bottom of the stack frame might be below the local frame allocation.
		//  These are pushes that happened after allocation, etc. We skip over these
		//  locations and define the outgoing args region to start strictly at the bottom
		//  of the local frame allocation.
		struct StackFrameEntry TempEntry = this->StackFrameMap.at(MapIndex);
		if (DebugFlag) {
			SMP_msg("StackFrameMap entry %zu: offset: %ld Read: %d Written: %d ESP: %d EBP: %d\n",
				MapIndex, TempEntry.offset, TempEntry.Read, TempEntry.Written,
				TempEntry.ESPRelativeAccess, TempEntry.EBPRelativeAccess);
		}
		if (TempEntry.offset < this->AllocPointDelta)
			continue;
		if ((0 != TempEntry.VarPtr) && ((0 == strcmp(" s", TempEntry.VarPtr->VarName)) || (0 == strcmp(" r", TempEntry.VarPtr->VarName)))) {
			// We have reached saved regs or the return address.
			break;
		}

		if (OutgoingArgsRegionFinished) {
			// We are just processing the stack frame padding.
			if (!TempEntry.Read && !TempEntry.Written) {
				// Could be stack frame padding.
				++FramePadSize;
			}
			else {
				break; // No more padding region
			}
		}
		else if ((this->OutgoingArgsSize == 0) && (!TempEntry.Read) && (!TempEntry.Written)) {
			// We have not started accumulating outgoing args bytes, we have reached the
			//  AllocPointDelta, yet we find space that is neither written nor read. This
			//  empty space at the bottom of the stack frame could just be for stack alignment
			//  purposes, especially in the new x86-64 ABI, so it should not prevent us from
			//  finding outgoing args space above it.
			++AlignmentPadSize;
		}
		else if (TempEntry.Read || TempEntry.EBPRelativeAccess || !TempEntry.Written
			|| !TempEntry.ESPRelativeAccess) {
			OutgoingArgsRegionFinished = true;
			if (!TempEntry.Read && !TempEntry.Written) {
				// Could be stack frame padding.
				++FramePadSize;
			}
			else {
				break; // No padding region
			}
		}
		else {
			this->OutgoingArgsSize++;
			if (TempEntry.IndexedAccess) {
				IndexedOutgoingArgs = true;
			}
		}
	}

	// Add in the alignment padding below the written outargs region.
	if (this->OutgoingArgsSize > 0) {
		this->OutgoingArgsSize += AlignmentPadSize;
	}

	// If any outgoing arg was accessed using an index register, then we don't know how high
	//  the index register value went. It could potentially consume the so-called padding
	//  region, which might be just the region we did not detect direct accesses to because
	//  the accesses were indirect. To be safe, we expand the outgoing args region to fill
	//  the padding region above it in this indexed access case.
	if (IndexedOutgoingArgs) {
		this->OutgoingArgsSize += FramePadSize;
	}

#if 0
	// Sometimes we encounter unused stack space above the outgoing args. Lump this space
	//  in with the outgoing args. We detect this by noting when the outgoing args space
	//  has only partially used the space assigned to a local var.
	// NOTE: This is usually just stack padding to maintain stack alignment. It could
	//  also be the case that the lowest local variable is accessed indirectly and we missed
	//  seeing its address taken, in which case it would be unsound to lump it into the
	//  outgoing args region. We might want to create a local var called STACKPAD
	//  to occupy this space.
	if ((0 < this->OutgoingArgsSize) && (this->OutgoingArgsSize < this->FuncInfo.frsize)) {
		long MapIndex = (this->AllocPointDelta - this->MinStackDelta);
		assert(0 <= MapIndex);
		MapIndex += (((long) this->OutgoingArgsSize) - 1);
		struct StackFrameEntry TempEntry = this->StackFrameMap.at((size_t) MapIndex);
		if (NULL == TempEntry.VarPtr) { // Gap in stack frame; IDA 6.0
			SMP_msg("Gap in stack frame: %s\n", this->GetFuncName());
		}
		else if (this->OutgoingArgsSize < (TempEntry.VarPtr->offset + TempEntry.VarPtr->size)) {
#if SMP_DEBUG_FRAMEFIXUP
			SMP_msg("OutGoingArgsSize = %d", this->OutgoingArgsSize);
#endif
			this->OutgoingArgsSize = TempEntry.VarPtr->offset + TempEntry.VarPtr->size;
#if SMP_DEBUG_FRAMEFIXUP
			SMP_msg(" adjusted to %d\n", this->OutgoingArgsSize);
#endif
		}
	}
#endif

	return;
} // end of SMPFunction::FindOutgoingArgsSize()

// If TempOp reads or writes to a stack location, return the offset (relative to the initial
//  stack pointer value) and the size in bytes of the data access. Also return whether the
//  access was frame-pointer-relative, and whether signedness can be inferred due to a load
//  from the stack being zero-extended or sign-extended.
// NOTE: This function assumes that offsets are already normalized. i.e. the TempOp argument
//  should always come from a DEF or USE that has been normalized to the stack delta at function entry.
// NOTE: TempOp must be of type o_displ or o_phrase, as no other operand type could be a
//  stack memory access.
// BaseValue is either this->MinStackAccessOffset, or this->MinStackDelta (when this->MinStackAccessOffset is still
//  being computed).
// Return true if a stack memory access was found in TempOp, false otherwise.
bool SMPFunction::MDGetStackOffsetAndSize(SMPInstr *Instr, op_t TempOp, sval_t BaseValue, ea_t &offset, size_t &DataSize, bool &FP,
										  bool &Indexed, bool &Signed, bool &Unsigned) {
	int BaseReg;
	int IndexReg;
	ushort ScaleFactor;
	int SignedOffset;
	sval_t sp_delta = Instr->GetStackPtrOffset();
	ea_t InstAddr = Instr->GetAddr(); // helps debugging

	assert((o_displ == TempOp.type) || (o_phrase == TempOp.type));
	MDExtractAddressFields(TempOp, BaseReg, IndexReg, ScaleFactor, offset);

	if (TempOp.type == o_phrase) {
		assert(offset == 0);  // implicit zero, as in [esp] ==> [esp+0]
	}

	SignedOffset = (int) offset;  // avoid sign errors during adjustment arithmetic

	if ((BaseReg == R_sp) || (IndexReg == R_sp)) {
		// ESP-relative constant offset
		if (!Instr->AreDefsNormalized()) {
			SignedOffset += sp_delta; // base offsets from entry ESP value
		}
		SignedOffset -= BaseValue; // convert to StackFrameMap index
		offset = (ea_t) SignedOffset; // write back to outgoing argument
		// Get size of data written
		DataSize = GetOpDataSize(TempOp);
		FP = false;
		Indexed = ((BaseReg != R_none) && (IndexReg != R_none)); // two regs used
		unsigned short opcode = Instr->GetCmd().itype;
		Unsigned = (opcode == NN_movzx);
		Signed = (opcode == NN_movsx);
		if ((0 > SignedOffset) && (!Indexed) && (BaseValue == this->MinStackAccessOffset)) {
			// Consider asserting here.
			SMP_msg("ERROR: Negative offset in MDGetStackOffsetAndSize for inst dump: \n");
			Instr->Dump();
		}
		return true;
	}
	else if (this->UseFP && ((BaseReg == MD_FRAME_POINTER_REG) || (IndexReg == MD_FRAME_POINTER_REG))) {
		SignedOffset -= this->FuncInfo.frregs; // base offsets from entry ESP value
		SignedOffset -= BaseValue; // convert to StackFrameMap index
		offset = (ea_t) SignedOffset;
		DataSize = GetOpDataSize(TempOp);
		FP = true;
		Indexed = ((BaseReg != R_none) && (IndexReg != R_none)); // two regs used
#if 0
		assert(Indexed || (!this->StackPtrAnalysisSucceeded()) || !this->HasSTARSStackPtrAnalysisCompleted()); // Else we should never get here with unnormalized stack operands
#else
		if (!(Indexed || (!this->StackPtrAnalysisSucceeded()) || !this->HasSTARSStackPtrAnalysisCompleted())) {
			SMP_msg("WARNING: Unnormalized FP-relative stack offset at %lx after stack analysis succeeded.\n",
				(unsigned long) Instr->GetAddr());
		}
#endif
		unsigned short opcode = Instr->GetCmd().itype;
		Unsigned = (opcode == NN_movzx);
		Signed = (opcode == NN_movsx);
		if ((0 > SignedOffset) && (!Indexed) && (BaseValue == this->MinStackAccessOffset)) {
			// Consider asserting here.
			SMP_msg("ERROR: Negative offset %d in MDGetStackOffsetAndSize: frregs: %d MinStackDelta: %ld Inst dump: \n",
				SignedOffset, this->FuncInfo.frregs, (long) this->MinStackDelta);
			Instr->Dump();
		}
		return true;
	}
	else {
		return false;
	}
} // end of SMPFunction::MDGetStackOffsetAndSize()
		
// Return fine grained stack entry for stack op TempOp from instruction at InstAddr
bool SMPFunction::MDGetFGStackLocInfo(ea_t InstAddr, op_t TempOp, struct FineGrainedInfo &FGEntry) {
	int BaseReg;
	int IndexReg;
	ushort ScaleFactor;
	ea_t offset;
	int SignedOffset;

	assert((o_displ == TempOp.type) || (o_phrase == TempOp.type));
	MDExtractAddressFields(TempOp, BaseReg, IndexReg, ScaleFactor, offset);

	SignedOffset = (int) offset;

	if (TempOp.type == o_phrase) {
		assert(SignedOffset == 0);  // implicit zero, as in [esp] ==> [esp+0]
	}
	if ((BaseReg == MD_STACK_POINTER_REG) || (IndexReg == MD_STACK_POINTER_REG)) {
		// ESP-relative constant offset
		SignedOffset -= this->MinStackAccessOffset; // convert to StackFrameMap index
	}
	else if (this->UseFP && ((BaseReg == MD_FRAME_POINTER_REG) || (IndexReg == MD_FRAME_POINTER_REG))) {
		assert(false); // should never get here with unnormalized stack operand
		SignedOffset -= this->FuncInfo.frregs; // base offsets from entry ESP value
		SignedOffset -= this->MinStackAccessOffset; // convert to StackFrameMap index
	}
	else {
		return false;
	}
	// We did not return false, so we should have a good offset. Use it to
	//  pass back the fine grained stack table entry for that offset.
	if ((0 > SignedOffset) || (SignedOffset >= (int) this->FineGrainedStackTable.size())) {
		if (this->OutgoingArgsComputed) {
			SMP_msg("ERROR: FG stack table index out of range in MDGetFGStackLocInfo at %lx\n",
				(unsigned long) InstAddr);
		}
		FGEntry.SignMiscInfo = 0; // We cannot figure out signedness info without an FG info stack table.
		FGEntry.SizeInfo = ComputeOperandBitWidthMask(TempOp, 0); // IDA can figure out width, anyway.
	}
	else {
		FGEntry = this->FineGrainedStackTable.at((size_t) SignedOffset);
	}
	return true;
} // end of SMPFunction::MDGetFGStackLocInfo()

// Return true if we update fine grained stack entry for stack op TempOp from instruction at InstAddr
bool SMPFunction::MDUpdateFGStackLocInfo(ea_t InstAddr, op_t TempOp, struct FineGrainedInfo NewFG) {
	int BaseReg;
	int IndexReg;
	ushort ScaleFactor;
	ea_t offset;
	int SignedOffset;
	struct FineGrainedInfo OldFG, UnionFG;

	assert((o_displ == TempOp.type) || (o_phrase == TempOp.type));
	MDExtractAddressFields(TempOp, BaseReg, IndexReg, ScaleFactor, offset);

	SignedOffset = (int) offset;

	if (TempOp.type == o_phrase) {
		assert(SignedOffset == 0);  // implicit zero, as in [esp] ==> [esp+0]
	}
	if ((BaseReg == MD_STACK_POINTER_REG) || (IndexReg == MD_STACK_POINTER_REG)) {
		// ESP-relative constant offset
		SignedOffset -= this->MinStackAccessOffset; // convert to StackFrameMap index
	}
	else if (this->UseFP && ((BaseReg == MD_FRAME_POINTER_REG) || (IndexReg == MD_FRAME_POINTER_REG))) {
		assert(false); // should never get here with unnormalized stack operands
		SignedOffset -= this->FuncInfo.frregs; // base offsets from entry ESP value
		SignedOffset -= this->MinStackAccessOffset; // convert to StackFrameMap index
	}
	else {
		return false;
	}
	// We did not return false, so we should have a good offset. Use it to
	//  retrieve the fine grained stack table entry for that offset.
	if ((0 > SignedOffset) || (SignedOffset >= (int) this->FineGrainedStackTable.size())) {
		if (this->OutgoingArgsComputed) {
			SMP_msg("ERROR: FG stack table index out of range in MDGetFGStackLocInfo at %lx\n",
				(unsigned long) InstAddr);
		}
		return false;
	}
	else if (this->OutgoingArgsComputed && (((size_t)SignedOffset) < this->OutgoingArgsSize)) {
		// We don't want to update the outgoing args region, as it will not be consistent
		//  over multiple function calls. NOTE: We could fine tune this by seeing if we
		//  call mutliple target functions or not; if only one, then outgoing args region
		//  would be consistent in the absence of varargs targets.
		return false;
	}
	else {
		OldFG = this->FineGrainedStackTable.at((size_t) SignedOffset);
		UnionFG.SignMiscInfo = OldFG.SignMiscInfo | NewFG.SignMiscInfo;
		UnionFG.SizeInfo = OldFG.SizeInfo | NewFG.SizeInfo;
		if ((OldFG.SignMiscInfo != UnionFG.SignMiscInfo) || (OldFG.SizeInfo != UnionFG.SizeInfo)) {
			// The signs they are a-changin'. Or maybe the sizes.
			this->FineGrainedStackTable.at(SignedOffset).SignMiscInfo |= NewFG.SignMiscInfo;
			this->FineGrainedStackTable.at(SignedOffset).SizeInfo |= NewFG.SizeInfo;
		}
	}
	return true;
} // end of SMPFunction::MDUpdateFGStackLocInfo()

// retrieve DEF addr from GlobalDefAddrBySSA or return BADADDR
ea_t SMPFunction::GetGlobalDefAddr(op_t DefOp, int SSANum) {
	map<int, ea_t>::iterator DefAddrMapIter;
	map<int, ea_t>::iterator MapResult;
	ea_t DefAddr = BADADDR; // BADADDR means we did not find it
	bool RegDef = (o_reg == DefOp.type);

	if (RegDef) {
		int HashedName = HashGlobalNameAndSSA(DefOp, SSANum);
		MapResult = this->GlobalDefAddrBySSA.find(HashedName);
		if (MapResult != this->GlobalDefAddrBySSA.end()) { // Found it.
			DefAddr = (ea_t) MapResult->second;
		}
	}
	else if (MDIsStackAccessOpnd(DefOp, this->UsesFramePointer())) {
		// Until we get stack operands into the GlobalDefAddrBySSA map,
		//  do a linear search.
		list<SMPInstr *>::iterator InstIter = this->Instrs.begin();
		set<DefOrUse, LessDefUse>::iterator DefIter;
		SMPInstr *CurrInst = (*InstIter);
		if (CurrInst->IsFloatNop()) { // marker inst
			if (0 == SSANum) { // Live-in-to-func stack locations get DEF at marker inst.
				DefIter = CurrInst->FindDef(DefOp);
				if (DefIter != CurrInst->GetLastDef()) {
					// Found it. Must be SSA 0.
					assert(0 == DefIter->GetSSANum());
					DefAddr = CurrInst->GetAddr();
					return DefAddr;
				}
			}
			++InstIter;
		}
		for ( ; InstIter != this->Instrs.end(); ++InstIter) {
			CurrInst = (*InstIter);
			if (CurrInst->HasDestMemoryOperand()) {
				op_t MemDefOp = CurrInst->GetMemDef();
				if (IsEqOp(DefOp, MemDefOp)) {
					DefIter = CurrInst->FindDef(MemDefOp);
					assert(DefIter != CurrInst->GetLastDef());
					int DefSSANum = DefIter->GetSSANum();
					if (DefSSANum == SSANum) { // found it
						DefAddr = CurrInst->GetAddr();
						break;
					}
				}
			}
		}
	}
	return DefAddr;
} // end of SMPFunction::GetGlobalDefAddr()

int SMPFunction::GetBlockNumForPhiDef(op_t DefOp, int SSANum) {
	size_t BlockIndex;
	for (BlockIndex = 0; BlockIndex < this->RPOBlocks.size(); ++BlockIndex) {
		SMPBasicBlock *CurrBlock = this->RPOBlocks.at(BlockIndex);
		set<SMPPhiFunction, LessPhi>::iterator PhiIter = CurrBlock->FindPhi(DefOp);
		if (PhiIter != CurrBlock->GetLastPhi()) {
			if (PhiIter->GetDefSSANum() == SSANum) {
				return CurrBlock->GetNumber();
			}
		}
	}
	return (int) BADADDR;
} // end of SMPFunction::GetBlockNumForPhiDef()

// Retrieve block iterator for InstAddr from InstBlockMap; assert if failure
SMPBasicBlock *SMPFunction::GetBlockFromInstAddr(ea_t InstAddr) {
	map<ea_t, SMPBasicBlock *>::iterator MapEntry;
	MapEntry = this->InstBlockMap.find(InstAddr);
	assert(MapEntry != this->InstBlockMap.end());
	return MapEntry->second;
}

// Retrieve inst pointer for InstAddr; assert if failure on block find.
SMPInstr *SMPFunction::GetInstFromAddr(ea_t InstAddr) {
	SMPBasicBlock *CurrBlock = this->GetBlockFromInstAddr(InstAddr);
	SMPInstr *CurrInst = CurrBlock->FindInstr(InstAddr);
	return CurrInst;
}

// Given block # and PhiDef op_t and SSANum, return the Phi iterator or assert.
set<SMPPhiFunction, LessPhi>::iterator SMPFunction::GetPhiIterForPhiDef(size_t BlockNumber, op_t DefOp, int SSANum) {
	SMPBasicBlock *DefBlock = this->RPOBlocks.at(BlockNumber);
	set<SMPPhiFunction, LessPhi>::iterator PhiIter = DefBlock->FindPhi(DefOp);
	assert(PhiIter != DefBlock->GetLastPhi());
	return PhiIter;
}

// Is DestOp within the outgoing args area? Assume it must be an ESP-relative
//  DEF operand in order to be a write to the outgoing args area.
// NOTE: DestOp should be already normalized to the entry stack delta.
bool SMPFunction::IsInOutgoingArgsRegion(op_t DestOp) {
	bool OutArgWrite = false;
	int BaseReg, IndexReg;
	ushort ScaleFactor;
	ea_t offset;

	if (this->IsLeaf())
		return false;

	MDExtractAddressFields(DestOp, BaseReg, IndexReg, ScaleFactor, offset);
	if ((BaseReg != R_sp) && (IndexReg != R_sp))
		return false;
	if (((BaseReg == R_sp) && (IndexReg != R_none))
		|| ((IndexReg == R_sp) && (BaseReg != R_none))
		|| (0 < ScaleFactor)) {

#if 0
		SMP_msg("WARNING: WritesToOutgoingArgs called with indexed write.");
		PrintOperand(DestOp);
#endif
		return false;
	}

	if (!this->OutgoingArgsComputed) {
		OutArgWrite = true; // be conservative
	}
	else {
		int SignedOffset = (int) offset;
		SignedOffset -= this->MinStackDelta; // convert to zero-based from bottom of stack frame
		OutArgWrite = (((size_t) SignedOffset) < this->OutgoingArgsSize);
	}
	return OutArgWrite;
} // end of SMPFunction::IsInOutgoingArgsRegion()

// Is DestOp a direct memory access above the local vars frame?
bool SMPFunction::WritesAboveLocalFrame(op_t DestOp, bool OpNormalized) {
	bool InArgWrite = false;
	int BaseReg, IndexReg;
	ushort ScaleFactor;
	ea_t offset;
	long SignedOffset;

	MDExtractAddressFields(DestOp, BaseReg, IndexReg, ScaleFactor, offset);
	SignedOffset = (long) offset;
	bool ESPrelative = (BaseReg == MD_STACK_POINTER_REG) || (IndexReg == MD_STACK_POINTER_REG);
	bool EBPrelative = this->UseFP && ((BaseReg == MD_FRAME_POINTER_REG) || (IndexReg == MD_FRAME_POINTER_REG));
	assert(!EBPrelative || !OpNormalized); // stack operands should be normalized by now
	if (!(ESPrelative || EBPrelative))
		return false;
	if (((IndexReg != R_none) && (BaseReg != R_none))
		|| (0 < ScaleFactor)) {

		SMP_msg("WARNING: WritesAboveLocalFrame called with indexed write.");
		PrintOperand(DestOp);
		return false;
	}

	// The next statement omits a complication: The possibility that OpNormalized is false,
	//  and an ESPRelative access is above the stack frame. For the purposes of determining
	//  whether a function is safe, this is irrelevant, because !OpNormalized would indicate
	//  that AnalyzedSP is false, which will make the function unsafe anyway. Future uses for
	//  other purposes need to fix this.
	InArgWrite = (ESPrelative && OpNormalized && (SignedOffset >= 0))
		|| (EBPrelative && (SignedOffset > 0));

	if (InArgWrite && OpNormalized && (0 == SignedOffset)) {
		SMP_msg("DANGER: Write to saved return address detected in function that begins at %lx\n",
			(unsigned long) this->FirstEA);
	}

	return InArgWrite;
}// end of SMPFunction::WritesAboveLocalFrame()

// Is DestOp an indexed write above the local vars frame?
bool SMPFunction::IndexedWritesAboveLocalFrame(op_t DestOp) {
	bool InArgWrite = false;
	int BaseReg, IndexReg;
	ushort ScaleFactor;
	ea_t offset;
	int SignedOffset;

	MDExtractAddressFields(DestOp, BaseReg, IndexReg, ScaleFactor, offset);
	bool ESPrelative = (BaseReg == MD_STACK_POINTER_REG) || (IndexReg == MD_STACK_POINTER_REG);
	bool EBPrelative = this->UseFP && ((BaseReg == MD_FRAME_POINTER_REG) || (IndexReg == MD_FRAME_POINTER_REG));
	assert(!EBPrelative || !this->StackPtrAnalysisSucceeded() || !this->HasSTARSStackPtrAnalysisCompleted()); // stack operands should be normalized by now
	if (!(ESPrelative || EBPrelative))
		return false;

	SignedOffset = (int) offset;
	InArgWrite = (ESPrelative && (SignedOffset > 0))
		|| (EBPrelative && (SignedOffset > 0));

	return InArgWrite;
} // end of SMPFunction::IndexedWritesAboveLocalFrame()

// Is CurrOp found anywhere in the StackPtrCopySet, regardless of which address and stack delta
//  values are associated with it?
bool SMPFunction::IsInStackPtrCopySet(op_t CurrOp) {
	bool found = false;
	// Set is composed of triples, so we have to iterate through it and compare operands.
	set<pair<op_t, pair<ea_t, sval_t> >, LessStackDeltaCopy>::iterator CopyIter;
	for (CopyIter = this->StackPtrCopySet.begin(); CopyIter != this->StackPtrCopySet.end(); ++CopyIter) {
		pair<op_t, pair<ea_t, sval_t> > CurrCopy = *CopyIter;
		op_t CopyOp = CurrCopy.first;
		if (IsEqOp(CopyOp, CurrOp)) {
			// Found it.
			found = true;
			break;
		}
		else if (CopyOp.type > CurrOp.type) {
			// already moved past its spot; not found
			break;
		}
	}

	return found;
} // end of SMPFunction::IsInStackPtrCopySet()

// Find evidence of calls to alloca(), which appear as stack space allocations (i.e.
//  subtractions [of unknown values(?)] from the stack pointer) AFTER the local frame allocation instruction
//  for this function.
// Return true if such an allocation is found and false otherwise.
bool SMPFunction::FindAlloca(void) {
	bool FoundAlloca = false;
	list<SMPInstr *>::iterator InstIter = this->Instrs.begin();
	SMPInstr *CurrInst;
	ea_t InstAddr;
#if SMP_USE_SSA_FNOP_MARKER
	++InstIter;  // skip marker instruction
#endif
	for ( ; InstIter != this->Instrs.end(); ++InstIter) {
		CurrInst = (*InstIter);
		InstAddr = CurrInst->GetAddr();
		if (InstAddr > this->LocalVarsAllocInstr) {
			if (CurrInst->MDIsFrameAllocInstr()) {
				FoundAlloca = true;
				if (CurrInst->HasAllocaRTL()) {
					CurrInst->SetAllocaCall();
				}
			}
			else if (CurrInst->MDIsPushInstr()) {
				this->PushAfterLocalVarAlloc = true;
			}
		}
	}
	return FoundAlloca;
} // end of SMPFunction::FindAlloca()

// Emit the annotations describing the regions of the stack frame.
void SMPFunction::EmitStackFrameAnnotations(FILE *AnnotFile, SMPInstr *Instr) {
	ea_t addr = Instr->GetAddr();

#if 0
	if (0 < IncomingArgsSize) {
		SMP_fprintf(AnnotFile, "%10lx %6d INARGS STACK esp + %ld %s \n",
				(unsigned long) addr, IncomingArgsSize,
				(long) (LocalVarsSize + CalleeSavedRegsSize + RetAddrSize),
				Instr->GetDisasm());
	}
#endif
	if (0 < this->RetAddrSize) {
		SMP_fprintf(AnnotFile, "%10lx %6d MEMORYHOLE STACK esp + %lu ReturnAddress \n",
				(unsigned long) addr, RetAddrSize, (unsigned long) (this->LocalVarsSize + this->CalleeSavedRegsSize));
	}
	if (0 < this->CalleeSavedRegsSize) {
		SMP_fprintf(AnnotFile, "%10lx %6u MEMORYHOLE STACK esp + %lu CalleeSavedRegs \n",
				(unsigned long) addr, this->CalleeSavedRegsSize, (unsigned long) this->LocalVarsSize);
	}
	if ((0 < this->LocalVarsSize) && this->GoodLocalVarTable) {
		unsigned long ParentReferentID = DataReferentID++;
		SMP_fprintf(AnnotFile, "%10lx %6lu DATAREF STACK %ld esp + %d PARENT LocalFrame LOCALFRAME\n",
				(unsigned long) addr, (unsigned long) this->LocalVarsSize, ParentReferentID, 0);
#if SMP_COMPUTE_STACK_GRANULARITY
		if (this->AnalyzedSP && !this->CallsAlloca && (BADADDR != this->LocalVarsAllocInstr)) {
			// We can only fine-grain the stack frame if we were able to analyze the stack
			if (this->OutgoingArgsSize > 0) {
				SMP_fprintf(AnnotFile, "%10lx %6zu DATAREF STACK %ld esp + %d CHILDOF %ld OFFSET %d OutArgsRegion OUTARGS\n",
					(unsigned long) addr, this->OutgoingArgsSize, DataReferentID, 0, ParentReferentID, 0);
				++DataReferentID;
			}
#if SMP_DEBUG_STACK_GRANULARITY
			SMP_msg("LocalVarTable of size %d for function %s\n", this->LocalVarTable.size(),
				this->GetFuncName());
#endif
			for (size_t i = 0; i < this->LocalVarTable.size(); ++i) {
#if SMP_DEBUG_STACK_GRANULARITY
				SMP_msg("Entry %d offset %ld size %d name %s\n", i, this->LocalVarTable[i].offset,
					this->LocalVarTable[i].size, this->LocalVarTable[i].VarName);
#endif
				// Don't emit annotations for incoming or outgoing args or anything else
				//  above or below the current local frame.
				if ((this->LocalVarTable[i].offset >= (long) this->FuncInfo.frsize)
					|| (this->LocalVarTable[i].offset < (long) this->OutgoingArgsSize))
					continue;
				SMP_fprintf(AnnotFile, "%10lx %6zu DATAREF STACK %ld esp + %ld CHILDOF %ld OFFSET %ld LOCALVAR %s \n",
					(unsigned long) addr, this->LocalVarTable[i].size, DataReferentID,
					this->LocalVarTable[i].offset, ParentReferentID,
					this->LocalVarTable[i].offset, this->LocalVarTable[i].VarName);
				++DataReferentID;
			}
		} // end if (this->AnalyzedSP and not Alloca .... )
#endif
	} // end if (0 < LocalVarsSize)
	return;
} // end of SMPFunction::EmitStackFrameAnnotations() 

// Audit and fix the IDA Pro code cross references for jumps and jump targets.
void SMPFunction::MDAuditJumpXrefs(void) {
	func_tail_iterator_t FuncTail(this->GetFuncInfo());
	enum cref_t NearJump = (cref_t)(fl_JN | XREF_USER);
	enum cref_t FarJump = (cref_t)(fl_JF | XREF_USER);

 	for (bool ChunkOK = FuncTail.main(); ChunkOK; ChunkOK = FuncTail.next()) {
		const area_t &CurrChunk = FuncTail.chunk();

		// Find the instructions for each chunk, audit the xrefs.
		for (ea_t addr = CurrChunk.startEA; addr < CurrChunk.endEA; addr = get_item_end(addr)) {
			flags_t InstrFlags = getFlags(addr);
			if (isHead(InstrFlags) && isCode(InstrFlags)) {
				// Fill cmd structure with disassembly of instr
				insn_t LocalCmd;
				ulong LocalFeatures;
				if (!SMPGetCmd(addr, LocalCmd, LocalFeatures)) {
					SMP_msg("ERROR: SMPGetCmd failed from MDAuditJumpXrefs at %lx\n",
						(unsigned long) addr);
				}
				else {
					unsigned short opcode = LocalCmd.itype;

					// Determine whether the instruction is a jump target by looking
					//  at its cross references and seeing if it has "TO" code xrefs.
					SMP_xref_t xrefs, Distant_xrefs;
					for (bool ok = xrefs.SMP_first_to(addr, XREF_FAR); ok; ok = xrefs.SMP_next_to()) {
						ea_t DistantAddr = xrefs.GetFrom();
						if ((DistantAddr != 0) && (xrefs.GetIscode())) {
							// Now we see if the distant instruction has an xref to this instruction.
							bool FoundDistantXref = false;
							for (bool ok2 = Distant_xrefs.SMP_first_from(DistantAddr, XREF_FAR); ok2; ok2 = Distant_xrefs.SMP_next_from()) {
								ea_t TargetAddr = Distant_xrefs.GetTo();
								if (TargetAddr == addr) {
									FoundDistantXref = true;
									break;
								}
							}
							if (!FoundDistantXref) {
								SMP_msg("WARNING: Missing code Xref from %lx to %lx\n",
									(unsigned long) DistantAddr, (unsigned long) addr);
								long SignedAddrDiff = (long) (DistantAddr - addr);
								if ((SignedAddrDiff < -128) || (SignedAddrDiff > 127)) {
									add_cref(DistantAddr, addr, FarJump);
								}
								else {
									add_cref(DistantAddr, addr, NearJump);
								}
							}
						}
					} // end for all "to" xrefs
					// Now check the "from" xrefs to see if the target inst has the corresponding "to" xref.
					for (bool ok = xrefs.SMP_first_from(addr, XREF_FAR); ok; ok = xrefs.SMP_next_from()) {
						ea_t DistantAddr = xrefs.GetTo();
						if ((DistantAddr != 0) && (xrefs.GetIscode())) {
							// Now we see if the distant instruction has an xref to this instruction.
							bool FoundDistantXref = false;
							for (bool ok2 = Distant_xrefs.SMP_first_to(DistantAddr, XREF_FAR); ok2; ok2 = Distant_xrefs.SMP_next_to()) {
								ea_t SourceAddr = Distant_xrefs.GetFrom();
								if (SourceAddr == addr) {
									FoundDistantXref = true;
									break;
								}
							}
							if (!FoundDistantXref) {
								SMP_msg("WARNING: Missing code Xref to %lx from %lx\n",
									(unsigned long) DistantAddr, (unsigned long) addr);
								long SignedAddrDiff = (long) (DistantAddr - addr);
								if ((SignedAddrDiff < -128) || (SignedAddrDiff > 127)) {
									add_cref(DistantAddr, addr, FarJump);
								}
								else {
									add_cref(DistantAddr, addr, NearJump);
								}
							}
						}
					} // end for all "from" xrefs
				} // end if (!SMPGetCmd() ... else ...
			} // end if (IsHead() and IsCode())
		} // end for all addrs in chunk
	} // end for all chunks

	return;
} // end of SMPFunction::MDAuditJumpXrefs()

// Main data flow analysis driver. Goes through the function and
//  fills all objects for instructions, basic blocks, and the function
//  itself.
void SMPFunction::Analyze(void) {
	bool FoundAllCallers = false;
	list<SMPInstr *>::iterator FirstInBlock = this->Instrs.end();
	   // For starting a basic block
	list<SMPInstr *>::iterator LastInBlock = this->Instrs.end();
	   // Terminating a basic block
	sval_t CurrStackPointerOffset = 0;
	set<ea_t> FragmentWorkList;  // Distant code fragments that belong to this function and need processing
	ea_t InstAddr; // grab address to help in debugging, conditional breakpoints, etc.
	ea_t PreviousIndirJumpAddr = BADADDR;
	enum cref_t NearJump = (cref_t)(fl_JN | XREF_USER);
	enum cref_t FarJump = (cref_t)(fl_JF | XREF_USER);

#if SMP_DEBUG_CONTROLFLOW
	SMP_msg("Entering SMPFunction::Analyze.\n");
#endif

	// Get some basic info from the FuncInfo structure.
	this->Size = this->FuncInfo.endEA - this->FuncInfo.startEA;
	this->UseFP = (0 != (this->FuncInfo.flags & (FUNC_FRAME | FUNC_BOTTOMBP)));
	this->StaticFunc = (0 != (this->FuncInfo.flags & FUNC_STATIC));
	this->LibFunc = (0 != (this->FuncInfo.flags & FUNC_LIB));
	this->AnalyzedSP = this->FuncInfo.analyzed_sp();

#if SMP_DEBUG_CONTROLFLOW
	SMP_msg("SMPFunction::Analyze: got basic info.\n");
#endif

	// Determine if we are dealing with shared chunks.
	size_t ChunkCounter = 0;
	func_tail_iterator_t FuncTail(this->GetFuncInfo());
	ea_t FuncHeadLastAddr = 0;
	for (bool ChunkOK = FuncTail.main(); ChunkOK; ChunkOK = FuncTail.next()) {
		const area_t &CurrChunk = FuncTail.chunk();
		++ChunkCounter;
		if (1 == ChunkCounter) { // head chunk
			FuncHeadLastAddr = CurrChunk.endEA;
		}
		else { // a tail chunk
#if STARS_FIND_UNSHARED_CHUNKS
			if (this->GetProg()->IsChunkUnshared(CurrChunk.startEA, this->FirstEA, FuncHeadLastAddr)) {
				this->UnsharedChunks = true;
#if SMP_DEBUG_CHUNKS
				SMP_msg("INFO: Found unshared tail chunk for %s at %lx\n",
					this->GetFuncName(), (unsigned long) CurrChunk.startEA);
#endif
			}
			else {
#endif // STARS_FIND_UNSHARED_CHUNKS
				this->SharedChunks = true;
#if SMP_DEBUG_CHUNKS
				SMP_msg("INFO: Found tail chunk for %s at %lx\n",
					this->GetFuncName(), (unsigned long) CurrChunk.startEA);
#endif
#if STARS_FIND_UNSHARED_CHUNKS 
			}
#endif // STARS_FIND_UNSHARED_CHUNKS
		}
	}

#if STARS_AUDIT_JUMP_XREFS
	this->MDAuditJumpXrefs();
#endif

	// Cycle through all chunks that belong to the function.
	ChunkCounter = 0;
	bool GoodRTL;
	this->BuiltRTLs = true;
 	for (bool ChunkOK = FuncTail.main(); ChunkOK; ChunkOK = FuncTail.next()) {
		const area_t &CurrChunk = FuncTail.chunk();
		++ChunkCounter;
#if 0
		if (CurrChunk.startEA < this->FirstEA) {
			this->FirstEA = CurrChunk.startEA;
		}
#endif
#if STARS_DEBUG_MEMORY_CORRUPTION
	bool DebugFlag = (0 == strcmp("sub_8063BE0", this->GetFuncName()));
#endif
		// Build the instruction and block lists for the function.
		for (ea_t addr = CurrChunk.startEA; addr < CurrChunk.endEA;
			addr = get_item_end(addr)) {
			flags_t InstrFlags = getFlags(addr);
			if (!isHead(InstrFlags)) {
				continue;
			}
			if (!isCode(InstrFlags)) { //data
				// Check for code xrefs from the data.
				SMP_xref_t xrefs;
				for (bool ok = xrefs.SMP_first_from(addr, XREF_ALL); ok; ok = xrefs.SMP_next_from()) {
					if ((xrefs.GetTo() != 0) && (xrefs.GetIscode())) {
						// Found a code target, with its address in xrefs.to
						PrintDataToCodeXref(addr, xrefs.GetTo(), 0);
					}
				}
			}
			else { // code
				SMPInstr *CurrInst = new SMPInstr(addr);
				// Fill in the instruction data members.
#if SMP_DEBUG_CONTROLFLOW
				SMP_msg("SMPFunction::Analyze: calling CurrInst::Analyze.\n");
#endif
				CurrInst->Analyze();
				if (SMPBinaryDebug) {
					SMP_msg("Disasm:  %s \n", CurrInst->GetDisasm());
				}
#if SMP_COUNT_MEMORY_ALLOCATIONS
				SMPInstBytes += sizeof(*CurrInst);
#endif

#if SMP_USE_SSA_FNOP_MARKER
				if (this->Instrs.empty()) {
					// First instruction in function. We want to create a pseudo-instruction
					//  at the top of the function that can hold SSA DEFs for LiveIn names
					//  to the function. We use a floating point no-op as the pseudo-inst.
					//  The code address is one less than the start address of the function.
					SMPInstr *MarkerInst = new SMPInstr(addr - 1);
					MarkerInst->AnalyzeMarker();
					GoodRTL = MarkerInst->BuildRTL();
					this->BuiltRTLs = (this->BuiltRTLs && GoodRTL);
					if (GoodRTL) {
						MarkerInst->SetGoodRTL();
					}
					assert(FirstInBlock == this->Instrs.end());
					this->Instrs.push_back(MarkerInst);
#if SMP_COUNT_MEMORY_ALLOCATIONS
					SMPInstBytes += sizeof(*MarkerInst);
#endif
				}
#endif

				// Find all functions that call the current function.
				SMP_xref_t CurrXrefs;
				if (!FoundAllCallers) {
					for (bool ok = CurrXrefs.SMP_first_to(addr, XREF_ALL); ok; ok = CurrXrefs.SMP_next_to()) {
						ea_t FromAddr = CurrXrefs.GetFrom();
						if ((FromAddr != 0) && (CurrXrefs.GetIscode())) {
							// Make sure it is not a fall-through. Must be a
							//  control-flow instruction of some sort, including
							//  direct or indirect calls or tail calls.
							SMPInstr CallInst(FromAddr);
							CallInst.Analyze();
							SMPitype CallType = CallInst.GetDataFlowType();
							if ((COND_BRANCH <= CallType) && (RETURN >= CallType)) {
								// Found a caller, with its call address in CurrXrefs.from
								this->AddCallSource(FromAddr);
							}
						}
					}
					FoundAllCallers = true; // only do this for first inst
				}

				SMPitype DataFlowType = CurrInst->GetDataFlowType();
				if ((DataFlowType == INDIR_CALL) || (DataFlowType == CALL)) {
					// See if IDA has determined the target of the call.
#if 0
					CurrInst->AnalyzeCallInst(this->FirstEA, this->FuncInfo.endEA);
#endif
					ea_t TargetAddr = CurrInst->GetCallTarget();
					bool LinkedToTarget = (BADADDR != TargetAddr);
					if (LinkedToTarget) {
						if (0 == TargetAddr) {
							SMP_msg("WARNING: Ignoring NULL call target (unreachable) at %lx\n", 
								(unsigned long) CurrInst->GetAddr());
						}
						else {
							pair<set<ea_t>::iterator, bool> InsertResult;
							if (INDIR_CALL == DataFlowType) {
								InsertResult = this->IndirectCallTargets.insert(TargetAddr);
							}
							else {
								InsertResult = this->DirectCallTargets.insert(TargetAddr);
							}
							if (InsertResult.second) {
								this->AllCallTargets.push_back(TargetAddr);
							}
						}
					}
					if (DataFlowType == INDIR_CALL) {
						this->IndirectCalls = true;
						this->UnresolvedIndirectCalls = (!LinkedToTarget);
					}
				} // end if INDIR_CALL or CALL
				else if (DataFlowType == INDIR_JUMP) {
					this->IndirectJumps = true;
#if STARS_AUDIT_INDIR_JUMP_XREFS
					PreviousIndirJumpAddr = addr;
#endif
				}
				else if (DataFlowType == RETURN) {
					this->HasReturnInst = true;
				}
				// Add call targets for tail call jumps.
				else if (CurrInst->IsBranchToFarChunk()) {
					ea_t FarTargetAddr = CurrInst->GetFarBranchTarget();
					if (BADADDR != FarTargetAddr) {
						assert((RETURN == DataFlowType) || (JUMP == DataFlowType) || (COND_BRANCH == DataFlowType));
						// Optimized tail calls, where the stack frame is down to zero at the call point,
						//  get RETURN as their DataFlowType. Might have to revisit that idea at some point. !!!!****!!!!
						if (this->FindDistantCodeFragment(FarTargetAddr)) {
							if (this->GetProg()->InsertUnsharedFragment(FarTargetAddr)) {
								// Fragment address was inserted in SMPProgram set, was not already there.
								pair<set<ea_t>::iterator, bool> InsertResult;
								InsertResult = FragmentWorkList.insert(FarTargetAddr);
								if (InsertResult.second) {
									SMP_msg("INFO: Found distant code fragment at %lx that can be added to func, reached from %lx\n",
										(unsigned long) FarTargetAddr, (unsigned long) addr);
#if 0
									if (FarTargetAddr < this->FirstEA) {
										this->FirstEA = FarTargetAddr;
									}
#endif
								}
								else {
									// These kind of fragments are generally only jumped to from one place,
									//  and jump back into the function that jumped into them. Very suspicious
									//  to encounter such a fragment more than once, and even if it happens,
									//  the insertion into the SMPProgram set should have failed due to already
									//  being present. This message and assertion should never be reached.
									SMP_msg("FATAL ERROR: Distant fragment at %lx reached from %lx already reached from same function.\n",
										(unsigned long) FarTargetAddr, (unsigned long) addr);
									assert(InsertResult.second); // sanity lost; shut down
								}
							}
							else { // Fragment address was already in SMPProgram set
								; // Probably added in loop at beginning that found unshared fragments.
#if 0
								// These kind of fragments are generally only jumped to from one place,
								//  and jump back into the function that jumped into them. Very suspicious
								//  to encounter such a fragment more than once.
								SMP_msg("WARNING: Distant fragment at %x reached from %x has already been processed.\n",
									FarTargetAddr, addr);
#endif
							}
						}
						else if (!this->GetProg()->IsUnsharedFragment(FarTargetAddr)) {
							pair<set<ea_t>::iterator, bool> InsertResult;
							InsertResult = this->DirectCallTargets.insert(FarTargetAddr);
							if (InsertResult.second) {
								this->AllCallTargets.push_back(FarTargetAddr);
							}
						}
					}
				}

#if STARS_AUDIT_INDIR_JUMP_XREFS
				if (FirstInBlock == this->Instrs.end()) { // CurrInst will start a block
					if (CurrInst->HasNoCodeXrefs() && (BADADDR != PreviousIndirJumpAddr) && (addr != PreviousIndirJumpAddr)) {
						// This block appears unreachable, but it can probably be reached by
						//  the most recent indirect jump. IDA Pro sometimes thinks it has
						//  resolved an indirect jump completely but has only done so partially.
						SMP_msg("WARNING: Adding possible missing indirect jump code Xref to %lx from %lx\n",
							(unsigned long) addr, (unsigned long) PreviousIndirJumpAddr);
						long SignedAddrDiff = (long) (addr - PreviousIndirJumpAddr);
						if ((SignedAddrDiff < -128) || (SignedAddrDiff > 127)) {
							add_cref(PreviousIndirJumpAddr, addr, FarJump);
						}
						else {
							add_cref(PreviousIndirJumpAddr, addr, NearJump);
						}
						CurrInst->SetJumpTarget();
					}
				}
#endif

				// Before we insert the instruction into the instruction
				//  list, determine if it is a jump target that does not
				//  follow a basic block terminator. This is the special case
				//  of a CASE in a SWITCH that falls through into another
				//  CASE, for example. The first sequence of statements
				//  was not terminated by a C "break;" statement, so it
				//  looks like straight line code, but there is an entry
				//  point at the beginning of the second CASE sequence and
				//  we have to split basic blocks at the entry point.
				if ((FirstInBlock != this->Instrs.end()) && CurrInst->IsJumpTarget()) {
#if SMP_DEBUG_CONTROLFLOW
					SMP_msg("SMPFunction::Analyze: hit special jump target case.\n");
#endif
					LastInBlock = --(this->Instrs.end());
					SMPBasicBlock *NewBlock = new SMPBasicBlock(this, FirstInBlock,	LastInBlock);
					// If not the first chunk in the function, it is a shared
					//  tail chunk.
					if (ChunkCounter > 1) {
						NewBlock->SetShared();
					}
					FirstInBlock = this->Instrs.end();
					LastInBlock = this->Instrs.end();
					this->Blocks.push_back(NewBlock);
					this->BlockCount += 1;
				}

				// Build tree RTLs for the instruction.
				GoodRTL = CurrInst->BuildRTL();
				this->BuiltRTLs = (this->BuiltRTLs && GoodRTL);
				if (GoodRTL) {
					CurrInst->SetGoodRTL();
				}
#if SMP_DEBUG_BUILD_RTL
				else {
					SMP_msg("ERROR: Cannot build RTL at %lx for %s\n", 
						(unsigned long) CurrInst->GetAddr(), CurrInst->GetDisasm());
				}
#endif

#if SMP_DEBUG_CONTROLFLOW
		SMP_msg("SMPFunction::Analyze: putting CurrInst on list.\n");
#endif
				// Insert instruction at end of list.
				this->Instrs.push_back(CurrInst);

				// Find basic block leaders and terminators.
				if (FirstInBlock == this->Instrs.end()) {
#if SMP_DEBUG_CONTROLFLOW
					SMP_msg("SMPFunction::Analyze: setting FirstInBlock.\n");
#endif
#if SMP_USE_SSA_FNOP_MARKER
					if (2 == this->Instrs.size()) {
						// Just pushed first real instruction, after the fnop marker.
						FirstInBlock = this->Instrs.begin();
					}
					else {
						FirstInBlock = --(this->Instrs.end());
					}
#else
					FirstInBlock = --(this->Instrs.end());
#endif
				}
				if (CurrInst->IsBasicBlockTerminator()) {
#if SMP_DEBUG_CONTROLFLOW
		SMP_msg("SMPFunction::Analyze: found block terminator.\n");
#endif
					LastInBlock = --(this->Instrs.end());
					SMPBasicBlock *NewBlock = new SMPBasicBlock(this, FirstInBlock, LastInBlock);
					// If not the first chunk in the function, it is a shared
					//  tail chunk.
					if (ChunkCounter > 1) {
						NewBlock->SetShared();
					}
					FirstInBlock = this->Instrs.end();
					LastInBlock = this->Instrs.end();
					this->Blocks.push_back(NewBlock);
					this->BlockCount += 1;

				}
			} // end if (isCode(InstrFlags))
		} // end for (ea_t addr = CurrChunk.startEA; ... )

		// Handle the special case in which a function does not terminate
		//  with a return instruction or any other basic block terminator.
		//  Sometimes IDA Pro sees a call to a NORET function and decides
		//  to not include the dead code after it in the function. That
		//  dead code includes the return instruction, so the function no
		//  longer includes a return instruction and terminates with a CALL.
		if (FirstInBlock != this->Instrs.end()) {
			LastInBlock = --(this->Instrs.end());
			SMPBasicBlock *NewBlock = new SMPBasicBlock(this, FirstInBlock, LastInBlock);
			// If not the first chunk in the function, it is a shared
			//  tail chunk.
			if (ChunkCounter > 1) {
				NewBlock->SetShared();
			}
			FirstInBlock = this->Instrs.end();
			LastInBlock = this->Instrs.end();
			this->Blocks.push_back(NewBlock);
			this->BlockCount += 1;
		}
	} // end for (bool ChunkOK = ...)

#if KLUDGE_VFPRINTF_FAMILY
	if (!this->SharedChunks && (0 != strstr(this->GetFuncName(), "printf"))) {
		this->SharedChunks = true;
		SMP_msg("INFO: Kludging function %s\n", this->GetFuncName());
	}
#endif

#if SMP_IDAPRO52_WORKAROUND
	if (!this->SharedChunks && (0 == strcmp(this->GetFuncName(), "error_for_asm"))) {
		this->SharedChunks = true;
		SMP_msg("Kludging function %s\n", this->GetFuncName());
	}
#endif

	// Now that we have all instructions and basic blocks, link each instruction
	//  to its basic block. 
	list<SMPBasicBlock *>::iterator BlockIter;
	SMPBasicBlock *CurrBlock;
	vector<SMPInstr *>::iterator InstIter;
	SMPInstr *CurrInst;
	for (BlockIter = this->Blocks.begin(); BlockIter != this->Blocks.end(); ++BlockIter) {
		CurrBlock = (*BlockIter);
		for (InstIter = CurrBlock->GetFirstInst(); InstIter != CurrBlock->GetLastInst(); ++InstIter) {
			CurrInst = (*InstIter);
			InstAddr = CurrInst->GetAddr();
			CurrInst->SetBlock(CurrBlock->GetThisBlock());

#if 0
			if (this->AnalyzedSP) {
				// Audit the IDA SP analysis.
				sval_t sp_delta = get_spd(this->GetFuncInfo(), InstAddr);
				// sp_delta is difference between current value of stack pointer
				//  and value of the stack pointer coming into the function. It
				//  is updated AFTER each instruction. Thus, it should not get back
				//  above zero (e.g. to +4) until after a return instruction.
				if (sp_delta > 0) {
					// Stack pointer has underflowed, according to IDA's analysis,
					//  which is probably incorrect.
					this->AnalyzedSP = false;
					SMP_msg("WARNING: Resetting AnalyzedSP to false for %s\n", this->GetFuncName());
					SMP_msg("Underflowing instruction: %s sp_delta: %d\n", CurrInst->GetDisasm(),
						sp_delta);
				}
				else if (sp_delta == 0) {
#if 0
					// Search for tail calls.
					if (CurrInst->IsBranchToFarChunk()) {
						// After the stack has been restored to the point at which
						//  we are ready to return, we instead find a jump to a
						//  far chunk. This is the classic tail call optimization:
						//  the return statement has been replaced with a jump to
						//  another function, which will return not to this function,
						//  but to the caller of this function.
						CurrInst->SetTailCall();
						SMP_msg("Found tail call at %x from %s: %s\n", InstAddr, this->GetFuncName(),
							CurrInst->GetDisasm());
					}
#endif
					;
				}
				else if (CurrInst->IsBranchToFarChunk() && (!this->HasSharedChunks())) {
					SMP_msg("WARNING: Found tail call branch with negative stack delta at %x\n", InstAddr);
				}
			} // end if (this->AnalyzedSP)
#endif

		} // end for each inst
		CurrBlock->Analyze();
	} // end for each block

	// Set up basic block links and map of instructions to blocks.
	this->SetLinks();
	this->RPONumberBlocks();

	FragmentWorkList.clear();
	return;
} // end of SMPFunction::Analyze()

// Perform analyses that might need some info from other functions in the call graph.
void SMPFunction::AdvancedAnalysis(void) {
	list<SMPInstr *>::iterator InstIter;
	SMPInstr *CurrInst;

	// IDA Pro has trouble with functions that do not have any local
	//  variables. Unfortunately, the C library has plenty of these
	//  functions. IDA usually claims that frregs is zero and frsize
	//  is N, when the values should have been reversed. We can attempt
	//  to detect this and fix it. IDA Pro also sometimes has trouble with
	//  functions that allocate the stack frame, and then push registers
	//  later before making a call, because it wants to include register
	//  pushes below the stack frame as being part of the stack frame,
	//  even when they are temporary saves and restores. __brk in the
	//  Gnu stdclib is an example as of November of 2012.
	bool FrameInfoFixed = this->MDFixFrameInfo();
#if SMP_DEBUG_CONTROLFLOW
	SMP_msg("Returned from MDFixFrameInfo()\n");
#endif

	this->FindAllAllocsAndDeallocs();
	this->CallsAlloca = this->FindAlloca();

#if 1
	InstIter = this->Instrs.begin();
	if ((*InstIter)->IsFloatNop()) {
		++InstIter; // skip marker inst
	}
	for ( ; InstIter != this->Instrs.end(); ++InstIter) {
		CurrInst = (*InstIter);
		// We can finally search for stack loads now that UseFP has been fixed by
		//  MDFixUseFP(). Otherwise, we would do this in SMPInstr::Analyze(),
		//  but the UseFP flag is not ready that early.
		CurrInst->MDFindLoadFromStack(this->UseFP);

		// Fix up machine dependent quirks in the def and use lists.
		//  This used to be called from within SMPInstr.Analyze(), but info such as UseFP
		//  is not available that early.
		CurrInst->MDFixupDefUseLists();
	}
#endif
	InstIter = this->Instrs.begin();
	if ((*InstIter)->IsFloatNop()) {
		++InstIter; // skip marker inst
	}
	for ( ; InstIter != this->Instrs.end(); ++InstIter) {
		CurrInst = (*InstIter);
		ea_t InstAddr = CurrInst->GetAddr(); // for debugging breakpoints
		if (CurrInst->HasGoodRTL())
			CurrInst->SyncAllRTs(this->UsesFramePointer(), this->GetFramePtrStackDelta());

		// Detect indirect memory references.
		CurrInst->AnalyzeIndirectRefs(this->UseFP);

#if 0
		// Is the instruction a branch to a target outside the function? If
		//  so, this function has shared tail chunks.
		if (CurrInst->IsBranchToFarChunk() && (!CurrInst->IsTailCall())) {
			this->SharedChunks = true;
		}
#endif
	} // end for all instructions

	// Audit the call instructions and call targets.
	//  !!!!****!!!! NOTE: Not sure the address range checks in this code are valid
	//   for functions with scattered chunks.
	if ((!this->AllCallTargets.empty()) || this->UnresolvedIndirectCalls) {
		bool FoundInternalCallTarget = false;
		vector<ea_t>::iterator CurrTarget = this->AllCallTargets.begin();
		set<ea_t>::iterator CurrDirectTarget, CurrIndirectTarget;
		while (CurrTarget != this->AllCallTargets.end()) {
			if ((this->FirstEA <= *CurrTarget) && (this->FuncInfo.endEA >= *CurrTarget)) {
				// Found a call target that is within the function.
				FoundInternalCallTarget = true;
				if (this->FirstEA == *CurrTarget) { // Direct recursion, not a pseudo-jump
					this->DirectlyRecursive = true;
				}
				CurrTarget = this->AllCallTargets.erase(CurrTarget);
			}
			else {
				++CurrTarget;
			}
		}
		if (FoundInternalCallTarget) {
			// We have to mark the pseudo-call instructions and audit the direct and
			//  indirect call target vectors.

			// Audit direct call targets.
			CurrDirectTarget = this->DirectCallTargets.begin();
			set<ea_t>::iterator CopyOfIterator;
			while (CurrDirectTarget != this->DirectCallTargets.end()) {
				ea_t TargetAddr = (*CurrDirectTarget);
				if ((this->FirstEA <= TargetAddr) && (this->FuncInfo.endEA >= TargetAddr)) {
					// Found a call target that is within the function.
					CopyOfIterator = CurrDirectTarget;
					++CopyOfIterator; // point to element after element that will be erased
					this->DirectCallTargets.erase(CurrDirectTarget);
					CurrDirectTarget = CopyOfIterator;
				}
				else {
					++CurrDirectTarget;
				}
			}
			// Audit indirect call targets.
			CurrIndirectTarget = this->IndirectCallTargets.begin();
			while (CurrIndirectTarget != this->IndirectCallTargets.end()) {
				ea_t TargetAddr = (*CurrIndirectTarget);
				if ((this->FirstEA <= TargetAddr) && (this->FuncInfo.endEA >= TargetAddr)) {
					// Found a call target that is within the function.
					CopyOfIterator = CurrIndirectTarget;
					++CopyOfIterator; // point to element after element that will be erased
					this->IndirectCallTargets.erase(CurrIndirectTarget);
					CurrIndirectTarget = CopyOfIterator;
				}
				else {
					++CurrIndirectTarget;
				}
			}
#if 1
			// Find calls used as jumps.
			list<SMPInstr *>::iterator InstIter = this->Instrs.begin();
			while (InstIter != this->Instrs.end()) {
				SMPInstr *CurrInst = (*InstIter);
				SMPitype InstFlow = CurrInst->GetDataFlowType();
				if ((CALL == InstFlow) || (INDIR_CALL == InstFlow)) {
					CurrInst->AnalyzeCallInst(this->FirstEA, this->FuncInfo.endEA);
				}
				++InstIter;
			}
#endif
		} // end if (FoundInternalCallTarget)
	}

	// Figure out the stack frame and related info.
#if SMP_ANALYZE_STACK_POINTER
	(void) this->AnalyzeStackPointerDeltas();
#else
	(void) this->UseIDAStackPointerDeltas();
#endif

#if SMP_DEBUG_CONTROLFLOW
	SMP_msg("SMPFunction::Analyze: set stack frame info.\n");
#endif
	if (!(this->HasSharedChunks())) {

		this->SetStackFrameInfo();

	} // end if not shared chunks
	else { // has shared chunks; still want to compute stack frame info
#ifdef SMP_DEBUG_FUNC
		SMP_msg(" %s has shared chunks \n", this->GetFuncName());
#endif
		// Figure out the stack frame and related info.
		this->SetStackFrameInfo();
	}

	this->MarkFunctionSafe();

#if SMP_COUNT_MEMORY_ALLOCATIONS
	SMPInstCount += ((unsigned long) this->Instrs.size());
	SMPBlockCount += ((unsigned long) this->Blocks.size());
	SMPLocalVarCount += ((unsigned long) this->LocalVarTable.size());
#endif

} // end of SMPFunction::AdvancedAnalysis()

// Count call targets that have not been processed.
size_t SMPFunction::UnprocessedCalleesCount(void) {
	size_t UnprocessedTargetsCount = 0;

	size_t TargetIndex;
	for (TargetIndex = 0; TargetIndex < this->AllCallTargets.size(); ++TargetIndex) {
		SMPFunction *CurrTarget = this->GetProg()->FindFunction(this->AllCallTargets.at(TargetIndex));
		if (NULL == CurrTarget) {
#if 0
			// Bad call targets are removed in AdvancedAnalysis(), which comes later.
			SMP_msg("ERROR: NULL CallTarget in UnprocessedCalleesCount() at TargetIndex %zu \n", TargetIndex);
#endif
		}
		else if (!(CurrTarget->IsFuncProcessed())) {
			++UnprocessedTargetsCount;
		}
	}
	return UnprocessedTargetsCount;
} // end of SMPFunction::UnprocessedCalleesCount()

ea_t SMPFunction::GetFirstUnprocessedCallee(void) {
	ea_t CalleeAddr = BADADDR;
	size_t TargetIndex;
	for (TargetIndex = 0; TargetIndex < this->AllCallTargets.size(); ++TargetIndex) {
		ea_t TargetAddr = this->AllCallTargets.at(TargetIndex);
		SMPFunction *CurrTarget = this->GetProg()->FindFunction(TargetAddr);
		if ((NULL != CurrTarget) && (!(CurrTarget->IsFuncProcessed()))) {
			CalleeAddr = TargetAddr;
			break;
		}
	}
	return CalleeAddr;
} // end of SMPFunction::GetFirstUnprocessedCallee()

// Is the code starting at TargetAddr a non-shared chunk that jumps back into our function?
//  If so, it can be incorporated into our function rather than treated as a separate function.
//  This method is called only when we see a jump outside our function, and it is looking for
//  code fragments that are not really functions (i.e. don't have a stack frame, jump straight back
//  into our function after executing a few instructions, not a chunk shared among other functions).
//  These code fragments are found in the locking and unlocking code of the gcc stdlib, for example.
bool SMPFunction::FindDistantCodeFragment(ea_t TargetAddr) {
	bool PrivateFragment = false;
	func_t *TargetFunc = get_func(TargetAddr);
	if (TargetFunc) {
		// Determine if we are dealing with shared chunks.
		size_t ChunkCounter = 0;
		func_tail_iterator_t FuncTail(TargetFunc);
		for (bool ChunkOK = FuncTail.main(); ChunkOK; ChunkOK = FuncTail.next()) {
			++ChunkCounter;
		}
		if (1 < ChunkCounter) {
			SMP_msg("INFO: Code fragment at %lx is shared chunk.\n", (unsigned long) TargetAddr);
		}
		else {
			bool JumpsBackIntoCurrentFunc = false;
			bool HasReturnInstruction = false;
			bool AllocatesStackFrame = false;
		 	for (bool ChunkOK = FuncTail.main(); ChunkOK; ChunkOK = FuncTail.next()) {
				const area_t &CurrChunk = FuncTail.chunk();
				++ChunkCounter;
				// Build the instruction and block lists for the function.
				for (ea_t addr = CurrChunk.startEA; addr < CurrChunk.endEA;	addr = get_item_end(addr)) {
					flags_t InstrFlags = getFlags(addr);
					if (isHead(InstrFlags) && isCode(InstrFlags)) {
						SMPInstr *CurrInst = new SMPInstr(addr);
						// Fill in the instruction data members.
						CurrInst->Analyze();
						// Search for two negative indicators (stack allocations and returns)
						//  and one positive indicator (jump back into this function).
						if (CurrInst->MDIsReturnInstr()) {
							HasReturnInstruction = true;
							break;
						}
						else if (CurrInst->MDIsFrameAllocInstr()) {
							AllocatesStackFrame = true;
							break;
						}
						else {
							SMPitype FlowType = CurrInst->GetDataFlowType();
							if ((JUMP == FlowType) || (INDIR_JUMP == FlowType)) {
								if (CurrInst->BuildRTL()) {
									ea_t FragmentJumpTarget = CurrInst->GetJumpTarget();
									if ((FragmentJumpTarget >= this->FirstEA) && (FragmentJumpTarget <= this->FuncInfo.endEA)) {
										JumpsBackIntoCurrentFunc = true;
									}
								}
							}
						}
					} // end if isHead() and isCode()
				} // end for all addrs in chunk
			} // end for all chunks (there will only be one)
			PrivateFragment = (JumpsBackIntoCurrentFunc && (!HasReturnInstruction) && (!AllocatesStackFrame));
		} // end if (1 < ChunkCounter) ... else ...
	} // end if (TargetFunc)

	return PrivateFragment;
} // end of SMPFunction::FindDistantCodeFragment()

// Free memory that is no longer needed after loop 2 of SMPProgram::Analyze().
void SMPFunction::FreeUnusedMemory2(void) {
	size_t UnusedElements;
	size_t CurrSize;

#if 0
	// Go through vector containers and resize to current capacity, if the vector
	//  has been fully computed by the time SMPProgram:Analyze() loop 2 completes.
	CurrSize = this->DirectCallTargets.size();
	UnusedElements = this->DirectCallTargets.capacity() - CurrSize;
	if (0 < UnusedElements) {
		UnusedIntCount += (unsigned long) UnusedElements;
#if SMP_SHRINK_TO_FIT
		std::vector<ea_t>(this->DirectCallTargets).swap(this->DirectCallTargets);
#else
		this->DirectCallTargets.resize(CurrSize);
#endif
	}

	CurrSize = this->IndirectCallTargets.size();
	UnusedElements = this->IndirectCallTargets.capacity() - CurrSize;
	if (0 < UnusedElements) {
		UnusedIntCount += (unsigned long) UnusedElements;
#if SMP_SHRINK_TO_FIT
		std::vector<ea_t>(this->IndirectCallTargets).swap(this->IndirectCallTargets);
#else
		this->IndirectCallTargets.resize(CurrSize);
#endif
	}
#endif

	CurrSize = this->AllCallTargets.size();
	UnusedElements = this->AllCallTargets.capacity() - CurrSize;
	if (0 < UnusedElements) {
		UnusedIntCount += (unsigned long) UnusedElements;
#if SMP_SHRINK_TO_FIT
		std::vector<ea_t>(this->AllCallTargets).swap(this->AllCallTargets);
#else
		this->AllCallTargets.resize(CurrSize);
#endif
	}

	CurrSize = this->SavedRegLoc.size();
	UnusedElements = this->SavedRegLoc.capacity() - CurrSize;
	if (0 < UnusedElements) {
		UnusedIntCount += (unsigned long) UnusedElements;
#if SMP_SHRINK_TO_FIT
		std::vector<int>(this->SavedRegLoc).swap(this->SavedRegLoc);
#else
		this->SavedRegLoc.resize(CurrSize);
#endif
	}

	CurrSize = this->RPOBlocks.size();
	UnusedElements = this->RPOBlocks.capacity() - CurrSize;
	if (0 < UnusedElements) {
		list<SMPBasicBlock *>::iterator DummyIter = this->Blocks.end();
		UnusedIntCount += (unsigned long) UnusedElements;
#if SMP_SHRINK_TO_FIT
		std::vector<SMPBasicBlock *>(this->RPOBlocks).swap(this->RPOBlocks);
#else
		this->RPOBlocks.resize(CurrSize, DummyIter);
#endif
	}

	CurrSize = this->LocalVarTable.size();
	UnusedElements = this->LocalVarTable.capacity() - CurrSize;
	if (0 < UnusedElements) {
		struct LocalVar DummyVar;
		DummyVar.offset = 0;
		DummyVar.size = 0;
		UnusedStructCount += (unsigned long) UnusedElements;
#if SMP_SHRINK_TO_FIT
		std::vector<struct LocalVar>(this->LocalVarTable).swap(this->LocalVarTable);
#else
		this->LocalVarTable.resize(CurrSize, DummyVar);
#endif
	}

	CurrSize = this->StackFrameMap.size();
	UnusedElements = this->StackFrameMap.capacity() - CurrSize;
	if (0 < UnusedElements) {
		struct StackFrameEntry DummyEntry;
		DummyEntry.offset = 0;
		DummyEntry.VarPtr = NULL;
		UnusedStructCount += (unsigned long) UnusedElements;
#if SMP_SHRINK_TO_FIT
		std::vector<struct StackFrameEntry>(this->StackFrameMap).swap(this->StackFrameMap);
#else
		this->StackFrameMap.resize(CurrSize, DummyEntry);
#endif
	}

	CurrSize = this->FineGrainedStackTable.size();
	UnusedElements = this->FineGrainedStackTable.capacity() - CurrSize;
	if (0 < UnusedElements) {
		struct FineGrainedInfo DummyFG;
		DummyFG.SignMiscInfo = 0;
		DummyFG.SizeInfo = 0;
		UnusedStructCount += (unsigned long) UnusedElements;
#if SMP_SHRINK_TO_FIT
		std::vector<struct FineGrainedInfo>(this->FineGrainedStackTable).swap(this->FineGrainedStackTable);
#else
		this->FineGrainedStackTable.resize(CurrSize, DummyFG);
#endif
	}

	return;
} // end of SMPFunction::FreeUnusedMemory2()

// Free memory that is no longer needed after loop 3 of SMPProgram::Analyze().
void SMPFunction::FreeUnusedMemory3(void) {
	size_t UnusedElements;
	size_t CurrSize;

	// Go through vector containers and resize to current capacity, if the vector
	//  has been fully computed by the time SMPProgram:Analyze() loop 2 completes.
	CurrSize = this->ReturnRegTypes.size();
	UnusedElements = this->ReturnRegTypes.capacity() - CurrSize;
	if (0 < UnusedElements) {
		UnusedIntCount += (unsigned long) UnusedElements;
#if SMP_SHRINK_TO_FIT
		std::vector<SMPOperandType>(this->ReturnRegTypes).swap(this->ReturnRegTypes);
#else		
		this->ReturnRegTypes.resize(CurrSize);
#endif
	}

	return;
} // end of SMPFunction::FreeUnusedMemory3()

// Free memory that is no longer needed after type inference (loop 4 of SMPProgram::Analyze()).
void SMPFunction::FreeUnusedMemory4(void) {
	this->KillSet.clear();
	this->LiveOutSet.clear();
	this->LiveInSet.clear();
	this->StackFrameMap.clear();
	this->BlocksDefinedIn.clear();

#if SMP_SHRINK_TO_FIT
	std::set<op_t, LessOp>(this->KillSet).swap(this->KillSet);
	std::set<op_t, LessOp>(this->LiveOutSet).swap(this->LiveOutSet);
	std::set<op_t, LessOp>(this->LiveInSet).swap(this->LiveInSet);
#endif

	list<SMPBasicBlock *>::iterator BlockIter;
	for (BlockIter = this->Blocks.begin(); BlockIter != this->Blocks.end(); ++BlockIter) {
		(*BlockIter)->FreeUnusedMemory4();
	}
	return;
} // end of SMPFunction::FreeUnusedMemory4()

// Free SSA data structures that are no longer needed when all SSA numbers have
//  been recorded in DEFs and USEs.
void SMPFunction::FreeSSAMemory(void) {
	this->IDom.clear();
	this->DomTree.clear();
	this->BlocksDefinedIn.clear();
	this->SSACounter.clear();
	this->SSAStack.clear();

#if SMP_SHRINK_TO_FIT
	vector<int>(this->IDom).swap(this->IDom);
	vector<pair<int, list<int> > >(this->DomTree).swap(this->DomTree);
	vector<list<int> >(this->BlocksDefinedIn).swap(this->BlocksDefinedIn);
	vector<int>(this->SSACounter).swap(this->SSACounter);
	vector<list<int> >(this->SSAStack).swap(this->SSAStack);
#endif

	list<SMPBasicBlock *>::iterator BlockIter;
	for (BlockIter = this->Blocks.begin(); BlockIter != this->Blocks.end(); ++BlockIter) {
		(*BlockIter)->FreeSSAMemory();
	}
	return;
} // end of SMPFunction::FreeSSAMemory()

// For each instruction, mark the non-flags-reg DEFs as having live
//  metadata (mmStrata needs to fetch and track this metadata for this
//  instruction) or dead metadata (won't be used as addressing reg, won't
//  be stored to memory, won't be returned to caller).
void SMPFunction::AnalyzeMetadataLiveness(void) {
	bool changed;
	int BaseReg;
	int IndexReg;
	ushort ScaleFactor;
	ea_t offset;
	op_t BaseOp = InitOp, IndexOp = InitOp, ReturnOp = InitOp;
	BaseOp.type = o_reg;
	IndexOp.type = o_reg;
	ReturnOp.type = o_reg;
	list<SMPInstr *>::iterator InstIter;
	list<SMPInstr *>::reverse_iterator RevInstIter;
	set<DefOrUse, LessDefUse>::iterator CurrDef;
	set<DefOrUse, LessDefUse>::iterator CurrUse;
	set<DefOrUse, LessDefUse>::iterator NextUse;
	bool DebugFlag = false;
	bool UseFP = this->UsesFramePointer();
	int IterationCount = 0;

#if SMP_DEBUG_DATAFLOW
	if (0 == strcmp("uw_frame_state_for", this->GetFuncName())) {
		DebugFlag = true;
	}
#endif

	do {
		changed = false;
		++IterationCount;
		bool SafeMemDest;
		if (DebugFlag) {
			SMP_msg("AnalyzeMetadataLiveness iteration count: %d \n", IterationCount);
		}
		for (RevInstIter = this->Instrs.rbegin(); RevInstIter != this->Instrs.rend(); ++RevInstIter) {
			SMPInstr *CurrInst = (*RevInstIter);
			ea_t InstAddr = CurrInst->GetAddr();
			SafeMemDest = false;  // true for some SafeFunc instructions
			// Skip the SSA marker instruction.
			if (NN_fnop == CurrInst->GetCmd().itype)
				continue;

			if (DebugFlag) {
				SMP_msg("Inst addr: %lx \n", (unsigned long) CurrInst->GetAddr());
			}
			CurrDef = CurrInst->GetFirstDef();
			while (CurrDef != CurrInst->GetLastDef()) {
				if (DEF_METADATA_UNANALYZED == CurrDef->GetMetadataStatus()) {
					op_t DefOp = CurrDef->GetOp();
					// Handle special registers never used as address regs.
					if (DefOp.is_reg(X86_FLAGS_REG)
						|| ((o_trreg <= DefOp.type) && (o_xmmreg >= DefOp.type))) {
						CurrDef = CurrInst->SetDefMetadata(DefOp,
							DEF_METADATA_UNUSED);
						changed = true;
					}
					else if (MDIsStackOrFramePointerReg(DefOp, UseFP)) {
						// Stack pointer register DEFs always have live
						//  metadata, but we don't need to propagate back
						//  through particular DEF-USE chains.
						CurrDef = CurrInst->SetDefMetadata(DefOp, DEF_METADATA_USED);
						changed = true;
					}
					else if ((o_mem <= DefOp.type) && (o_displ >= DefOp.type)) {
						// DEF is a memory operand. The addressing registers
						//  therefore have live metadata, and the memory metadata is live.
						// EXCEPTION: If the function is Safe, then direct stack writes
						//  to local variables (above the outgoing args area of the frame)
						//  are not live metadata, and there will be no indirect local frame
						//  writes, by definition of "safe." So, for safe funcs, only
						//  the o_mem (globals) and indirect writes are live metadata.
						if (this->SafeFunc && MDIsStackAccessOpnd(DefOp, this->UseFP)
							&& (!this->WritesAboveLocalFrame(DefOp, CurrInst->AreDefsNormalized()))
							&& (!this->IsInOutgoingArgsRegion(DefOp))) {
							++CurrDef;
							SafeMemDest = true;
							continue;
						}
						CurrDef = CurrInst->SetDefMetadata(DefOp, DEF_METADATA_USED);
						changed = true;
						MDExtractAddressFields(DefOp, BaseReg, IndexReg,
							ScaleFactor, offset);
						if (R_none != BaseReg) {
							BaseOp.reg = MDCanonicalizeSubReg((ushort) BaseReg);
							BaseOp.dtyp = CurrInst->GetOperandDtypField(); // canonical reg width
							if (MDIsStackOrFramePointerReg(BaseOp, UseFP)) {
								; // do nothing; DEF handled by case above
							}
							else {
								CurrUse = CurrInst->FindUse(BaseOp);
								if (CurrUse == CurrInst->GetLastUse()) {
									SMP_msg("FATAL ERROR: BaseReg %d not in USE list at %lx for %s\n",
										BaseOp.reg, (unsigned long) CurrInst->GetAddr(),
										CurrInst->GetDisasm());
								}
								assert(CurrUse != CurrInst->GetLastUse());
								if (this->IsGlobalName(BaseOp)) {
									changed |= this->PropagateGlobalMetadata(BaseOp,
										DEF_METADATA_USED, CurrUse->GetSSANum(), InstAddr);
								}
								else {
									changed |= CurrInst->GetBlock()->PropagateLocalMetadata(BaseOp,
										DEF_METADATA_USED, CurrUse->GetSSANum(), InstAddr);
								}
							}
						} // end if R_none != BaseReg
						if (R_none != IndexReg) {
							IndexOp.reg = MDCanonicalizeSubReg((ushort) IndexReg);
							IndexOp.dtyp = CurrInst->GetOperandDtypField(); // canonical reg width
							if (MDIsStackOrFramePointerReg(IndexOp, UseFP)) {
								; // do nothing; DEF handled by case above
							}
							else {
								CurrUse = CurrInst->FindUse(IndexOp);
								if (CurrUse == CurrInst->GetLastUse()) {
									SMP_msg("FATAL ERROR: IndexReg %d not in USE list at %lx for %s\n",
										IndexOp.reg, (unsigned long) CurrInst->GetAddr(),
										CurrInst->GetDisasm());
								}
								assert(CurrUse != CurrInst->GetLastUse());
								if (0 != ScaleFactor) {
									; // mmStrata knows scaled reg is NUMERIC
									// ... its metadata is not fetched
								}
								else if (this->IsGlobalName(IndexOp)) {
									changed |= this->PropagateGlobalMetadata(IndexOp,
										DEF_METADATA_USED, CurrUse->GetSSANum(), InstAddr);
								}
								else {
									changed |= CurrInst->GetBlock()->PropagateLocalMetadata(IndexOp,
										DEF_METADATA_USED, CurrUse->GetSSANum(), InstAddr);
								}
							}
						} // end if R_none != IndexReg
					} // end if X86_FLAGS_REG .. else if stack ptr ... 
				} // end if unanalyzed metadata usage
				++CurrDef;
			} // end while processing DEFs
			if ((RETURN == CurrInst->GetDataFlowType())
				|| (CurrInst->IsTailCall())   // quasi-return
				|| (CALL == CurrInst->GetDataFlowType())
				|| (INDIR_CALL == CurrInst->GetDataFlowType())) {
				// The EAX and EDX registers can be returned to the caller,
				//  which might use their metadata. They show up as USEs
				//  of the return instruction. Some library functions
				//  pass return values in non-standard ways. e.g. through
				//  EBX or EDI, so we treat all return regs the same.
				// For CALL instructions, values can be passed in caller-saved
				//  registers, unfortunately, so the metadata is live-in.
				CurrUse = CurrInst->GetFirstUse();
				while (CurrUse != CurrInst->GetLastUse()) {
					NextUse = CurrUse;
					++NextUse;
					ReturnOp = CurrUse->GetOp();
					if (DebugFlag) {
						SMP_msg("ReturnOp: ");
						PrintOperand(ReturnOp);
						SMP_msg("\n");
					}
					if ((o_reg == ReturnOp.type) &&
						(!MDIsStackOrFramePointerReg(ReturnOp, UseFP)) &&
						(!ReturnOp.is_reg(X86_FLAGS_REG))) {
						if (this->IsGlobalName(ReturnOp)) {
							changed |= this->PropagateGlobalMetadata(ReturnOp,
									DEF_METADATA_USED, CurrUse->GetSSANum(), InstAddr);
						}
						else {
							changed |= CurrInst->GetBlock()->PropagateLocalMetadata(ReturnOp,
									DEF_METADATA_USED, CurrUse->GetSSANum(), InstAddr);
						}
					}
					CurrUse = NextUse;
				} // end while all USEs
			} // end if return or call
			else if (CurrInst->HasDestMemoryOperand() 
				|| CurrInst->MDIsPushInstr()) {
				// Memory writes cause a lot of metadata usage.
				//  Addressing registers in the memory destination
				//  have live metadata used in bounds checking. The
				//  register being stored to memory could end up being
				//  used in some other bounds checking, unless we 
				//  have precise memory tracking and know that it
				//  won't.
				// We handled the addressing registers above, so we
				//  handle the register written to memory here.
				// The same exception applies as above: If the destination
				//  memory operand is not a stack write, then safe functions
				//  do not need to track the metadata.
				// If we push a register and have callees, the metadata could
				//  be live, if the callee gets its incoming args from our push
				//  instructions.
				if (SafeMemDest && !(CurrInst->MDIsPushInstr() && !this->IsLeaf())) {
					continue;  // go to next instruction
				}
				CurrUse = CurrInst->GetFirstUse();
				while (CurrUse != CurrInst->GetLastUse()) {
					NextUse = CurrUse;
					++NextUse;
					op_t UseOp = CurrUse->GetOp();
					// NOTE: **!!** To be less conservative, we
					//  should propagate less for exchange category
					//  instructions.
					if ((UseOp.type == o_reg) && (!MDIsStackOrFramePointerReg(UseOp, UseFP)) && (!UseOp.is_reg(X86_FLAGS_REG))) {
						if (this->IsGlobalName(UseOp)) {
							changed |= this->PropagateGlobalMetadata(UseOp,
									DEF_METADATA_USED, CurrUse->GetSSANum(), InstAddr);
						}
						else {
							changed |= CurrInst->GetBlock()->PropagateLocalMetadata(UseOp,
									DEF_METADATA_USED, CurrUse->GetSSANum(), InstAddr);
						}
					} // end if register
					CurrUse = NextUse;
				} // end while all USEs
			} // end if call or return else if memdest ...
		} // end for all instructions
	} while (changed);

	// All DEFs that still have status DEF_METADATA_UNANALYZED can now
	//  be marked as DEF_METADATA_UNUSED.
	for (InstIter = this->Instrs.begin(); InstIter != this->Instrs.end(); ++InstIter) {
		SMPInstr *CurrInst = (*InstIter);
		if (NN_fnop == CurrInst->GetCmd().itype)
			continue;
		CurrDef = CurrInst->GetFirstDef();
		while (CurrDef != CurrInst->GetLastDef()) {
			if (DEF_METADATA_UNANALYZED == CurrDef->GetMetadataStatus()) {
				CurrDef = CurrInst->SetDefMetadata(CurrDef->GetOp(),
					DEF_METADATA_UNUSED);
				assert(CurrDef != CurrInst->GetLastDef());
			}
			++CurrDef;
		}
	}

	return;
} // end of SMPFunction::AnalyzeMetadataLiveness() 

// Propagate the metadata Status for UseOp/SSANum to its global DEF.
// Return true if successful.
bool SMPFunction::PropagateGlobalMetadata(op_t UseOp, SMPMetadataType Status, int SSANum, ea_t UseAddr) {
	bool changed = false;
	bool UseFP = this->UsesFramePointer();

	if ((0 > SSANum) || (o_void == UseOp.type) || (!MDIsDataFlowOpnd(UseOp, UseFP)) || MDIsIndirectMemoryOpnd(UseOp, UseFP))
		return false;

	// Find the DEF of UseOp with SSANum.
	ea_t DefAddr;
	SMPBasicBlock *UseBlock;
	SMPBasicBlock *DefBlock;

	if (UseAddr > this->GetNumBlocks()) { // UseAddr is an inst addr
		UseBlock = this->GetBlockFromInstAddr(UseAddr);
	}
	else { // UseAddr is a block number
		UseBlock = this->GetBlockByNum((size_t) UseAddr);
	}

	DefAddr = UseBlock->GetUltimateDefAddr(UseOp, UseAddr, SSANum, false);

	if (BADADDR == DefAddr) {
		return changed;
	}

	if (DefAddr > this->GetNumBlocks()) { // found a DEF inst.
		SMPInstr *CurrInst = this->GetInstFromAddr(DefAddr);
		ea_t InstAddr = DefAddr;
		DefBlock = this->GetBlockFromInstAddr(DefAddr);
		set<DefOrUse, LessDefUse>::iterator CurrDef;
		set<DefOrUse, LessDefUse>::iterator CurrUse;
		CurrDef = CurrInst->FindDef(UseOp);
		assert(CurrDef != CurrInst->GetLastDef());
		assert(SSANum == CurrDef->GetSSANum());
		if (Status != CurrDef->GetMetadataStatus()) {
			CurrDef = CurrInst->SetDefMetadata(UseOp, Status);
			changed = (CurrDef != CurrInst->GetLastDef());
			bool PropThroughUses = changed;

			// If source operand was memory, we have two cases.
			//  (1) The instruction could be a load, in which
			//  case we should simply terminate the
			//  propagation, because the prior DEF of a memory
			//  location is always considered live metadata
			//  already, and we do not want to propagate liveness
			//  to the address regs in the USE list.
			//  EXCEPTION: For safe funcs, we propagate liveness
			//   for stack locations.
			//  (2) We could have an arithmetic operation such
			//  as reg := reg arithop memsrc. In this case, we
			//  still do not want to propagate through the memsrc,
			//  (with the same safe func EXCEPTION),
			//  but the register is both DEF and USE and we need
			//  to propagate through the register.
			if (CurrInst->HasSourceMemoryOperand()) {
				if (this->SafeFunc) {
					op_t MemSrcOp = CurrInst->MDGetMemUseOp();
					assert(o_void != MemSrcOp.type);
					if (MDIsDirectStackAccessOpnd(MemSrcOp, this->UseFP)) {
						// We have a SafeFunc stack access. This is
						//  the EXCEPTION case where we want to
						//  propagate metadata liveness for a memory
						//  location.
						CurrUse = CurrInst->FindUse(MemSrcOp);
						assert(CurrUse != CurrInst->GetLastUse());
						if (this->IsGlobalName(MemSrcOp)) {
							changed |= this->PropagateGlobalMetadata(MemSrcOp,
								Status, CurrUse->GetSSANum(), InstAddr);
						}
						else {
							changed |= CurrInst->GetBlock()->PropagateLocalMetadata(MemSrcOp,
								Status, CurrUse->GetSSANum(), InstAddr);
						}
					} // end if stack access operand
				} // end if SafeFunc
				if (3 == CurrInst->GetOptType()) { // move inst
					PropThroughUses = false; // load address regs are not live metadata
				}
				else if ((5 == CurrInst->GetOptType())
					|| (NN_and == CurrInst->GetCmd().itype)
					|| (NN_or == CurrInst->GetCmd().itype)
					|| (NN_xor == CurrInst->GetCmd().itype)) {
					// add, subtract, and, or with memsrc
					// Find the DEF reg in the USE list.
					CurrUse = CurrInst->FindUse(UseOp);
					assert(CurrUse != CurrInst->GetLastUse());
					changed |= this->PropagateGlobalMetadata(UseOp,
						Status, CurrUse->GetSSANum(), InstAddr);
					PropThroughUses = false;
				}
			} // end if memory source

			// Now, propagate the metadata status to all the
			//  non-memory, non-flags-reg, non-special-reg 
			//  (i.e. regular registers) USEs.
			if (PropThroughUses) {
				CurrUse = CurrInst->GetFirstUse();
				while (CurrUse != CurrInst->GetLastUse()) {
					op_t CurrUseOp = CurrUse->GetOp();
					// NOTE: **!!** To be less conservative, we
					//  should propagate less for exchange category
					//  instructions.
					if ((CurrUseOp.type == o_reg) && (!MDIsStackOrFramePointerReg(CurrUseOp, UseFP))
						&& (!CurrUseOp.is_reg(X86_FLAGS_REG))) {

						if (this->IsGlobalName(CurrUseOp)) {
							changed |= this->PropagateGlobalMetadata(CurrUseOp,
								Status, CurrUse->GetSSANum(), InstAddr);
						}
						else {
							changed |= CurrInst->GetBlock()->PropagateLocalMetadata(CurrUseOp,
								Status, CurrUse->GetSSANum(), InstAddr);
						}
					}
					++CurrUse;
				} // end while all USEs
			}
		}
	}

	else { // Found a DEF block number in DefAddr.
		// Check the Phi functions
		DefBlock = this->GetBlockByNum((size_t) DefAddr);
		set<SMPPhiFunction, LessPhi>::iterator DefPhi;
		DefPhi = DefBlock->FindPhi(UseOp);
		assert(DefPhi != DefBlock->GetLastPhi());
		assert(SSANum == DefPhi->GetDefSSANum());
		if (Status != DefPhi->GetDefMetadata()) {
			DefPhi = DefBlock->SetPhiDefMetadata(UseOp, Status);
			changed = true;
			// If the Phi DEF has live metadata, then the Phi
			//  USEs each have live metadata. Propagate.
			int UseSSANum;
			for (size_t index = 0; index < DefPhi->GetPhiListSize(); ++index) {
				UseSSANum = DefPhi->GetUseSSANum(index);
				// UseSSANum can be -1 in some cases because
				//  we conservatively make EAX and EDX be USEs
				//  of all return instructions, when the function
				//  might have a void return type, making it
				//  appear as if an uninitialized EAX or EDX
				//  could make it to the return block.
				if (0 <= UseSSANum) {
					changed |= this->PropagateGlobalMetadata(UseOp,	Status, UseSSANum, DefAddr);
				}
			}
		}

	} // end if (DefAddr is inst addr) else ... [DefAddr is block number]

	return changed;
} // end of SMPFunction::PropagateGlobalMetadata()

// Find consecutive DEFs of the same type and mark the second one redundant.
void SMPFunction::FindRedundantMetadata(void) {
	list<SMPBasicBlock *>::iterator BlockIter;
	SMPBasicBlock *CurrBlock;
	bool changed = false;

	for (BlockIter = this->Blocks.begin(); BlockIter != this->Blocks.end(); ++BlockIter) {
		CurrBlock = (*BlockIter);
		changed |= CurrBlock->FindRedundantLocalMetadata(this->SafeFunc);
	}
	return;
} // end of SMPFunction::FindRedundantMetadata()

// Perform SCCP to find constant values for DEFs, store in this->ConstantDefs
void SMPFunction::SparseConditionalConstantPropagation(void) {
	// We perform the SCCP (Sparse Conditional Constant Propagation) algorithm
	//  as found in Cooper & Torczon, "Engineering a Compiler."

	// CFGWorkList := { all edges from pseudo-entry block to entry blocks }
	//  We do not have a pseudo-entry block, so we special case by starting processing at
	//  the first basic block, block number 0, which is our entry block.
	list<pair<int, int> > CFGWorkList; // edges from pair.first = source block number to pair.second = dest block number
	pair<int, int> InitEdge(-1, 0); // -1 is pseudo-block-number
	CFGWorkList.push_back(InitEdge);
	size_t BlockNumLimit = this->Blocks.size();
	vector<STARSBitSet> ExecutedEdgeBitSet(BlockNumLimit); // records which edges have been executed in SCCP; row = DestBlockNum, col (bit) = SrcBlockNum

	// for each edge e in the CFG
	//  mark e as unexecuted
	for (size_t EdgeIndex = 0; EdgeIndex < BlockNumLimit; ++EdgeIndex) {
		ExecutedEdgeBitSet[EdgeIndex].AllocateBits(BlockNumLimit); // allocate and zero all bits
	}
	this->ResetSCCPVisitedBlocks();  // records which blocks have been visited in SCCP algorithm

	// SSAWorkList := { empty set }
	list<pair<int, int> > SSAWorkList; // pair.first = block number, pair.second = name+SSA hash
	SSAWorkList.clear();

	// for each ref def x in the procedure
	//   Value(x) = TOP
	//  We currently implement this by having this->ConstantDefs contain no entry for defs with value TOP

	// while ((CFGWorkList is not empty) or (SSAWorkList is not empty))
	while (!(CFGWorkList.empty() && SSAWorkList.empty())) {

	//   if (CFGWorkList is not empty) then
	//       remove an edge e = (m, n) from the CFGWorkList
	//       if (e is marked as unexecuted) then
	//          mark e as executed
	//          EvaluateAllPhisInBlock(n)
	//          if (e is only edge into n marked as executed) then
	//              for (each instruction i in block n) do
	//                  if (i is an assignment) then
	//                      EvaluateAssign(i)
	//                  else if (i is a conditional branch) then
	//                      EvaluateConditional(i)
	//                  endif
	//              endfor
	//              Put block successors on CFGWorkList, based on conditional branch evaluation if any
	//          endif
	//       endif
	//   endif

	//   if (CFGWorkList is not empty) then
		if (!(CFGWorkList.empty())) {
	//       remove an edge e = (m, n) from the CFGWorkList
			pair<int, int> CurrentEdge = CFGWorkList.front();
			CFGWorkList.pop_front();
	//       if (e is marked as unexecuted) then
			int SrcBlockNum = CurrentEdge.first;
			int DestBlockNum = CurrentEdge.second;
			bool UnexecutedEdge = (0 > CurrentEdge.first);
			if (!UnexecutedEdge) {
				UnexecutedEdge = (!ExecutedEdgeBitSet.at((size_t) DestBlockNum).GetBit((size_t) SrcBlockNum));
			}
			if (UnexecutedEdge) {
	//          mark e as executed
				if (0 <= SrcBlockNum) {
					ExecutedEdgeBitSet.at((size_t) DestBlockNum).SetBit((size_t) SrcBlockNum);
				}
	//          EvaluateAllPhisInBlock(n)
				this->EvaluateAllPhiConstants(DestBlockNum, ExecutedEdgeBitSet, SSAWorkList);
	//          if (e is only edge into n marked as executed) then
				SMPBasicBlock *CurrBlock = this->GetBlockByNum(DestBlockNum);
				if (!(CurrBlock->IsSCCPVisited())) {
	//              for (each instruction i in block n) do
	//                  if (i is an assignment) then
	//                      EvaluateAssign(i)
	//                  else if (i is a conditional branch) then
	//                      EvaluateConditional(i)
	//                  endif
	//              endfor
					enum STARSBranchConst BranchEval = STARS_BRANCH_UNKNOWN;
					CurrBlock->SCCPEvaluateConstants(BranchEval, CFGWorkList, SSAWorkList); // also marks block as SCCP visited
	//          endif
				}
	//       endif
			}
	//   endif
		}


	//
	//   if (SSAWorkList is not empty) then
	//       remove an edge e = (s, d) from SSAWorkList
	//       c := CFG node that uses d
	//       if (any edge entering c is marked as executable) then
	//           if (d is a phi function argument) then
	//               EvaluatePhi(d)
	//           else
	//              for (each instruction i in block c) do
	//                  if (i is an assignment that uses d) then
	//                      EvaluateAssign(i)
	//                  else if (i is a conditional branch that uses d) then
	//                      EvaluateConditional(i)
	//                  endif
	//              endfor
	//           endif
	//       endif
	//   endif

	//   if (SSAWorkList is not empty) then
		if (!(SSAWorkList.empty())) {
	//       remove an edge e = (s, d) from SSAWorkList
			pair<int, int> SSAEdge = SSAWorkList.front();
			SSAWorkList.pop_front();
			int BlockNum = SSAEdge.first;
			int DefHashValue = SSAEdge.second;
	//       c := CFG node that uses d
			assert(0 <= BlockNum);
			SMPBasicBlock *CurrBlock = this->GetBlockByNum((size_t) BlockNum);
			op_t DefOp = InitOp;
			DefOp.type = o_reg;
			DefOp.reg = (DefHashValue & 0x0000ffff);
			int DefSSANum = ((DefHashValue & 0x7fff0000) >> 16);
			bool LocalName = CurrBlock->IsLocalName(DefOp);
	//       if (any edge entering c is marked as executable) then
	//           if (d is a phi function argument) then
	//               EvaluatePhi(d)
	//           else
	//              for (each instruction i in block c) do
	//                  if (i is an assignment that uses d) then
	//                      EvaluateAssign(i)
	//                  else if (i is a conditional branch that uses d) then
	//                      EvaluateConditional(i)
	//                  endif
	//              endfor
	//           endif
	//       endif
			assert(CurrBlock->IsSCCPVisited()); // a local name is only added to SSAWorkList from within the block
			vector<SMPInstr *>::iterator InstIter;
			bool FoundReDEF = false;
			for (InstIter = CurrBlock->GetFirstInst(); InstIter != CurrBlock->GetLastInst(); ++InstIter) {
				SMPInstr *CurrInst = (*InstIter);
				set<DefOrUse, LessDefUse>::iterator UseIter = CurrInst->FindUse(DefOp);
				if (UseIter != CurrInst->GetLastUse()) { // operand is USEd; check SSANum
					int UseSSANum = UseIter->GetSSANum();
					if (UseSSANum == DefSSANum) {
						SMPitype DataFlowType = CurrInst->GetDataFlowType();
						if (DEFAULT == DataFlowType) {
							CurrInst->SCCPEvaluateAssignment(SSAWorkList);
						}
						else if (COND_BRANCH == DataFlowType) {
							enum STARSBranchConst BranchEval;
							CurrInst->SCCPEvaluateCondBranch(BranchEval);
							CurrBlock->SCCPHandleSuccessors(BranchEval, CFGWorkList);
						}
					}
				}
				set<DefOrUse, LessDefUse>::iterator DefIter = CurrInst->FindDef(DefOp);
				if (DefIter != CurrInst->GetLastDef()) { // check for re-DEF
					int NewDefSSANum = DefIter->GetSSANum();
					if (NewDefSSANum > DefSSANum) { // re-DEF; we can stop searching for USEs of DefOp/DefSSANum in this block
						FoundReDEF = true;
						break;
					}
				}
			} // end for all insts in block
			// See if we need to search for other blocks that use DefOp/DefSSANum
			if (!(LocalName || FoundReDEF)) { // we have global name that is not redefined
				list<SMPBasicBlock *>::iterator SuccIter;
				for (SuccIter = CurrBlock->GetFirstSucc(); SuccIter != CurrBlock->GetLastSucc(); ++SuccIter) {
					SMPBasicBlock *SuccBlock = (*SuccIter);
					if (SuccBlock->IsSCCPVisited() && SuccBlock->IsLiveIn(DefOp)) {
						this->ResetProcessedBlocks();
						SuccBlock->SCCPGlobalPropagationHelper(DefOp, DefSSANum, ExecutedEdgeBitSet, CFGWorkList, SSAWorkList);
					}
				}
			}
	//   endif
		}
#if 0
		SSAWorkList.clear(); // temporary stub
#endif
	// endwhile
	}

	// Go back over the basic blocks and detect never-visited blocks. Label these as unreachable.
	list<SMPBasicBlock *>::iterator BlockIter;
	bool UnreachableBlocksFound = false;
	for (BlockIter = this->Blocks.begin(); BlockIter != this->Blocks.end(); ++BlockIter) {
		SMPBasicBlock *CurrBlock = (*BlockIter);
		if (!(CurrBlock->IsSCCPVisited())) {
			UnreachableBlocksFound = true;
			CurrBlock->SetUnreachableBlock(true);
#if STARS_DEBUG_SCCP
			ea_t BlockAddr = CurrBlock->GetFirstAddr();
			SMP_msg("INFO: SCCP found unreachable block at %lx\n", (unsigned long) BlockAddr);
#endif
#if STARS_SCCP_CONVERT_UNREACHABLE_BLOCKS
			CurrBlock->SCCPNullifyUnreachableBlock();
#endif
		}
#if STARS_SCCP_GATHER_STATISTICS
		else if (CurrBlock->HasCallInstruction()) {
			CurrBlock->SCCPGatherStatistics();
		}
#endif
	}

	return;
} // end of SMPFunction::SparseConditionalConstantPropagation() 


// part of SCCP processing; propagate const DEFs into Phi USEs and Phi DEFs
void SMPFunction::EvaluateAllPhiConstants(int BlockNum, vector<STARSBitSet> ExecutedEdgeBitSet, list<pair<int, int> > &SSAWorkList) {
	// For all Phi DEFs of the type we are tracking for const values:
	//   If Phi DEF const value is not already the lattice bottom value:
	//     Accumulate const DEF values only for Phi USEs that correspond to incoming
	//      edges that are executed.
	//     If we have a consistent const value, set Phi DEF const value to it; if
	//      we have conflicting const values, set Phi DEF const value to type lattice bottom.
	//     If we set the Phi DEF const value to a new value, then propagate along SSA edges.

	// For all Phi DEFs of the type we are tracking for const values:
	SMPBasicBlock *CurrBlock = this->GetBlockByNum(BlockNum);
	set<SMPPhiFunction, LessPhi>::iterator PhiIter;
	for (PhiIter = CurrBlock->GetFirstPhi(); PhiIter != CurrBlock->GetLastPhi(); ++PhiIter) {
		op_t PhiOp = PhiIter->GetAnyOp();
		if (!(o_reg == PhiOp.type))   // !!!!****!!!! Add stack locations also in safe functions
			continue;
		int DefSSANum = PhiIter->GetDefSSANum();
		int DefHashValue = HashGlobalNameAndSSA(PhiOp, DefSSANum);
	//   If Phi DEF const value is not already the lattice bottom value:
		map<int, struct STARS_SCCP_Const_Struct>::iterator ConstIter = this->FindConstValue(DefHashValue);
		STARSConstantValueType DefConstValType = STARS_CONST_TOP; // default; no entry in map
		if (ConstIter != this->GetLastConstValueIter()) { // found entry in map
			DefConstValType = ConstIter->second.ConstType;
		}
		if (DefConstValType != STARS_CONST_BOTTOM) {
	//     Accumulate const DEF values only for Phi USEs that correspond to incoming
	//      edges that are executed.
			uval_t ConstUseVal;
			bool ConstUseValueSeen = false;
			list<SMPBasicBlock *>::iterator PredIter;
			size_t PredIndex = 0;
			STARSConstantValueType DefFinalConstValType = DefConstValType;
			for (PredIter = CurrBlock->GetFirstPred(); PredIter != CurrBlock->GetLastPred(); ++PredIter) {
				int IncomingBlockNum = (*PredIter)->GetNumber();
				bool ExecutedIncomingEdge = ExecutedEdgeBitSet.at(BlockNum).GetBit(IncomingBlockNum);
				if (ExecutedIncomingEdge) {
					int UseSSANum = PhiIter->GetUseSSANum(PredIndex);
					int UseHashValue = HashGlobalNameAndSSA(PhiOp, UseSSANum);
	//     If we have a consistent const value, set Phi DEF const value to it; if
	//      we have conflicting const values, set Phi DEF const value to type lattice bottom.
					ConstIter = this->FindConstValue(UseHashValue);
					STARSConstantValueType UseConstValType = STARS_CONST_TOP; // default; no entry in map
					if (ConstIter != this->GetLastConstValueIter()) { // found entry in map
						UseConstValType = ConstIter->second.ConstType;
					}
					if (UseConstValType == STARS_CONST_HAS_VALUE) {
						if (ConstUseValueSeen) { // check for consistency of values
							if (ConstUseVal != ConstIter->second.ConstValue) { // inconsistent const values
								DefFinalConstValType = STARS_CONST_BOTTOM;
								break; // no need to see more Phi USEs
							}
						}
						else { // this is the first const value we have seen
							DefFinalConstValType = STARS_CONST_HAS_VALUE; // so far, anyway
							ConstUseValueSeen = true;
							ConstUseVal = ConstIter->second.ConstValue; // only value seen so far
						}
					}
					else if (UseConstValType == STARS_CONST_BOTTOM) {
						// Any BOTTOM value in a USE makes the DEF also become BOTTOM.
						DefFinalConstValType =  STARS_CONST_BOTTOM;
						break; // no need to see more Phi USEs
					}
					// else must be STARS_CONST_TOP, which is a don't-care case
				} // end if (ExecutedIncomingEdge)
				++PredIndex; // keep index in sync with PredIter
			} // end for PredIter iteration through predecessor blocks

	//     If we set the Phi DEF const value to a new value, then propagate along SSA edges.
			if (DefFinalConstValType != DefConstValType) { // const entry is changing
				struct STARS_SCCP_Const_Struct NewConstEntry;
				NewConstEntry.ConstType = DefFinalConstValType;
				NewConstEntry.ConstValue = ConstUseVal;
				if (DefConstValType == STARS_CONST_TOP) { // there was no old map entry; insert new one
					pair<int, struct STARS_SCCP_Const_Struct> NewMapEntry(DefHashValue, NewConstEntry);
					pair<map<int, struct STARS_SCCP_Const_Struct>::iterator, bool> InsertResult = this->ConstantDefs.insert(NewMapEntry);
					assert(InsertResult.second);
				}
				else { // old map entry needs to be changed
					this->ConstantDefs[DefHashValue] = NewConstEntry;
				}
				// Propagate along SSA edges.
				pair<int, int> SSAEdge(BlockNum, DefHashValue);
				SSAWorkList.push_back(SSAEdge);
			} // end if entry is changing
		} // end if previous DEF value was not already BOTTOM
	} // end for all Phi functions
	return;
} // end of SMPFunction::EvaluateAllPhiConstants()

// Do we not care if DEF underflowed, due to how it is used?
bool SMPFunction::IsBenignUnderflowDEF(op_t DefOp, int DefSSANum, size_t DefAddr, int &IdiomCode) {
	bool benign = false;
	list<SMPInstr *>::iterator InstIter;
	set<DefOrUse, LessDefUse>::iterator DefIter, UseIter;
	int UseSSANum;
	SMPOperandType DefType;

	// We are looking to suppress overflow and underflow warnings on the following
	//  code sequence: PTR1-PTR2+1 gets a loop invariant code motion optimization
	//  that pulls  temp := 1-PTR2 out of the loop, and leaves temp2 := PTR1+temp
	//  inside the loop. The hoisted subtraction could underflow, and the addition
	//  that is not hoisted could overflow. The net effect of these two instructions
	//  is benign, however, so we want to suppress underflow and overflow checks on
	//  both of them, but only if we can match the pair of instructions.
	
	// We know that DefOp/DefAddr/DefSSANum refer to a subtraction instruction that
	//  produces a NEGATEDPTR result. We only need to find the paired addition instruction
	//  that USEs the same SSA name to produce a PTROFFSET result to prove that we have
	//  a case of benign underflow and overflow. If we find such a pair, we will mark
	//  both of their DEF results as benign overflows to suppress overflow checks.

	// PAINFUL: Linear search of instructions. Need to address this in the future.
	//  Perhaps we should have a map of UseHashValue to InstAddr, but that is more
	//  memory consumption. Sure would be useful, though.
	for (InstIter = this->Instrs.begin(); InstIter != this->Instrs.end(); ++InstIter) {
		SMPInstr *CurrInst = (*InstIter);
		UseIter = CurrInst->FindUse(DefOp);
		UseSSANum = UseIter->GetSSANum();
		if (UseSSANum == DefSSANum) {
			// Only remaining question: Do we produce a PTROFFSET in CurrInst? (If we do,
			//  that implies we had an addition, so we don't need to check that.)
			DefIter = CurrInst->GetFirstNonFlagsDef();
			DefType = DefIter->GetType();
			// NOTE: Make this more general. What if we just move the NEGATEDPTR into a register
			//  and then the next instruction, with different SSA name, produces the PTROFFSET?
			//  !!!!!*****!!!!!
			if (IsEqType(DefType, PTROFFSET)) {
				// Found a pair. Mark both DEFs as benign and return true.
				benign = true;
				IdiomCode = 4;
				// Note that we have two possibilities for the addition. The NEGATEDPTR could be
				//  both the DEF and a USE, e.g. add negptr,ptr1; or the NEGATEDPTR could be
				//  just a USE, e.g. add reg,negptr, so that reg is overwritten and becomes a
				//  PTROFFSET. It really does not matter. The point is that we want to ignore
				//  overflow on this addition, and also on the subtraction that produced the
				//  NEGATEDPTR, so we mark the DEF in each instruction as benignly overflowing.
				op_t UseInstDefOp = DefIter->GetOp();
				CurrInst->SetDefNoOverflow(UseInstDefOp, true);
				SMPInstr *DefInst = this->GetInstFromAddr(DefAddr);
				DefInst->SetDefNoOverflow(DefOp, true);
				break;
			}
		}
	}

	return benign;
} // end of SMPFunction::IsBenignUnderflowDEF()

bool SMPFunction::HasIntErrorCallSink(op_t DefOp, int DefSSANum, size_t DefAddr, std::string &SinkString) {
	bool FoundSink = false;

	this->ResetProcessedBlocks(); // prepare for recursion through blocks
	SinkString.clear();
	SMPBasicBlock *CurrBlock = this->GetBlockFromInstAddr(DefAddr);
	assert(CurrBlock != NULL);

	FoundSink = CurrBlock->IsCriticalSink(DefOp, DefSSANum, SinkString);

	return FoundSink;
} // end of SMPFunction::HasIntErrorCallSink()

// Compute SSA form data structures across the function.
void SMPFunction::ComputeSSA(void) {
	bool DebugFlag = false;
	bool DumpFlag = false;
#if SMP_DEBUG_DATAFLOW
	DumpFlag |= (0 == strcmp("uw_frame_state_for", this->GetFuncName()));
	DebugFlag |= (0 == strcmp("uw_frame_state_for", this->GetFuncName()));
#endif

#if 1
	if (DumpFlag)
		this->Dump();
#endif
	if (DebugFlag) SMP_msg("Computing IDoms.\n");
	this->ComputeIDoms();
	if (DebugFlag) SMP_msg("Computing Dom frontiers.\n");
	this->ComputeDomFrontiers();
	if (DebugFlag) SMP_msg("Computing global names.\n");
	this->ComputeGlobalNames();
	if (DebugFlag) SMP_msg("Computing blocks defined in.\n");
	this->ComputeBlocksDefinedIn();

	if (DebugFlag) SMP_msg("Inserting Phi functions.\n");
	this->InsertPhiFunctions();
	if (DebugFlag) SMP_msg("Building dominator tree.\n");
	this->BuildDominatorTree();
	if (DebugFlag) SMP_msg("Computing SSA renumbering.\n");
	this->SSARenumber();
	list<SMPBasicBlock *>::iterator BlockIter;
	SMPBasicBlock *CurrBlock;
	for (BlockIter = this->Blocks.begin(); BlockIter != this->Blocks.end(); ++BlockIter) {
		CurrBlock = (*BlockIter);
		if (CurrBlock->FindLoopHeadsAndTails()) {
			++this->LoopCount;
		}

		if (DumpFlag) CurrBlock->Dump();

		if (DebugFlag) SMP_msg("Computing local names.\n");
		CurrBlock->SetLocalNames();
		if (DebugFlag) SMP_msg("Computing local SSA renumbering.\n");
		CurrBlock->SSALocalRenumber();
		if (DumpFlag) CurrBlock->Dump();

#if STARS_BUILD_DEF_USE_CHAINS
		if (DebugFlag) SMP_msg("Computing global chains.\n");
		CurrBlock->CreateGlobalChains();
#endif

#if 1
		if (DebugFlag) SMP_msg("Marking dead registers.\n");
		CurrBlock->MarkDeadRegs();
#endif
	}
#if SMP_DEBUG_DATAFLOW
	if (DumpFlag)
		this->Dump();
#endif

	// Once SSA numbers have been set into all DEFs, USES, and DU-chains, then
	//  the SSA numbering data structures will no longer be used and can be
	//  de-allocated.
	this->FreeSSAMemory();
	return;
} // end of SMPFunction::ComputeSSA()

// Detect which blocks are in which loops and populate FuncLoopsByBlock data structure.
void SMPFunction::DetectLoops(void) {
	list<SMPBasicBlock *>::iterator BlockIter;
	size_t LoopNumber = 0;
	for (BlockIter = this->Blocks.begin(); BlockIter != this->Blocks.end(); ++BlockIter) {
		SMPBasicBlock *CurrBlock = (*BlockIter);
		if (CurrBlock->IsLoopTailBlock()) {
			// For each loop tail block, get its loop header block number (the target
			//  block for its back edge). Then traverse the CFG upwards, recording all
			//  of the basic block numbers that lie between the loop tail and loop head,
			//  along with the tail and head.
			this->ResetProcessedBlocks();
			int TailBlockNum = CurrBlock->GetNumber();
			int HeadBlockNum = CurrBlock->GetLoopHeaderNumber();
			assert((TailBlockNum != SMP_BLOCKNUM_UNINIT) && (HeadBlockNum != SMP_BLOCKNUM_UNINIT));
			list<list<SMPBasicBlock *>::iterator> BlockWorkList;
			BlockWorkList.push_back(BlockIter);
			SMPBasicBlock *WorkBlock;
			SMPBasicBlock *PredBlock;
			list<SMPBasicBlock *>::iterator WorkIter;
			list<SMPBasicBlock *>::iterator PredIter;
			do {
				WorkIter = BlockWorkList.front();
				BlockWorkList.pop_front();
				WorkBlock = (*WorkIter);
				int WorkBlockNum = WorkBlock->GetNumber();
				assert(WorkBlockNum != SMP_BLOCKNUM_UNINIT);
				if (!(WorkBlock->IsProcessed())) {
					this->FuncLoopsByBlock[(size_t) WorkBlockNum].SetBit(LoopNumber);
					WorkBlock->SetProcessed(true);
					// Add unprocessed predecessors to the work list until we reach the loop head.
					if (WorkBlockNum != HeadBlockNum) {
						for (PredIter = WorkBlock->GetFirstPred(); PredIter != WorkBlock->GetLastPred(); ++PredIter) {
							PredBlock = (*PredIter);
							bool AlreadyProcessed = PredBlock->IsProcessed();
							if (!AlreadyProcessed) {
								BlockWorkList.push_back(PredIter);
							}
						}
					}
				}
			} while (!BlockWorkList.empty());
			++LoopNumber;
		}
	}

	return;
} // end of SMPFunction::DetectLoops()

// Find memory writes (DEFs) with possible aliases
void SMPFunction::AliasAnalysis(void) {
	// First task: Mark which memory DEFs MIGHT be aliased because an
	//  indirect memory write occurs somewhere in the DEF-USE chain.
	//  Memory DEF-USE chains with no possible aliasing can be subjected
	//  to type inference and type-based optimizing annotations, e.g. a
	//  register spill to memory followed by retrieval from spill memory
	//  followed by NUMERIC USEs should be typed as a continuous NUMERIC
	//  chain if there is no possibility of aliasing.

	// Preparatory step: For each indirect write, mark all def-use chains
	//  (maintained at the basic block level) that include the indirect
	//  write instruction. If there are no indirect writes in the function,
	//  leave all DEFs marked as unaliased and exit.
	if (!(this->HasIndirectWrites))
		return;

	list<SMPBasicBlock *>::iterator BlockIter;
	SMPBasicBlock *CurrBlock;
	vector<SMPInstr *>::iterator BlkInstIter;
	for (BlockIter = this->Blocks.begin(); BlockIter != this->Blocks.end(); ++BlockIter) {
		CurrBlock = (*BlockIter);
		for (BlkInstIter = CurrBlock->GetFirstInst(); BlkInstIter != CurrBlock->GetLastInst(); ++BlkInstIter) {
			SMPInstr *CurrInst = (*BlkInstIter);
			if (CurrInst->HasIndirectMemoryWrite()) {
#if STARS_BUILD_DEF_USE_CHAINS
				CurrBlock->MarkIndWriteChains(CurrInst->GetAddr());
#endif
				// Until we get true aliasing analysis, any indirect write
				//  is classified as may-be-aliased.
				CurrBlock->SetMaybeAliased(true);
			}
		} // end for all insts in block
	} // end for all blocks in function

	// Step one: Find only the memory DEFs to start with.
	bool FoundIndWrite = false;
	list<SMPInstr *>::iterator InstIter;
	for (InstIter = this->Instrs.begin(); InstIter != this->Instrs.end(); ++InstIter) {
		SMPInstr *CurrInst = (*InstIter);
		ea_t InstAddr = CurrInst->GetAddr();
		if (CurrInst->HasDestMemoryOperand()) {
			// Starting with the DEF instruction, traverse the control flow
			//  until we run into (A) the re-definition of the operand, including
			//  a re-definition of any of its addressing registers, or (B) an
			//  indirect write. Return false if condition A terminates the
			//  search, and true if condition B terminates the search.
			this->ResetProcessedBlocks();
			op_t MemDefOp = CurrInst->MDGetMemDefOp();
			assert(o_void != MemDefOp.type);
			set<DefOrUse, LessDefUse>::iterator CurrMemDef = CurrInst->FindDef(MemDefOp);
			assert(CurrMemDef != CurrInst->GetLastDef());
			int SSANum = CurrMemDef->GetSSANum();
			FoundIndWrite = this->FindPossibleChainAlias(CurrInst, MemDefOp, SSANum);
			if (FoundIndWrite) {
				// Mark the DEF as aliased.
				CurrMemDef = CurrInst->SetDefIndWrite(CurrMemDef->GetOp(), true);
			}
		} // end if inst has dest memory operand
	} // end for all instructions

	return;
} // end of SMPFunction::AliasAnalysis()

// Does the DefOp DEF_USE chain have an indirect mem write starting at CurrInst?
bool SMPFunction::FindPossibleChainAlias(SMPInstr *CurrInst, op_t DefOp, int SSANum) {
#if 0
	bool DebugFlag = false;
	if (0 == strcmp("sdissect", this->GetFuncName())) {
		// Next line is just a good place to set a break point.
		DebugFlag = true;
	}
#endif

	// Starting with the DEF instruction, traverse the control flow
	//  until we run into (A) the re-definition of the operand, including
	//  a re-definition of any of its addressing registers, or (B) an
	//  indirect write. Return false if condition A terminates the
	//  search, and true if condition B terminates the search.
	SMPBasicBlock *CurrBlock = CurrInst->GetBlock();
	if (!(CurrBlock->IsProcessed())) {
		CurrBlock->SetProcessed(true);
	}
	else
		return false; // block already processed

	// Proceed by cases:
	ea_t DefAddr = CurrInst->GetAddr();
	set<DefOrUse, LessDefUse>::iterator UseIter;
	vector<SMPInstr *>::iterator InstIter = CurrBlock->GetInstIterFromAddr(DefAddr);
	bool IndWriteFound, ReDef;
	++InstIter;
	// Case 1: Local name. Return the IndWrite flag for the local Def-Use
	//  chain begun by CurrInst.
	bool UseAfterIndirectWrite = CurrBlock->HasUseAfterIndWrite(DefOp, InstIter, IndWriteFound, ReDef);
	bool LiveOutFlag = CurrBlock->IsLiveOut(DefOp);
	if (CurrBlock->IsLocalName(DefOp)) {
#if STARS_BUILD_DEF_USE_CHAINS
		return CurrBlock->GetLocalDUChainIndWrite(DefOp, SSANum);
#else
		return (UseAfterIndirectWrite);
#endif
	}

	// Case 2: Global name.
#if 1
	if (UseAfterIndirectWrite) {
		return true;
	}
	else if (IndWriteFound) {
		// We found an indirect write, but no USE of DefOp after it.
		//  If DefOp is LiveOut, then there is a USE of DefOp in a
		//  successor block, so DefOp can be aliased.
		return (LiveOutFlag && !ReDef);
	}
#else
	// Case 2A: If Def-Use chain within this block for this memory operand
	//  has its IndWrite flag set to true, then stop and return true.
	else if (CurrBlock->GetGlobalDUChainIndWrite(DefOp, DefAddr)) {
		return true;
	}

	// Case 2B: Else if Def-Use chain is not the last chain in this block
	//  for this operand, then there must be a later redefinition of the
	//  memory operand (with new SSA number assigned) later in this block.
	//  Because we did not fall into case 2A, we know there is no IndWrite
	//  within the current memory operand's chain, so we return false.
	else if (!CurrBlock->IsLastGlobalChain(DefOp, DefAddr)) {
		return false;
	}

	// Case 2C: Else if current memory operand is NOT LiveOut, even though
	//  this is the last def-use chain in the block, then there is no more
	//  traversing of the control flow graph to be done. The chain has ended
	//  without encountering an IndWrite, so return false.
	else if (!(CurrBlock->IsLiveOut(DefOp))) {
		return false;
	}
#endif

	// Case 2D: We have passed all previous checks, so we must have a memory
	//  operand that reaches the end of the block without encountering an
	//  IndWrite and is LiveOut. Its may-alias status will be determined by
	//  following the control flow graph for all successor blocks and examining
	//  the def-use chains in those blocks.
	list<SMPBasicBlock *>::iterator SuccBlock;
	SuccBlock = CurrBlock->GetFirstSucc();
	bool FoundAliasedWrite = false;
	if (LiveOutFlag && !ReDef) {
		do {
			if ((*SuccBlock)->IsLiveIn(DefOp)) {
				FoundAliasedWrite = this->FindChainAliasHelper(SuccBlock, DefOp);
			}
			++SuccBlock;
		} while (!FoundAliasedWrite && (SuccBlock != CurrBlock->GetLastSucc()));
	}

	return FoundAliasedWrite;
} // end of SMPFunction::FindPossibleChainAlias()

// recursive helper for global DU-chains that traverse CFG
bool SMPFunction::FindChainAliasHelper(list<SMPBasicBlock *>::iterator BlockIter, op_t DefOp) {
	bool DebugFlag = false;
	SMPBasicBlock *CurrBlock = (*BlockIter);
	if (0 == strcmp("mem2chunk_check", this->GetFuncName())) {
		// Next line is just a good place to set a break point.
		DebugFlag = true;
	}

	if (!(CurrBlock->IsProcessed())) {
		CurrBlock->SetProcessed(true);
	}
	else
		return false; // block already processed

	// The LVA sets can be used to decide whether it is possible that
	//  the incoming DU chain overlaps a may-alias write. We can express
	//  the decision making in a truth table:
	//
	//  Case #    LiveIn?   Killed?   AliasedWrite in block?  Action to take
	//  -------   -------   -------   ----------------------  --------------
	//    1          N          N                N             return false
	//    2          N          N                Y             return false
	//    3          N          Y                N             return false
	//    4          N          Y                Y             return false
	//    5          Y          N                N             recurse into successors
	//    6          Y          N                Y             return true
	//    7          Y          Y                N             return false
	//    8          Y          Y                Y             check location of aliased write
	//
	// In the last case, if there is an aliased write before the
	// incoming DEF is killed and after it is used, then the
	// incoming DU chain overlaps an aliased write, otherwise
	// it does not.


	// If not LiveIn, incoming DU chain does not run through this block
	//  at all, so return false.
	if (!(CurrBlock->IsLiveIn(DefOp)))
		return false;  // cases 1-4

	bool killed = CurrBlock->IsVarKill(DefOp);
	bool BlockHasAliasedWrite = CurrBlock->MaybeAliasedWrite();

	if (BlockHasAliasedWrite) {
		// If DefOp is LiveIn and is not killed, then any aliased
		//  write in the block overlaps the incoming DU chain.
		if (!killed) {
			return true;  // case 6
		}
		// If DefOp is LiveIn and is killed, then the location
		//  of the aliased write is the determining factor.
		else { // case 8; depends on finding indirect write, then USE, before re-DEF.
			vector<SMPInstr *>::iterator InstIter = CurrBlock->GetFirstInst();
			bool IndWriteFound, ReDef;
			return CurrBlock->HasUseAfterIndWrite(DefOp, InstIter, IndWriteFound, ReDef);
		}
	}
	else {
		// If killed, no aliased write, then cannot overlap an aliased write.
		if (killed)
			return false; // case 7
		else {
			// Need to recurse into all successors, because we passed through
			//  the block without seeing an aliased write and without killing
			//  the DefOp.
			list<SMPBasicBlock *>::iterator SuccBlock;
			SuccBlock = CurrBlock->GetFirstSucc();
			bool FoundAliasedWrite = false;
			while (!FoundAliasedWrite && (SuccBlock != CurrBlock->GetLastSucc())) {
				FoundAliasedWrite = this->FindChainAliasHelper(SuccBlock, DefOp);
				++SuccBlock;
			};

			if (DebugFlag) {
				SMP_msg("FindChainAliasHelper is returning %d\n", FoundAliasedWrite);
			}
			return FoundAliasedWrite;
		}
	}
	assert(false); // statement should be unreachable
	return false;
} // end of SMPFunction::FindChainAliasHelper()

// Link basic blocks to their predecessors and successors, and build the map
//  of instruction addresses to basic blocks.
void SMPFunction::SetLinks(void) {
	list<SMPBasicBlock *>::iterator BlockIter;
	SMPBasicBlock *CurrBlock;
	list<SMPBasicBlock *> UnresolvedBranchWorkList;
	ea_t InstAddr;
#if SMP_DEBUG_DATAFLOW_VERBOSE
	SMP_msg("SetLinks called for %s\n", this->GetFuncName());
#endif
	// First, set up the map of instructions to basic blocks.
	for (BlockIter = this->Blocks.begin(); BlockIter != this->Blocks.end(); ++BlockIter) {
		CurrBlock = (*BlockIter);
		vector<SMPInstr *>::iterator InstIter;
		for (InstIter = CurrBlock->GetFirstInst(); InstIter != CurrBlock->GetLastInst(); ++InstIter) {
			InstAddr = (*InstIter)->GetAddr();
			pair<ea_t, SMPBasicBlock *> MapItem(InstAddr, CurrBlock);
			InstBlockMap.insert(MapItem);
		}
	}

#if SMP_DEBUG_DATAFLOW_VERBOSE
	SMP_msg("SetLinks finished mapping: %s\n", this->GetFuncName());
#endif
	// Next, set successors of each basic block, also setting up the predecessors in the
	//  process.
	for (BlockIter = this->Blocks.begin(); BlockIter != this->Blocks.end(); ++BlockIter) {
		CurrBlock = (*BlockIter);
		vector<SMPInstr *>::iterator InstIter = (--(CurrBlock->GetLastInst()));
		SMPInstr *CurrInst = (*InstIter);
		InstAddr = CurrInst->GetAddr();
		bool CondTailCall = false;
		if (CurrBlock->HasReturn()) {
			if (!(CurrInst->IsCondTailCall())) {
				// We either have a return instruction or an unconditional
				//  tail call instruction. We don't want to link to the
				//  tail call target, and there is no link for a return
				continue;
			}
			else {
				// We have a conditional tail call. We don't want to
				//  link to the tail call target, but we do want fall
				//  through to the next instruction.
				CondTailCall = true;
			}
		}

		// Last instruction in block; set successors
		bool CallFlag = (CALL == CurrInst->GetDataFlowType());
		bool IndirJumpFlag = (INDIR_JUMP == CurrInst->GetDataFlowType());
		bool IndirCallFlag = (INDIR_CALL == CurrInst->GetDataFlowType());
		// NOTE: Dues to phase re-ordering, we cannot yet identify tail calls,
		//  so CondTailCall and TailCallFlag will always be false, which is harmless.
		//  SMPInstr::SetTailCall() will do a little cleanup later.
		bool TailCallFlag = CondTailCall && CurrInst->IsCondTailCall();
		SMP_xref_t CurrXrefs;
		bool LinkedToTarget = false;
		for (bool ok = CurrXrefs.SMP_first_from(CurrInst->GetAddr(), XREF_ALL);
			ok;
			ok = CurrXrefs.SMP_next_from()) {
				ea_t TargetAddr = CurrXrefs.GetTo();
				if ((TargetAddr != 0) && (CurrXrefs.GetIscode())) {
					// Found a code target, with its address in CurrXrefs.to
					if ((CallFlag || IndirCallFlag || TailCallFlag) 
						&& (TargetAddr != (CurrInst->GetAddr() + CurrInst->GetCmd().size))) {
						// A call instruction will have two targets: the fall through to the
						//  next instruction, and the called function. We want to link to the
						//  fall-through instruction, but not to the called function.
						// Some blocks end with a call just because the fall-through instruction
						//  is a jump target from elsewhere.
						continue;
					}
					map<ea_t, SMPBasicBlock *>::iterator MapEntry;
					MapEntry = this->InstBlockMap.find(TargetAddr);
					if (MapEntry == this->InstBlockMap.end()) {
						; // do nothing; probably a tail call (not yet identified)
#if 0
						SMP_msg("WARNING: addr %x not found in map for %s\n", TargetAddr,
							this->GetFuncName());
						SMP_msg(" Referenced from %s\n", CurrInst->GetDisasm());
#endif
					}
					else {
						SMPBasicBlock *Target = MapEntry->second;
						// Make target block a successor of current block.
						CurrBlock->LinkToSucc(Target);
						// Make current block a predecessor of target block.
						Target->LinkToPred(CurrBlock);
						LinkedToTarget = true;
#if SMP_USE_SWITCH_TABLE_INFO
						if (IndirJumpFlag) {
#if SMP_DEBUG_SWITCH_TABLE_INFO
							SMP_msg("Switch table link: jump at %x target at %x\n",
								CurrInst->GetAddr(), TargetAddr);
#else
							;
#endif
						}
#endif
					}
				}
		} // end for all xrefs
		if (IndirJumpFlag && (!LinkedToTarget)) {
			this->UnresolvedIndirectJumps = true;
			UnresolvedBranchWorkList.push_back(CurrBlock);
			SMP_msg("WARNING: Unresolved indirect jump at %lx\n", (unsigned long) CurrInst->GetAddr());
		}
		else if (IndirCallFlag && (!LinkedToTarget)) {
			this->UnresolvedIndirectCalls = true;
			SMP_msg("WARNING: Unresolved indirect call at %lx\n", (unsigned long) CurrInst->GetAddr());
		}
	} // end for all blocks

	// Mark all blocks that can be reached from the entry block, so we can find the unreachable ones.
	this->ResetProcessedBlocks();
	this->Blocks.front()->DepthFirstMark();
	// We have two cases: (1) Unresolved indirect branches could be targeting the unmarked blocks, making
	//  these blocks reachable, in which case we should link the unresolved branches to the unmarked blocks;
	//  or (2) there are no unresolved branches, in which case the unmarked blocks are unreachable within
	//  the function. They might be reachable from outside the function using exception handling jumps, but
	//  that still would not allow us to link them into the CFG of this function properly, so in any case we
	//  are deleting those unreachable blocks and not emitting annotations for them.
	// NOTE: An odd new gcc recursion optimization uses indirect calls within the function, so
	//  they can behave like indirect jumps. However, we don't want to link unresolved calls to unmarked blocks
	//  at this time.
	bool HellNodeCase = (!UnresolvedBranchWorkList.empty() && (this->HasUnresolvedIndirectCalls() || this->HasUnresolvedIndirectJumps()));
	bool AddedMissingLinks = false;
	bool changed;
	do {
		changed = false;
		list<SMPBasicBlock *>::iterator BlockIter = this->Blocks.begin();
		while (BlockIter != this->Blocks.end()) {
			CurrBlock = (*BlockIter);
			if (CurrBlock->IsProcessed()) {
				++BlockIter;
			}
			else {
				// Block cannot be reached from entry node, even after we have added links
				//  on previous loop iterations.
				if (!HellNodeCase) {
					if (CurrBlock->AllNops())
						SMP_msg("INFO: Removing all nops block at %lx\n", (unsigned long) CurrBlock->GetFirstAddr());
					else
						SMP_msg("INFO: Removing unreachable block at %lx\n", (unsigned long) CurrBlock->GetFirstAddr());
					// Remove this block from the predecessors list of its successors.
					list<SMPBasicBlock *>::iterator SuccIter;
					ea_t TempAddr = CurrBlock->GetFirstAddr();
					for (SuccIter = CurrBlock->GetFirstSucc(); SuccIter != CurrBlock->GetLastSucc(); ++SuccIter) {
						(*SuccIter)->ErasePred(TempAddr);
					}
					// Remove the unreachable instructions from the function inst list.
					vector<SMPInstr *>::iterator InstIter;
					InstIter = CurrBlock->GetFirstInst();
					ea_t FirstBadAddr = (*InstIter)->GetAddr();
					InstIter = CurrBlock->GetLastInst();
					--InstIter; // get last real instruction
					ea_t LastBadAddr = (*InstIter)->GetAddr();
					this->EraseInstRange(FirstBadAddr, LastBadAddr);

					// Remove the block from the blocks list.
					BlockIter = this->Blocks.erase(BlockIter);
					this->BlockCount -= 1;

#if 0  // Exception handling code requires something more delicate than this. Later checks for stack adjustment etc. can look at these blocks.
					// Finally, call destructors on the block and insts removed.
					InstIter = CurrBlock->GetFirstInst();
					while (InstIter != CurrBlock->GetLastInst()) {
						SMPInstr *DeadInst = (*InstIter);
						++InstIter;
						if (NULL != DeadInst) delete DeadInst;
					}
					delete CurrBlock;
#endif
				}
				else { // HellNodeCase
					// Block must be reachable only through an unresolved indirect branch.
					// Make each unresolved indirect branch link to the block so it is reachable.
					list<SMPBasicBlock *>::iterator WorkIter;
					AddedMissingLinks = true;
					for (WorkIter = UnresolvedBranchWorkList.begin(); WorkIter != UnresolvedBranchWorkList.end(); ++ WorkIter) {
						SMPBasicBlock *WorkBlock = (*WorkIter);
						WorkBlock->LinkToSucc(CurrBlock);
					}
					// Mark CurrBlock as now being reachable, along with the blocks it dominates.
					CurrBlock->DepthFirstMark();
					++BlockIter;
				}
				changed = true;
			} // end if (processed) ... else ...
		} // end loop through blocks
	} while (changed);
	if (HellNodeCase && (!AddedMissingLinks)) {
		SMP_msg("SERIOUS WARNING: Function at %lx has unresolved indirect branches but no unreachable blocks.\n",
			(unsigned long) this->FirstEA);
	}

#if 0
	// If we have any blocks that are all no-ops and have no predecessors, remove those
	//  blocks. They are dead and make the CFG no longer a lattice. Any blocks that have
	//  no predecessors but are not all no-ops should also be removed with a different
	//  log message.
	// NOTE: Prior to construction of hell nodes in functions with unresolved indirect jumps,
	//  we cannot conclude that a block with no predecessors is unreachable. Also, the block
	//  order might be such that removal of a block makes an already processed block
	//  unreachable, so we have to iterate until there are no more changes.
	bool NoPredecessors;
	bool OnlyPredIsItself;
	list<SMPBasicBlock *>::iterator CurrPred;
#if SMP_USE_SWITCH_TABLE_INFO
	if (!(this->HasUnresolvedIndirectJumps() || this->HasUnresolvedIndirectCalls())) {
#else
	if (!(this->HasIndirectJumps() || this->HasIndirectCalls())) {
#endif
		bool changed;
		do {
			changed = false;
			BlockIter = this->Blocks.begin();
			++BlockIter; // don't delete the top block, no matter what.
			while (BlockIter != this->Blocks.end()) {
				CurrBlock = (*BlockIter);
				OnlyPredIsItself = false;
				CurrPred = CurrBlock->GetFirstPred();
				NoPredecessors = (CurrPred == CurrBlock->GetLastPred());
				if (!NoPredecessors) {
					if ((*CurrPred)->GetFirstAddr() == CurrBlock->GetFirstAddr()) { // self-recursion
						++CurrPred; // any more preds besides itself?
						OnlyPredIsItself = (CurrPred == CurrBlock->GetLastPred());
							// Only predecessor was the self-recursion if no more preds
					}
				}
				if (NoPredecessors || OnlyPredIsItself) {
					if (CurrBlock->AllNops())
						SMP_msg("Removing all nops block at %x\n", CurrBlock->GetFirstAddr());
					else
						SMP_msg("Removing block with no predecessors at %x\n", CurrBlock->GetFirstAddr());
					// Remove this block from the predecessors list of its successors.
					list<SMPBasicBlock *>::iterator SuccIter;
					ea_t TempAddr = CurrBlock->GetFirstAddr();
					for (SuccIter = CurrBlock->GetFirstSucc(); SuccIter != CurrBlock->GetLastSucc(); ++SuccIter) {
						(*SuccIter)->ErasePred(TempAddr);
					}
					// Remove the unreachable instructions from the function inst list.
					vector<SMPInstr *>::iterator InstIter;
					InstIter = CurrBlock->GetFirstInst();
					ea_t FirstBadAddr = (*InstIter)->GetAddr();
					InstIter = CurrBlock->GetLastInst();
					--InstIter; // get last real instruction
					ea_t LastBadAddr = (*InstIter)->GetAddr();
					this->EraseInstRange(FirstBadAddr, LastBadAddr);

					// Finally, remove the block from the blocks list.
					BlockIter = this->Blocks.erase(BlockIter);
					this->BlockCount -= 1;
					changed = true;
				}
				else {
					++BlockIter;
				}
			} // end while all blocks after the first one
		} while (changed);
	} // end if not unresolved indirect jumps or indirect calls
	else if (this->UnresolvedIndirectJumps) {
		// Make each unresolved indirect branch have each block with no predecessor as a target,
		//  so that the resulting CFG has a proper structure.
		BlockIter = this->Blocks.begin();
		++BlockIter; // The top block is expected to have no predecessors, which is not a CFG problem.
		bool AddedMissingLinks = false;
		while (BlockIter != this->Blocks.end()) {
			CurrBlock = (*BlockIter);
			OnlyPredIsItself = false;
			CurrPred = CurrBlock->GetFirstPred();
			NoPredecessors = (CurrPred == CurrBlock->GetLastPred());
			if (!NoPredecessors) {
				if ((*CurrPred)->GetFirstAddr() == CurrBlock->GetFirstAddr()) { // self-recursion
					++CurrPred; // any more preds besides itself?
					OnlyPredIsItself = (CurrPred == CurrBlock->GetLastPred());
						// Only predecessor was the self-recursion if no more preds
				}
			}
			if (NoPredecessors || OnlyPredIsItself) {
				// Block must be reachable only through an unresolved indirect branch.
				// Make each unresolved indirect branch link to the block so it is reachable.
				list<SMPBasicBlock *>::iterator WorkIter;
				AddedMissingLinks = true;
				for (WorkIter = UnresolvedBranchWorkList.begin(); WorkIter != UnresolvedBranchWorkList.end(); ++ WorkIter) {
					SMPBasicBlock *WorkBlock = (*WorkIter);
					WorkBlock->LinkToSucc(CurrBlock);
				}
			}
			++BlockIter;
		} // end for all blocks
		if (!AddedMissingLinks) {
			SMP_msg("SERIOUS WARNING: Function at %x has unresolved indirect branches but no unreachable blocks.\n", this->FirstEA);
		}
	}
#endif

	return;
} // end of SMPFunction::SetLinks()

// Number all basic blocks in reverse postorder (RPO) and set RPOBlocks vector to
//  access them.
void SMPFunction::RPONumberBlocks(void) {
#if SMP_DEBUG_DATAFLOW
	bool DebugFlag = false;
	DebugFlag = (0 == strcmp("uw_frame_state_for", this->GetFuncName()));
	if (DebugFlag) SMP_msg("Entered RPONumberBlocks\n");
#endif
	int CurrNum = 0;
	list<SMPBasicBlock *> WorkList;

	// Number the first block with 0.
	list<SMPBasicBlock *>::iterator BlockIter = this->Blocks.begin();
	SMPBasicBlock *CurrBlock = (*BlockIter);
#if 0
	if (this->RPOBlocks.capacity() <= (size_t) this->BlockCount) {
		SMP_msg("Reserving %d RPOBlocks old value: %d\n", 2+this->BlockCount, this->RPOBlocks.capacity());
		this->RPOBlocks.reserve(2 + this->BlockCount);
		this->RPOBlocks.assign(2 + this->BlockCount, this->Blocks.end());
	}
#endif
	CurrBlock->SetNumber(CurrNum);
	this->RPOBlocks.push_back(CurrBlock);
	++CurrNum;
	// Push the first block's successors onto the work list.
	list<SMPBasicBlock *>::iterator CurrSucc = CurrBlock->GetFirstSucc();
	while (CurrSucc != CurrBlock->GetLastSucc()) {
		WorkList.push_back(*CurrSucc);
		++CurrSucc;
	}

	// Use the WorkList to iterate through all blocks in the function
	list<SMPBasicBlock *>::iterator CurrListItem = WorkList.begin();
	bool change;
	while (!WorkList.empty()) {
		change = false;
		while (CurrListItem != WorkList.end()) {
			if ((*CurrListItem)->GetNumber() != SMP_BLOCKNUM_UNINIT) {
				// Duplicates get pushed onto the WorkList because a block
				//  can be the successor of multiple other blocks. If it is
				//  already numbered, it is a duplicate and can be removed
				//  from the list.
				CurrListItem = WorkList.erase(CurrListItem);
				change = true;
				continue;
			}
			if ((*CurrListItem)->AllPredecessorsNumbered()) {
				// Ready to be numbered.
				(*CurrListItem)->SetNumber(CurrNum);
#if 0
				SMP_msg("Set RPO number %d\n", CurrNum);
				if (DebugFlag && (7 == CurrNum))
					this->Dump();
#endif
				this->RPOBlocks.push_back(*CurrListItem);
				++CurrNum;
				change = true;
				// Push its unnumbered successors onto the work list.
				CurrSucc = (*CurrListItem)->GetFirstSucc();
				while (CurrSucc != (*CurrListItem)->GetLastSucc()) {
					if ((*CurrSucc)->GetNumber() == SMP_BLOCKNUM_UNINIT)
						WorkList.push_back(*CurrSucc);
					++CurrSucc;
				}
				CurrListItem = WorkList.erase(CurrListItem);
			}
			else {
				++CurrListItem;
			}
		} // end while (CurrListItem != WorkList.end())
		if (change) {
			// Reset CurrListItem to beginning of work list for next iteration.
			CurrListItem = WorkList.begin();
		}
		else {
			// Loops can cause us to not be able to find a WorkList item that has
			//  all predecessors numbered. Take the WorkList item with the lowest address
			//  and number it so we can proceed.
			CurrListItem = WorkList.begin();
			ea_t LowAddr = (*CurrListItem)->GetFirstAddr();
			list<SMPBasicBlock *>::iterator SaveItem = CurrListItem;
			++CurrListItem;
			while (CurrListItem != WorkList.end()) {
				if (LowAddr > (*CurrListItem)->GetFirstAddr()) {
					SaveItem = CurrListItem;
					LowAddr = (*CurrListItem)->GetFirstAddr();
				}
				++CurrListItem;
			}
			// SaveItem should now be numbered.
			(*SaveItem)->SetNumber(CurrNum);
#if SMP_DEBUG_DATAFLOW
			SMP_msg("Picked LowAddr %x and set RPO number %d\n", LowAddr, CurrNum);
#endif
			this->RPOBlocks.push_back(*SaveItem);
			++CurrNum;
			// Push its unnumbered successors onto the work list.
			CurrSucc = (*SaveItem)->GetFirstSucc();
			while (CurrSucc != (*SaveItem)->GetLastSucc()) {
				if ((*CurrSucc)->GetNumber() == SMP_BLOCKNUM_UNINIT)
					WorkList.push_back(*CurrSucc);
				++CurrSucc;
			}
			CurrListItem = WorkList.erase(SaveItem);
			CurrListItem = WorkList.begin();
		} // end if (change) ... else ...
	} // end while work list is nonempty

	// Prior to construction of hell nodes for functions with indirect jumps, there
	//  could still be unnumbered blocks because they appear to be unreachable
	//  (no predecessors from SetLinks() because they are reached only via indirect
	//  jumps). We need to number these and push them on the RPOBlocks vector so
	//  that the vector contains all the blocks.
	// NOTE: Odd new gcc recursion optimization seems to use indirect calls to reach
	//  some blocks within a recursive function, operating somewhat like an indirect
	//  jump.
	if (this->HasIndirectJumps() || this->HasIndirectCalls()) {
		for (BlockIter = this->Blocks.begin(); BlockIter != this->Blocks.end(); ++BlockIter) {
			CurrBlock = (*BlockIter);
			if (SMP_BLOCKNUM_UNINIT == CurrBlock->GetNumber()) {
				SMP_msg("WARNING: Numbering indirectly reachable block at %lx\n", (unsigned long) CurrBlock->GetFirstAddr());
				CurrBlock->SetNumber(CurrNum);
				this->RPOBlocks.push_back(CurrBlock);
				++CurrNum;
			}
		}
	}
	// If we still have unnumbered blocks, it is not because of indirect jumps or calls.
	//  We have some mysterious dead code.
	if (this->BlockCount > this->RPOBlocks.size()) {
		SMP_msg("SERIOUS WARNING: RPONumberBlocks method: Function %s has BlockCount %d and RPOBlocks size %zu\n",
			this->GetFuncName(), this->BlockCount, this->RPOBlocks.size());
		for (BlockIter = this->Blocks.begin(); BlockIter != this->Blocks.end(); ++BlockIter) {
			CurrBlock = (*BlockIter);
			if (SMP_BLOCKNUM_UNINIT == CurrBlock->GetNumber()) {
				SMP_msg("WARNING: Numbering apparently unreachable block at %lx\n", (unsigned long) CurrBlock->GetFirstAddr());
				CurrBlock->SetNumber(CurrNum);
				this->RPOBlocks.push_back(CurrBlock);
				++CurrNum;
			}
		}
	}
	return;
} // end of SMPFunction::RPONumberBlocks()

// Perform live variable analysis on all blocks in the function.
// See chapter 9 of Cooper/Torczon, Engineering a Compiler, for the algorithm.
void SMPFunction::LiveVariableAnalysis(void) {
	list<SMPBasicBlock *>::iterator BlockIter;
	SMPBasicBlock *CurrBlock;
#if SMP_DEBUG_DATAFLOW
	bool DebugFlag = (0 == strcmp("uw_frame_state_for", this->GetFuncName()));
#endif
#if SMP_DEBUG_DATAFLOW_VERBOSE
	SMP_msg("LiveVariableAnalysis for %s\n", this->GetFuncName());
#endif

#if SMP_ANALYZE_STACK_POINTER
	;
#else
	for (BlockIter = this->Blocks.begin(); BlockIter != this->Blocks.end(); ++BlockIter) {
		CurrBlock = (*BlockIter);
		// Initialize the Killed and UpwardExposed sets for each block.
		CurrBlock->InitKilledExposed(this->UsesFramePointer());
	}
#endif

	bool changed;
	// Iterate over each block, updating LiveOut sets until no more changes are made.
	// NOTE: LVA is more efficient when computed over a reverse post-order list of blocks
	//  from the inverted CFG. We have an RPO list from the forward CFG, so it is just as
	//  good to simply iterate through the blocks in layout order.
#if 1
	do {
		changed = false;
		for (BlockIter = this->Blocks.begin(); BlockIter != this->Blocks.end(); ++BlockIter) {
			CurrBlock = (*BlockIter);
			changed |= CurrBlock->UpdateLiveOut();
		}
	} while (changed);
#else // Use reverse postorder
	do {
		changed = false;
		for (size_t index = 0; index < this->RPOBlocks.size(); ++index) {
			CurrBlock = this->RPOBlocks.at(index);
			changed |= CurrBlock->UpdateLiveOut();
		}
	} while (changed);
#endif

#if SMP_USE_SSA_FNOP_MARKER
	// Create DEFs in the marker instruction for all names in the LiveInSet
	//  of the first block. These are the names for the function that
	//  would otherwise look like USEs of uninitialized variables later.
	// Note that the LiveVariableAnalysis work does not actually populate
	//  a LiveInSet for the first block, so we simulate it with its
	//  dataflow equation, UpExposed union (LiveOut minus VarKill).
	set<op_t, LessOp>::iterator UpExposedIter, LiveOutIter;
	list<SMPInstr *>::iterator MarkerInst = this->Instrs.begin();
	SMPBasicBlock *FirstBlock = this->Blocks.front();
	for (UpExposedIter = FirstBlock->GetFirstUpExposed();
		UpExposedIter != FirstBlock->GetLastUpExposed();
		++UpExposedIter) {
			// Add DEF with SSANum of 0.
			(*MarkerInst)->AddDef(*UpExposedIter, UNINIT, 0);
			// Add to the VarKill and LiveIn sets.
			FirstBlock->AddVarKill(*UpExposedIter); // "killed" by marker inst def
			FirstBlock->AddLiveIn(*UpExposedIter);
	}
	for (LiveOutIter = FirstBlock->GetFirstLiveOut();
		LiveOutIter != FirstBlock->GetLastLiveOut();
		++LiveOutIter) {
			if (!(FirstBlock->IsVarKill(*LiveOutIter))) {
				// Add DEF with SSANum of 0.
				(*MarkerInst)->AddDef(*LiveOutIter, UNINIT, 0);
				// Add to the VarKill and LiveIn sets.
				FirstBlock->AddVarKill(*LiveOutIter); // "killed" by marker inst def
				FirstBlock->AddLiveIn(*LiveOutIter);
			}
	}
#endif

#if SMP_DEBUG_DATAFLOW_VERBOSE
	if (DebugFlag) SMP_msg("Exiting LiveVariableAnalysis\n");
#endif
	return;
} // end of SMPFunction::LiveVariableAnalysis()

// Return the IDom index that is the end of the intersection prefix of the Dom sets of
//  the two blocks designated by the RPO numbers passed in.
// See Cooper & Torczon, "Engineering a Compiler" 1st edition figure 9.8.
int SMPFunction::IntersectDoms(int block1, int block2) const {
	int finger1 = block1;
	int finger2 = block2;
	while (finger1 != finger2) {
		while (finger1 > finger2)
			finger1 = this->IDom.at(finger1);
		while (finger2 > finger1)
			finger2 = this->IDom.at(finger2);
	}
	return finger1;
} // end of SMPFunction::IntersectDoms()

// Compute immediate dominators of all blocks into IDom[] vector.
void SMPFunction::ComputeIDoms(void) {
	bool DebugFlag = false;
#if SMP_DEBUG_DATAFLOW
	DebugFlag = (0 == strcmp("_ZN6soplex7NameSetC2Eiidd", this->GetFuncName()));
	if (DebugFlag) SMP_msg("Entered ComputeIDoms\n");
#endif
	// Initialize the IDom[] vector to uninitialized values for all blocks.
	this->IDom.reserve(this->BlockCount);
	this->IDom.assign(this->BlockCount, SMP_BLOCKNUM_UNINIT);
	if (DebugFlag) {
		SMP_msg("BlockCount = %d RPOBlocks size = %zu\n", this->BlockCount, this->RPOBlocks.size());
	}
	if (this->BlockCount != this->RPOBlocks.size()) {
		SMP_msg("SERIOUS WARNING: Function %s has BlockCount of %d and RPOBlocks size of %zu\n",
			this->GetFuncName(), this->BlockCount, this->RPOBlocks.size());
	}
	this->IDom[0] = 0; // First block is dominated only by itself
	bool changed;
	do {
		changed = false;
		for (size_t RPONum = 1; RPONum < (size_t) this->BlockCount; ++RPONum) {
			if (DebugFlag) SMP_msg("RPONum %zu\n", RPONum);
#if 0
			if (DebugFlag) {
				SMP_msg("RPOBlocks vector size: %d\n", this->RPOBlocks.size());
				for (size_t index = 0; index < this->RPOBlocks.size(); ++index) {
					SMP_msg("RPOBlocks entry %d is %d\n", index, RPOBlocks[index]->GetNumber());
				}
			}
#endif
			// To avoid infinite loops on blocks that dominate themselves but otherwise have no 
			//  predecessors (probably reachable only through indirect jumps), we stop processing
			//  the blocks once the IDom becomes the top (entry) block. This probably saves time
			//  on other blocks as well.
			if (0 == this->IDom[RPONum])
				continue;

			SMPBasicBlock *CurrBlock = this->RPOBlocks.at(RPONum);
			// if (DebugFlag) SMP_msg("CurrBlock: %x\n", CurrBlock._Ptr);
			list<SMPBasicBlock *>::iterator CurrPred;
			// Initialize NewIdom to the first processed predecessor of block RPONum.
			int NewIdom = SMP_BLOCKNUM_UNINIT;
			for (CurrPred = CurrBlock->GetFirstPred(); CurrPred != CurrBlock->GetLastPred(); ++CurrPred) {
				int PredNum = (*CurrPred)->GetNumber();
				if (DebugFlag) SMP_msg("Pred: %d\n", PredNum);
				// **!!** See comment below about unreachable blocks.
				if (SMP_BLOCKNUM_UNINIT == PredNum)
					continue;
				int PredIDOM = this->IDom.at(PredNum);
				if (DebugFlag) SMP_msg("Pred IDom: %d\n", PredIDOM);
				if (SMP_BLOCKNUM_UNINIT != PredIDOM) {
					NewIdom = PredNum;
					break;
				}
			}
			if (NewIdom == SMP_BLOCKNUM_UNINIT) {
				SMP_msg("WARNING: Failure on NewIdom in ComputeIDoms for %s\n", this->GetFuncName());
				if (this->HasIndirectJumps() || this->HasIndirectCalls()) {
					// Might be reachable only through indirect jumps.
					NewIdom = 0; // make it dominated by entry block
					SMP_msg("WARNING: Assuming block %d at address %lx is reachable indirectly.\n",
						CurrBlock->GetNumber(), (unsigned long) CurrBlock->GetFirstAddr());
				}
				else {
					// Might be exception handling code, reachable only by call stack walking.
					NewIdom = 0; // make it be dominated by entry block
					SMP_msg("WARNING: Assuming block %d at address %lx is reachable by exception handling.\n",
						CurrBlock->GetNumber(), (unsigned long) CurrBlock->GetFirstAddr());
				}
			}
			assert(NewIdom != SMP_BLOCKNUM_UNINIT);
			// Loop through all predecessors of block RPONum except block NewIdom.
			//  Set NewIdom to the intersection of its Dom set and the Doms set of
			//  each predecessor that has had its Doms set computed.
			for (CurrPred = CurrBlock->GetFirstPred(); CurrPred != CurrBlock->GetLastPred(); ++CurrPred) {
				int PredNum = (*CurrPred)->GetNumber();
				if (DebugFlag) SMP_msg("PredNum: %d\n", PredNum);
				// **!!** We can avoid failure on unreachable basic blocks
				//  by executing a continue statement if PredNum is -1. Long term solution
				//  is to prune out unreachable basic blocks, or better yet, create hell nodes
				//  if the function has indirect jumps.
				if (PredNum == SMP_BLOCKNUM_UNINIT)
					continue;
				int PredIDOM = this->IDom.at(PredNum);
				if (DebugFlag) SMP_msg("PredIDOM: %d\n", PredIDOM);
				if ((SMP_BLOCKNUM_UNINIT == PredIDOM) || (NewIdom == PredIDOM)) {
					// Skip predecessors that have uncomputed Dom sets, or are the
					//  current NewIdom.
					continue;
				}
				if (DebugFlag) SMP_msg("Old NewIdom value: %d\n", NewIdom);
				NewIdom = this->IntersectDoms(PredNum, NewIdom);
				if (DebugFlag) SMP_msg("New NewIdom value: %d\n", NewIdom);
			}
			// If NewIdom is not the value currently in vector IDom[], update the
			//  vector entry and set changed to true.
			if (NewIdom != this->IDom.at(RPONum)) {
				if (DebugFlag) SMP_msg("IDOM changed from %d to %d\n", this->IDom.at(RPONum), NewIdom);
				this->IDom[RPONum] = NewIdom;
				changed = true;
			}
		}
	} while (changed);
	return;
} // end of SMPFunction::ComputeIDoms()

// Compute dominance frontier sets for each block.
void SMPFunction::ComputeDomFrontiers(void) {
	list<SMPBasicBlock *>::iterator BlockIter;
	SMPBasicBlock *RunnerBlock;
	SMPBasicBlock *CurrBlock;
	for (BlockIter = this->Blocks.begin(); BlockIter != this->Blocks.end(); ++BlockIter) {
		CurrBlock = (*BlockIter);
		// We look only at join points in the CFG, as per Cooper/Torczon chapter 9.
		if (1 < CurrBlock->GetNumPreds()) { // join point; more than 1 predecessor
			int runner;
			list<SMPBasicBlock *>::iterator PredIter;
			SMPBasicBlock *CurrPred;
			for (PredIter = CurrBlock->GetFirstPred(); PredIter != CurrBlock->GetLastPred(); ++PredIter) {
				CurrPred = (*PredIter);
				// For each predecessor, we run up the IDom[] vector and add CurrBlock to the
				//  DomFrontier for all blocks that are between CurrPred and IDom[CurrBlock],
				//  not including IDom[CurrBlock] itself.
				runner = CurrPred->GetNumber();
				while (runner != this->IDom.at(CurrBlock->GetNumber())) {
					// Cooper/Harvey/Kennedy paper does not quite agree with the later
					//  text by Cooper/Torczon. Text says that the start node has no IDom
					//  in the example on pages 462-463, but it shows an IDOM for the
					//  root node in Figure 9.9 of value == itself. The first edition text
					//  on p.463 seems correct, as the start node dominates every node and
					//  thus should have no dominance frontier.
					if (SMP_TOP_BLOCK == runner)
						break;
					RunnerBlock = this->RPOBlocks.at(runner);
					RunnerBlock->AddToDomFrontier(CurrBlock->GetNumber());
					runner = this->IDom.at(runner);
				}
			} // end for all predecessors
		} // end if join point
	} // end for all blocks
	return;
} // end of SMPFunction::ComputeDomFrontiers()

// Compute the GlobalNames set, which includes all operands that are used in more than
//  one basic block. It is the union of all UpExposedSets of all blocks.
void SMPFunction::ComputeGlobalNames(void) {
	set<op_t, LessOp>::iterator SetIter;
	list<SMPBasicBlock *>::iterator BlockIter;
	SMPBasicBlock *CurrBlock;
	unsigned int index = 0;
	if (this->Blocks.size() < 2)
		return; // cannot have global names if there is only one block

	bool DebugFlag = false;
#if SMP_DEBUG_DATAFLOW
	DebugFlag = (0 == strcmp("uw_frame_state_for", this->GetFuncName()));
#endif

	for (BlockIter = this->Blocks.begin(); BlockIter != this->Blocks.end(); ++BlockIter) {
		CurrBlock = (*BlockIter);
		for (SetIter = CurrBlock->GetFirstUpExposed(); SetIter != CurrBlock->GetLastUpExposed(); ++SetIter) {
			op_t TempOp = *SetIter;
			// The GlobalNames set will have the complete collection of operands that we are
			//  going to number in our SSA computations. We now assign an operand number
			//  within the op_t structure for each, so that we can index into the
			//  BlocksUsedIn[] vector, for example. This operand number is not to be
			//  confused with SSA numbers.
			// We use the operand number field op_t.n for the lower 8 bits, and the offset
			//  fields op_t.offb:op_t.offo for the upper 16 bits. We are overwriting IDA
			//  values here, but operands in the data flow analysis sets should never be
			//  inserted back into the program anyway.
			SetGlobalIndex(&TempOp, index);

#if SMP_DEBUG_DATAFLOW
			if (DebugFlag) {
				SMP_msg("Global Name: ");
				PrintListOperand(TempOp);
			}
#endif
			set<op_t, LessOp>::iterator AlreadyInSet;
			pair<set<op_t, LessOp>::iterator, bool> InsertResult;
			InsertResult = this->GlobalNames.insert(TempOp);
			if (!InsertResult.second) {
				// Already in GlobalNames, so don't assign an index number.
				;
#if SMP_DEBUG_DATAFLOW
				if (DebugFlag) {
					SMP_msg(" already in GlobalNames.\n");
				}
#endif
			}
			else {
				++index;
#if SMP_DEBUG_DATAFLOW
				if (DebugFlag) {
					SMP_msg(" inserted as index %d\n", ExtractGlobalIndex(TempOp));
				}
#endif
			}
		} // for each upward exposed item in the current block
	} // for each basic block

	assert(16777215 >= this->GlobalNames.size()); // index fits in 24 bits
	return;
} // end of SMPFunction::ComputeGlobalNames()

// For each item in GlobalNames, record the blocks that DEF the item.
void SMPFunction::ComputeBlocksDefinedIn(void) {
	// Loop through all basic blocks and examine all DEFs. For Global DEFs, record
	//  the block number in BlocksDefinedIn. The VarKillSet records DEFs without
	//  having to examine every instruction.
	list<SMPBasicBlock *>::iterator BlockIter;
	SMPBasicBlock *CurrBlock;

	this->BlocksDefinedIn.clear();
	for (size_t i = 0; i < this->GlobalNames.size(); ++i) {
		list<int> TempList;
		this->BlocksDefinedIn.push_back(TempList);
	}
#if SMP_DEBUG_DATAFLOW_VERBOSE
	SMP_msg("Number of GlobalNames: %d\n", this->GlobalNames.size());
	SMP_msg("Size of BlocksDefinedIn: %d\n", this->BlocksDefinedIn.size());
#endif
	for (BlockIter = this->Blocks.begin(); BlockIter != this->Blocks.end(); ++BlockIter) {
		set<op_t, LessOp>::iterator KillIter;
		CurrBlock = (*BlockIter);
		for (KillIter = CurrBlock->GetFirstVarKill(); KillIter != CurrBlock->GetLastVarKill(); ++KillIter) {
			// If killed item is not a block-local item (it is global), record it.
			set<op_t, LessOp>::iterator NameIter = this->GlobalNames.find(*KillIter);
			if (NameIter != this->GlobalNames.end()) { // found in GlobalNames set
				// We have a kill of a global name. Get index from three 8-bit fields.
				unsigned int index = ExtractGlobalIndex(*NameIter);
				if (index >= this->GlobalNames.size()) {
					// We are about to assert false.
					SMP_msg("ComputeBlocksDefinedIn: Bad index: %d limit: %zu\n", index,
						this->GlobalNames.size());
					SMP_msg("Block number %d\n", CurrBlock->GetNumber());
					SMP_msg("Killed item: ");
					PrintListOperand(*KillIter);
					SMP_msg("\n");
					SMP_msg("This is a fatal error.\n");
				}
				assert(index < this->GlobalNames.size());
				// index is a valid subscript for the BlocksDefinedIn vector. Push the
				//  current block number onto the list of blocks that define this global name.
				this->BlocksDefinedIn[index].push_back(CurrBlock->GetNumber());
			}			
		}
	}
	return;
} // end of SMPFunction::ComputeBlocksDefinedIn()

// Compute the phi functions at the entry point of each basic block that is a join point.
void SMPFunction::InsertPhiFunctions(void) {
	set<op_t, LessOp>::iterator NameIter;
	list<int> WorkList;  // list of block numbers
	bool DebugFlag = false;
#if SMP_DEBUG_DATAFLOW
	DebugFlag = (0 == strcmp("uw_frame_state_for", this->GetFuncName()));
#endif
	if (DebugFlag) SMP_msg("GlobalNames size: %zu\n", this->GlobalNames.size());
	for (NameIter = this->GlobalNames.begin(); NameIter != this->GlobalNames.end(); ++NameIter) {
		int CurrNameIndex = (int) (ExtractGlobalIndex(*NameIter));
		if (DebugFlag) SMP_msg("CurrNameIndex: %d\n", CurrNameIndex);
#if 0
		DebugFlag = (DebugFlag && (6 == CurrNameIndex));
#endif
		// Initialize the work list to all blocks that define the current name.
		WorkList.clear();
		list<int>::iterator WorkIter;
		for (WorkIter = this->BlocksDefinedIn.at((size_t) CurrNameIndex).begin();
			WorkIter != this->BlocksDefinedIn.at((size_t) CurrNameIndex).end();
			++WorkIter) {
			WorkList.push_back(*WorkIter);
		}

		// Iterate through the work list, inserting phi functions for the current name
		//  into all the blocks in the dominance frontier of each work list block.
		//  Insert into the work list each block that had a phi function added.
		while (!WorkList.empty()) {
#if SMP_DEBUG_DATAFLOW_VERBOSE
			if (DebugFlag) SMP_msg("WorkList size: %d\n", WorkList.size());
#endif
			list<int>::iterator WorkIter = WorkList.begin();
			while (WorkIter != WorkList.end()) {
				set<int>::iterator DomFrontIter;
#if SMP_DEBUG_DATAFLOW_VERBOSE
				if (DebugFlag) SMP_msg("WorkIter: %d\n", *WorkIter);
#endif
				if (DebugFlag && (*WorkIter > this->BlockCount)) {
					SMP_msg("ERROR: WorkList block # %d out of range.\n", *WorkIter);
				}
				SMPBasicBlock *WorkBlock = this->RPOBlocks[*WorkIter];
				for (DomFrontIter = WorkBlock->GetFirstDomFrontier();
					DomFrontIter != WorkBlock->GetLastDomFrontier();
					++DomFrontIter) {
#if SMP_DEBUG_DATAFLOW_VERBOSE
					if (DebugFlag) SMP_msg("DomFront: %d\n", *DomFrontIter);
#endif
					if (DebugFlag && (*DomFrontIter > this->BlockCount)) {
						SMP_msg("ERROR: DomFront block # %d out of range.\n", *DomFrontIter);
					}
					SMPBasicBlock *PhiBlock = this->RPOBlocks[*DomFrontIter];
					// Before inserting a phi function for the current name in *PhiBlock,
					//  see if the current name is LiveIn for *PhiBlock. If not, there
					//  is no need for the phi function. This check is what makes the SSA
					//  a fully pruned SSA.
					if (PhiBlock->IsLiveIn(*NameIter)) {
						size_t NumPreds = PhiBlock->GetNumPreds();
						DefOrUse CurrRef(*NameIter);
						SMPPhiFunction CurrPhi(CurrNameIndex, CurrRef);
						for (size_t NumCopies = 0; NumCopies < NumPreds; ++NumCopies) {
							CurrPhi.PushBack(CurrRef); // inputs to phi
						}
						if (PhiBlock->AddPhi(CurrPhi)) {
							// If not already in Phi set, new phi function was inserted.
							WorkList.push_back(PhiBlock->GetNumber());
#if SMP_DEBUG_DATAFLOW_VERBOSE
							if (DebugFlag) SMP_msg("Added phi for name %d at top of block %d\n", CurrNameIndex, PhiBlock->GetNumber());
#endif
						}
					}
					else {
						if (DebugFlag) {
							SMP_msg("Global %d not LiveIn for block %d\n", CurrNameIndex, PhiBlock->GetNumber());
						}
					}
				} // end for all blocks in the dominance frontier
				// Remove current block number from the work list
				if (DebugFlag) {
					SMP_msg("Removing block %d from work list.\n", *WorkIter);
				}
				WorkIter = WorkList.erase(WorkIter);
			} // end for all block numbers in the work list
		} // end while the work list is not empty
		if (DebugFlag) SMP_msg("WorkList empty.\n");
	} // end for all elements of the GlobalNames set
	return;
} // end of SMPFunction::InsertPhiFunctions()

// Build the dominator tree.
void SMPFunction::BuildDominatorTree(void) {
	size_t index;
	// First, fill the DomTree vector with the parent numbers filled in and the child lists
	//  left empty.
	for (index = 0; index < this->IDom.size(); ++index) {
		pair<int, list<int> > DomTreeEntry;
		DomTreeEntry.first = this->IDom.at(index);
		DomTreeEntry.second.clear();
		this->DomTree.push_back(DomTreeEntry);
	}
	// Now, push the children onto the appropriate lists.
	for (index = 0; index < this->IDom.size(); ++index) {
		// E.g. if block 5 has block 3 as a parent, then we fetch the number 3
		//  using the expression this->DomTree.at(index).first, which was just
		//  initialized in the previous loop. Then we go to DomTree entry 3 and push
		//  the number 5 on its child list.
		int parent = this->DomTree.at(index).first;
		if (parent != (int) index) // block can dominate itself, but not in DomTree!
			this->DomTree.at(parent).second.push_back((int) index);
	}

	return;
} // end of SMPFunction::BuildDominatorTree()

// Does basic block HeadBlockNum dominate basic block TailBlockNum?
bool SMPFunction::DoesBlockDominateBlock(int HeadBlockNum, int TailBlockNum) {
	if (HeadBlockNum == TailBlockNum)
		return true;
	else if ((HeadBlockNum == SMP_BLOCKNUM_UNINIT) || (TailBlockNum == SMP_BLOCKNUM_UNINIT)) {
		return false;
	}
	else {
		// Recurse downward from HeadBlockNum in the dominator tree until we find TailBlockNum
		//  or return false if we never find it.
		bool FoundIt = false;
		for (list<int>::iterator ChildIter = this->DomTree.at(HeadBlockNum).second.begin(); 
			ChildIter != this->DomTree.at(HeadBlockNum).second.end(); 
			++ChildIter) {
			int ChildBlockNum = (*ChildIter);
			if (this->DoesBlockDominateBlock(ChildBlockNum, TailBlockNum)) { // recurse depth-first
				FoundIt = true;
				break;
			}
		}
		return FoundIt;
	}
} // end of SMPFunction::DoesBlockDominateBlock()

// Is block (with block # BlockNum) inside any loop?
bool SMPFunction::IsBlockInAnyLoop(int BlockNum) {
	bool FoundInsideLoop = this->FuncLoopsByBlock.at((size_t)BlockNum).IsAnyBitSet();
	return FoundInsideLoop;
} // end of SMPFunction::IsBlockInAnyLoop()

// Is block (with block # BlockNum) inside loop # LoopNum?
bool SMPFunction::IsBlockInLoop(int BlockNum, size_t LoopNum) {
	return ((LoopNum < this->LoopCount) && (this->FuncLoopsByBlock.at((size_t) BlockNum).GetBit(LoopNum)));
} // end of SMPFunction::IsBlockInLoop()

// build list of loop numbers that BlockNum is part of.
void SMPFunction::BuildLoopList(int BlockNum, list<size_t> &LoopList) {
	size_t LoopIndex;
	for (LoopIndex = 0; LoopIndex < this->LoopCount; ++LoopIndex) {
		if (this->FuncLoopsByBlock.at((size_t) BlockNum).GetBit(LoopIndex)) {
			LoopList.push_back(LoopIndex);
		}
	}
	return;
} // end of SMPFunction::BuildLoopList()

// Helper for SSA subscript renumbering: return the next SSA number for the global name
//  and increment the SSACounter to prepare the next number. Push the returned number onto
//  the SSAStack for the global name.
int SMPFunction::SSANewNumber(size_t GlobNameIndex) {
	int Subscript = this->SSACounter.at(GlobNameIndex);
	++(this->SSACounter[GlobNameIndex]);
	this->SSAStack[GlobNameIndex].push_back(Subscript);
	return Subscript;
} // end of SMPFunction::SSANewNumber()

// Main helper for SSA subscript renumbering. Renumber within block throughout its phi
//  functions, then its DEFs and USEs, then its phi successors. Recurse then on all
//  successors in the dominator tree.
void SMPFunction::SSARename(int BlockNumber) {
	assert(0 <= BlockNumber);
	assert(BlockNumber < this->BlockCount);

	SMPBasicBlock *CurrBlock = this->RPOBlocks.at((size_t) BlockNumber);

	bool DumpFlag = false;
#if SMP_DEBUG_DATAFLOW_VERBOSE
	DumpFlag |=	(0 == strcmp("main", this->GetFuncName()));
	DumpFlag |= (0 == strcmp("dohanoi", this->GetFuncName()));
	DumpFlag |= (0 == strcmp("uw_frame_state_for", this->GetFuncName()));
	DumpFlag |= (0 == strcmp("_IO_sputbackc", this->GetFuncName()));
#endif

	if (DumpFlag) SMP_msg("Entered SSARename for block number %d\n", BlockNumber);

	// For each phi function at the top of the block, rename the DEF of the phi function
	//  using SSANewNumber() on the global name index.
	set<SMPPhiFunction, LessPhi>::iterator CurrPhi;
	list<SMPPhiFunction> TempPhiList;
	int GlobalNameIndex;
	for (CurrPhi = CurrBlock->GetFirstPhi(); CurrPhi != CurrBlock->GetLastPhi(); ++CurrPhi) {
		op_t PhiDefOp = CurrPhi->GetAnyOp();
		GlobalNameIndex = CurrPhi->GetIndex();
		assert(0 <= GlobalNameIndex);
		int NewSSANum = this->SSANewNumber((size_t) GlobalNameIndex);

		// Cannot change the C++ STL set item directly, as sets might become unordered.
		SMPPhiFunction TempPhi = (*CurrPhi);
		TempPhi.SetSSADef(NewSSANum);
		TempPhiList.push_back(TempPhi);

		if (o_reg == PhiDefOp.type) {
			if (DumpFlag && PhiDefOp.is_reg(R_ax)) {
				SMP_msg("New EAX Phi Def SSANum: %d Block %d\n", NewSSANum, BlockNumber);
			}
			// Map the final SSA number to the block number.
			int DefHashValue = HashGlobalNameAndSSA(PhiDefOp, NewSSANum);
			pair<int, ea_t> DefMapEntry(DefHashValue, CurrBlock->GetNumber());
			pair<map<int, ea_t>::iterator, bool> MapReturnValue;
			MapReturnValue = this->GlobalDefAddrBySSA.insert(DefMapEntry);
			assert(MapReturnValue.second);
		}
	}
	// Go back through the Phi function set and replace the items that need to be updated.
	list<SMPPhiFunction>::iterator TempIter;
	for (TempIter = TempPhiList.begin(); TempIter != TempPhiList.end(); ++TempIter) {
		// Use the op_t from the first phi use, because they are all the same.
		bool Erased = CurrBlock->ErasePhi(TempIter->GetPhiRef(0).GetOp());
		assert(Erased);
		// Now we can add back the phi function that had the DEF SSA number changed.
		bool Added = CurrBlock->AddPhi(*TempIter);
		assert(Added);
	}
	TempPhiList.clear();
	if (DumpFlag) SMP_msg("Processed phi functions at top.\n");

	// For each instruction in the block, rename all global USEs and then all global DEFs.
	vector<SMPInstr *>::iterator InstIter;
	SMPInstr *CurrInst;
	for (InstIter = CurrBlock->GetFirstInst(); InstIter != CurrBlock->GetLastInst(); ++InstIter) {
		CurrInst = (*InstIter);
		set<DefOrUse, LessDefUse>::iterator CurrUse = CurrInst->GetFirstUse();
		ea_t InstAddr = CurrInst->GetAddr(); // for debugging break points
		while (CurrUse != CurrInst->GetLastUse()) {
			// See if Use is a global name.
			op_t UseOp = CurrUse->GetOp();
			set<op_t, LessOp>::iterator GlobIter = this->GlobalNames.find(UseOp);
			if (GlobIter != this->GlobalNames.end()) { // found it
				unsigned int GlobIndex = ExtractGlobalIndex(*GlobIter);
				if (GlobIndex > this->SSAStack.size()) {
					// Get some debug info out to the log file before we crash.
					SMP_msg("FATAL ERROR: Bad GlobIndex: %d at %lx in %s\n", GlobIndex, (unsigned long) InstAddr, this->GetFuncName());
					exit(EXIT_FAILURE);
				}
				// Set the SSA number for this use to the top of stack SSA # (back())
				int NewSSANum;
				if (this->SSAStack.at(GlobIndex).empty()) {
					// No top of stack entry to read.
#if SMP_DEBUG_UNINITIALIZED_SSA_NAMES
					if (!CurrInst->MDIsPopInstr() && (o_reg == UseOp.type)) {
						// POP uses the stack offset and generates spurious
						//  uninitialized variable messages for [esp+0].
						SMP_msg("WARNING: function %s : Use of uninitialized variable: ",
							this->GetFuncName());
						SMP_msg(" Variable: ");
						PrintListOperand(*GlobIter);
						SMP_msg(" Block number: %d Address: %lx Instruction: %s\n", BlockNumber,
							(unsigned long) CurrInst->GetAddr(), CurrInst->GetDisasm());
					}
#endif
					NewSSANum = SMP_SSA_UNINIT;
				}
				else {
					NewSSANum = this->SSAStack.at(GlobIndex).back();
				}
				CurrUse = CurrInst->SetUseSSA(UseOp, NewSSANum);
				if (DumpFlag && (o_reg == UseOp.type) && UseOp.is_reg(R_ax)) {
					SMP_msg("New EAX Use SSANum: %d at %lx\n", NewSSANum, (unsigned long) CurrInst->GetAddr());
				}
			}
			++CurrUse;
		} // end for all USEs
		set<DefOrUse, LessDefUse>::iterator CurrDef = CurrInst->GetFirstDef();
		while (CurrDef != CurrInst->GetLastDef()) {
			// See if Def is a global name.
			op_t DefOp = CurrDef->GetOp();
			set<op_t, LessOp>::iterator GlobIter = this->GlobalNames.find(DefOp);
			if (GlobIter != this->GlobalNames.end()) { // found it
				unsigned int GlobIndex = ExtractGlobalIndex(*GlobIter);
				// Set the SSA number for this DEF to the SSANewNumber top of stack
				int NewSSANum = this->SSANewNumber(GlobIndex);
				CurrDef = CurrInst->SetDefSSA(DefOp, NewSSANum);
				if (o_reg == DefOp.type) {
					ea_t DefAddr = InstAddr;
					if (DumpFlag && DefOp.is_reg(R_ax)) {
						SMP_msg("New EAX Def SSANum: %d at %lx\n", NewSSANum, (unsigned long) DefAddr);
					}

					// Map the final SSA number to the DEF address.
					int DefHashValue = HashGlobalNameAndSSA(DefOp, NewSSANum);
					pair<int, ea_t> DefMapEntry(DefHashValue, DefAddr);
					pair<map<int, ea_t>::iterator, bool> MapReturnValue;
					MapReturnValue = this->GlobalDefAddrBySSA.insert(DefMapEntry);
					assert(MapReturnValue.second);
				}
			}
			++CurrDef;
		} //  end for all DEFs
	} // end for all instructions
	if (DumpFlag) SMP_msg("Processed all instructions.\n");

	// For all control flow graph (not dominator tree) successors, fill in the current
	//  (outgoing) SSA number in the corresponding USE slot in the phi function, for all
	//  global names appearing in phi functions.
	list<SMPBasicBlock *>::iterator SuccIter;
	for (SuccIter = CurrBlock->GetFirstSucc(); SuccIter != CurrBlock->GetLastSucc(); ++SuccIter) {
		// What position in the Preds list of this successor is CurrBlock?
		int ListPos = (*SuccIter)->GetPredPosition(BlockNumber);
		assert(0 <= ListPos);

		// Go through all phi functions in this successor. At ListPos position in the
		//  incoming arguments for that phi function, set the SSA number to the SSA number
		//  in the top of stack entry for the global name associated with that phi function.
		set<SMPPhiFunction, LessPhi>::iterator CurrPhi;
		for (CurrPhi = (*SuccIter)->GetFirstPhi(); CurrPhi != (*SuccIter)->GetLastPhi(); ++CurrPhi) {
			int GlobIndex = CurrPhi->GetIndex();
			int CurrSSA;
			if (this->SSAStack.at(GlobIndex).empty()) {
				// No top of stack entry to read.
#if SMP_DEBUG_UNINITIALIZED_SSA_NAMES
				SMP_msg("WARNING: function %s : Path to use of uninitialized variable: ",
					this->GetFuncName());
				SMP_msg(" Variable: ");
				PrintListOperand(CurrPhi->GetAnyOp());
				SMP_msg(" Block number: %d Successor block number: %d\n", BlockNumber,
					(*SuccIter)->GetNumber());
#endif
				CurrSSA = SMP_SSA_UNINIT;
			}
			else {
				CurrSSA = this->SSAStack.at(GlobIndex).back();  // fetch from top of stack
			}
			SMPPhiFunction TempPhi = (*CurrPhi);
			TempPhi.SetSSARef(ListPos, CurrSSA);
			TempPhiList.push_back(TempPhi);
			if (DumpFlag && (BlockNumber >= 3) && (BlockNumber <= 4)) {
				SMP_msg("BlockNumber: %d  ListPos: %d\n", BlockNumber, ListPos);
			}
		} // end for all phi functions in successor
		// Go back through the Phi function set and replace the items that need to be updated.
		for (TempIter = TempPhiList.begin(); TempIter != TempPhiList.end(); ++TempIter) {
#if 0
			if (DumpFlag && (BlockNumber >= 3) && (BlockNumber <= 4)) {
				SMP_msg("Special before phi dump:\n");
				set<SMPPhiFunction, LessPhi>::iterator FoundPhi;
				FoundPhi = (*SuccIter)->FindPhi(TempIter->GetAnyOp());
				FoundPhi->Dump();
			}
#endif
			// Use the op_t from the first phi use, because they are all the same.
			bool Erased = (*SuccIter)->ErasePhi(TempIter->GetPhiRef(0).GetOp());
			assert(Erased);
			// Now we can add back the phi function that had one SSA number changed.
			bool Added = (*SuccIter)->AddPhi(*TempIter);
			assert(Added);
			if (DumpFlag && (BlockNumber >= 3) && (BlockNumber <= 4)) {
				SMP_msg("Special after phi dump:\n");
				set<SMPPhiFunction, LessPhi>::iterator FoundPhi;
				FoundPhi = (*SuccIter)->FindPhi(TempIter->GetAnyOp());
				FoundPhi->Dump();
			}
		}
		TempPhiList.clear();
	} // end for all successors of CurrBlock
	if (DumpFlag) SMP_msg("Processed successor phi functions.\n");

	// For each successor in the dominator tree, recurse.
	list<int>::iterator ChildIter;
	for (ChildIter = this->DomTree[BlockNumber].second.begin();
		ChildIter != this->DomTree[BlockNumber].second.end();
		++ChildIter) {
			this->SSARename(*ChildIter);
	}
	if (DumpFlag) SMP_msg("Finished recursion.\n");

	// Pop off all SSAStack entries pushed during this block. I.e. for each global name,
	//  pop its SSAStack once per DEF and once per phi function in this block.
	for (CurrPhi = CurrBlock->GetFirstPhi(); CurrPhi != CurrBlock->GetLastPhi(); ++CurrPhi) {
		GlobalNameIndex = CurrPhi->GetIndex();
		this->SSAStack.at((size_t) GlobalNameIndex).pop_back();
	}
	if (DumpFlag) SMP_msg("Popped off entries due to phi functions.\n");
	for (InstIter = CurrBlock->GetFirstInst(); InstIter != CurrBlock->GetLastInst(); ++InstIter) {
		set<DefOrUse, LessDefUse>::iterator CurrDef;
		CurrInst = (*InstIter);
		for (CurrDef = CurrInst->GetFirstDef(); CurrDef != CurrInst->GetLastDef(); ++CurrDef) {
			// See if DEF is a global name.
			set<op_t, LessOp>::iterator GlobIter = this->GlobalNames.find(CurrDef->GetOp());
			if (GlobIter != this->GlobalNames.end()) { // found it
				unsigned int GlobIndex = ExtractGlobalIndex(*GlobIter);
				this->SSAStack.at((size_t) GlobIndex).pop_back();
			}
		} //  end for all DEFs
	} // end for all instructions
	if (DumpFlag) { 
		SMP_msg("Popped off entries due to instructions.\n");
	}

	return;
} // end of SMPFunction::SSARename()

// Main driver of SSA subscript renumbering.
void SMPFunction::SSARenumber(void) {
	bool DumpFlag = false;
#if 0
	DumpFlag |= (0 == strcmp("_IO_sputbackc", this->GetFuncName()));
#endif

	if (0 >= this->GlobalNames.size())
		return;  // no names to renumber

	// Initialize stacks and counters of SSA numbers.
	size_t GlobIndex;
	assert(0 == this->SSACounter.size());
	for (GlobIndex = 0; GlobIndex < this->GlobalNames.size(); ++GlobIndex) {
		list<int> DummyList;
		this->SSACounter.push_back(0);
		this->SSAStack.push_back(DummyList);
	}

	// Recurse through the dominator tree starting with node 0.
	this->SSARename(0);
	if (DumpFlag)
		this->Dump();
	return;
} // end of SMPFunction::SSARenumber()

// Emit debugging output for analyzing time spent in InferTypes() ?
#define SMP_ANALYZE_INFER_TYPES_TIME 0

// Main driver for the type inference system.
void SMPFunction::InferTypes(bool FirstIter) {
	// The type inference system is an iteration over four analysis steps, until
	//  a fixed point is reached:
	// 1) Within an instruction, set types of operators based on the operator type,
	//     the operand types, and the instruction type category, and propagate the
	//     type of the SMP_ASSIGN operator to its DEF.
	// 2) Propagate the type of a DEF along its SSA chain to all USEs of that SSA name.
	// 3) If all USEs of an SSA name have the same type, but the DEF has no type,
	//     then infer that the DEF must have the same type.
	// 4) If all references to a memory location have the same type, mark that memory
	//     location as having that type, if no aliasing occurs.
	//
	// The type inference system will mark DEFs and USEs in each instruction's DEF and USE
	//  sets with an inferred type. This inference on USEs is not conclusive for other USEs
	//  outside of that instruction. For example, a pointer could be read in from memory
	//  and used as a pointer, then hashed using an arithmetic operation. If the arithmetic
	//  operation always treats its source operands as NUMERIC and produces a NUMERIC
	//  result, e.g. SMP_BITWISE_XOR, then the USE of that pointer is NUMERIC within
	//  this xor instruction. If the DEF at the beginning of the SSA chain for the pointer
	//  is eventually marked as POINTER, then all USEs in the chain will be marked POINTER
	//  as well (see step 2 above). This inconsistency along the USE chain is perfectly
	//  acceptable in our type system. It is important to mark the USEs according to how
	//  we observe them being used, because consistent USEs will propagate back up to
	//  the DEF in step 3 above.

	bool changed;
	bool NewChange = false;
#if SMP_ANALYZE_INFER_TYPES_TIME
	bool DebugFlag2 = false;
	DebugFlag2 |= (0 == strcmp("Option", this->GetFuncName()));
	long NewChangeCount;
	long IterationCount = 0;
#endif
#if SMP_DEBUG_TYPE_INFERENCE
	bool DebugFlag = false;
	DebugFlag |= (0 == strcmp("__libc_csu_init", this->GetFuncName()));
#endif
	list<SMPInstr *>::iterator InstIter;
	SMPInstr *CurrInst;
	set<DefOrUse, LessDefUse>::iterator CurrDef;
	set<DefOrUse, LessDefUse>::iterator NextDef;
	list<SMPBasicBlock *>::iterator BlockIter;
	SMPBasicBlock *CurrBlock;
	ea_t InstAddr;

#if SMP_DEBUG_TYPE_INFERENCE
	if (DebugFlag) {
		this->Dump();
	}
#endif
	// One time only: Set the types of immediate values, flags register, stack and frame
	//  pointers, and floating point registers.
	if (FirstIter) {
		for (InstIter = this->Instrs.begin(); InstIter != this->Instrs.end(); ++InstIter) {
			CurrInst = (*InstIter);
#if SMP_DEBUG_TYPE_INFERENCE
			if (DebugFlag) {
				SMP_msg("SetImmedTypes for inst at %x: %s\n", CurrInst->GetAddr(), CurrInst->GetDisasm());
			}
#endif
			CurrInst->SetImmedTypes(this->UseFP);
			// Infer signedness, bit width, and other info from the nature of the instruction
			//  (e.g. loads from stack locations whose signedness has been inferred earlier
			//  in FindOutGoingArgSize(), or inherently signed arithmetic opcodes like signed
			//  or unsigned multiplies and divides).
			CurrInst->MDSetWidthSignInfo(this->UseFP);
		}
		// Check for signedness inferences from conditional branches at the end of blocks.
		for (BlockIter = this->Blocks.begin(); BlockIter != this->Blocks.end(); ++BlockIter) {
			CurrBlock = (*BlockIter);
			CurrBlock->MarkBranchSignedness();
		}

		// Find counter variables (e.g. init to zero or small constant, then just add or subtract small
		//  constant values. These cannot be POINTER and can be marked as NUMERIC.
		this->FindCounterVariables();
	}

	// Iterate until no more changes: set types in DEF and USE lists based on RTL
	//  operators and the instruction category, SSA DEF-USE chains, etc.
	do {
#if SMP_ANALYZE_INFER_TYPES_TIME
		if (DebugFlag2)
			++IterationCount;
#endif
#if 0
		do {
#endif
			changed = false;
#if SMP_ANALYZE_INFER_TYPES_TIME
			if (DebugFlag2)
				NewChangeCount = 0;
#endif
			// Step one: Infer types within instructions, context free.
			// Step two, propagating DEF types to all USEs, happens within step one
			//  whenever a DEF type is set for the first time.
			for (InstIter = this->Instrs.begin(); InstIter != this->Instrs.end(); ++InstIter) {
				CurrInst = (*InstIter);
#if SMP_DEBUG_TYPE_INFERENCE
				if (DebugFlag) SMP_msg("Inferring types for %s\n", CurrInst->GetDisasm());
#endif
				NewChange = CurrInst->InferTypes();
				changed = (changed || NewChange);
#if SMP_ANALYZE_INFER_TYPES_TIME
				if (DebugFlag2 && NewChange) {
					ea_t InstAddr = CurrInst->GetAddr();
					++NewChangeCount;
				}
#endif
			}
#if SMP_ANALYZE_INFER_TYPES_TIME
			if (DebugFlag2) {
				SMP_msg(" InferTypes iteration: %ld NewChangeCount: %ld \n", IterationCount, NewChangeCount);
			}
#endif
#if 0
		} while (changed);
#endif
#if SMP_DEBUG_TYPE_INFERENCE
		if (DebugFlag) SMP_msg("Finished type inference steps 1 and 2.\n");
#endif
		// Step three: If all USEs of an SSA name have the same type, but the DEF has no
		//  type, then infer that the DEF must have the same type.
		this->TypedDefs = 0;
		this->UntypedDefs = 0;
		this->TypedPhiDefs = 0;
		this->UntypedPhiDefs = 0;
		// This step of the type inference might converge faster if we used a reverse iterator
		//  to go through the instructions, because we could infer a DEF, propagate it to
		//  the right hand side by making SMPInstr::InferOperatorType() public and calling it
		//  on the SMP_ASSIGN operator after we set the type of the left hand side (DEF). Any
		//  additional DEF inferences would be triggered mostly in the upwards direction by
		//  setting the type of one or more USEs in the current instruction. How much time gain
		//  could be achieved by doing this sequence is questionable.  !!!!****!!!!****
		for (InstIter = this->Instrs.begin(); InstIter != this->Instrs.end(); ++InstIter) {
			CurrInst = (*InstIter);
			InstAddr = CurrInst->GetAddr();
			// Find any DEF that still has type UNINIT.
			CurrDef = CurrInst->GetFirstDef();
			while (CurrDef != CurrInst->GetLastDef()) {
				// Set erase() and insert() are needed to change types of DEFs, so
				//  get hold of the next iterator value now.
				NextDef = CurrDef;
				++NextDef;
				NewChange = false;
				if (UNINIT != CurrDef->GetType()) {
					++(this->TypedDefs);
				}
				else {
					op_t DefOp = CurrDef->GetOp();
					bool MemDef = (DefOp.type != o_reg);
					bool AliasedMemWrite = (MemDef && CurrDef->HasIndirectWrite());
					++(this->UntypedDefs);
					if (MDIsIndirectMemoryOpnd(DefOp, this->UseFP)  // relax this?
#if 0
						|| (o_mem == DefOp.type)
#endif
						|| AliasedMemWrite) {
						// Don't want to infer along DEF-USE chains for indirect
						//  memory accesses until we have alias analysis.
						++CurrDef;
						continue;
					}
					ea_t DefAddr = InstAddr;
					// Call inference method based on whether it is a block-local
					//  name or a global name.
					CurrBlock = CurrInst->GetBlock();
					if (CurrBlock->IsLocalName(DefOp)) {
						set<op_t, LessOp>::iterator NameIter;
						NameIter = CurrBlock->FindLocalName(DefOp);
						assert(CurrBlock->GetLastLocalName() != NameIter);
						unsigned int LocIndex = ExtractGlobalIndex(*NameIter);
						NewChange = CurrBlock->InferLocalDefType(DefOp, LocIndex, DefAddr);
						if (NewChange) {
							--(this->UntypedDefs);
							++(this->TypedDefs);
						}
						changed = (changed || NewChange);
					}
					else {
						// global name
						bool CallInst = ((CALL == CurrInst->GetDataFlowType())
							|| (INDIR_CALL == CurrInst->GetDataFlowType()));
						int DefSSANum = CurrDef->GetSSANum();
						SMPOperandType DefType = UNINIT;
						DefType = this->InferGlobalDefType(DefOp,
							DefSSANum, CurrBlock, CallInst, DefAddr);
						if (IsNotEqType(UNINIT, DefType)) {
							CurrDef = CurrInst->SetDefType(DefOp, DefType);
							--(this->UntypedDefs);
							++(this->TypedDefs);
							NewChange = true;
							// If we have one or more USEs of type POINTER and the
							//  other USEs are UNINIT, then InferGlobalDefType() will
							//  infer that it is a POINTER. We want to propagate POINTER
							//  to all the USEs now.
							if (IsDataPtr(DefType)) {
								this->ResetProcessedBlocks();
								CurrInst->GetBlock()->PropagateGlobalDefType(DefOp, DefType, DefSSANum, IsMemOperand(DefOp));
							}
						}
						changed = (changed || NewChange);
					} // end if local name ... else ...
				} // end if (UNINIT != CurrDef->GetType()) .. else ...
				CurrDef = NextDef;
			} // end while all DEFs in the DEF set
		} // end for all instructions
#if SMP_DEBUG_TYPE_INFERENCE
		if (DebugFlag) SMP_msg("Finished type inference step 3.\n");
#endif

		for (BlockIter = this->Blocks.begin(); BlockIter != this->Blocks.end(); ++BlockIter) {
			CurrBlock = (*BlockIter);
			changed |= CurrBlock->InferAllPhiDefTypes();
		}

#if SMP_DEBUG_TYPE_INFERENCE
		if (DebugFlag) SMP_msg("Finished unconditional phi type inference.\n");
#endif

#if SMP_CONDITIONAL_TYPE_PROPAGATION
		if (!changed) { // Try conditional type propagation
			changed |= this->ConditionalTypePropagation();
#if SMP_DEBUG_TYPE_INFERENCE
			if (DebugFlag) {
				SMP_msg("changed = %d after conditional type propagation.\n", changed);
			}
#endif
		}
#endif

	} while (changed);

	// With type inference finished, infer signedness from the types, e.g.
	//  POINTER and CODEPOINTER types must be UNSIGNED.
	if (FirstIter) { // Don't want profiler-dependent signedness in the system yet.
		for (InstIter = this->Instrs.begin(); InstIter != this->Instrs.end(); ++InstIter) {
			(*InstIter)->InferSignednessFromSMPTypes(this->UsesFramePointer());
		}
	}

	// Record the meet of all register types that reach RETURN instructions.
	this->MDFindReturnTypes();
	return;
} // end of SMPFunction::InferTypes()

// determine signedness and width info for all operands
void SMPFunction::InferFGInfo(void) {
	bool changed, NewChange;
	unsigned short IterCount = 0;
	list<SMPInstr *>::iterator InstIter;
	list<SMPBasicBlock *>::iterator BlockIter;
	SMPBasicBlock *CurrBlock;

	do {
		changed = false;
		++IterCount;
		for (InstIter = this->Instrs.begin(); InstIter != this->Instrs.end(); ++InstIter) {
			SMPInstr *CurrInst = (*InstIter);
			NewChange = CurrInst->InferFGInfo(IterCount);
			changed = (changed || NewChange);
		}
		if (changed) {
			for (BlockIter = this->Blocks.begin(); BlockIter != this->Blocks.end(); ++BlockIter) {
				CurrBlock = (*BlockIter);
				CurrBlock->PropagatePhiFGInfo();
			}
		}
#if STARS_AGGRESSIVE_SIGNEDNESS_PROPAGATION
		if (!changed) {
			changed = this->PropagateSignedness();
		}
#endif
	} while (changed);

	return;
} // end of SMPFunction::InferFGInfo()

// Apply the profiler information to this function once we've inferred everything we can about it.
void SMPFunction::ApplyProfilerInformation(ProfilerInformation* pi)
{
	assert(pi);

	// If no profiler annotations are available, save time.
	if (0 == pi->GetProfilerAnnotationCount())
		return;

	SetIsSpeculative(true);	

	list<SMPInstr *>::iterator InstIter;
	set<DefOrUse, LessDefUse>::iterator CurrDef, NextDef;
	
	bool DebugFlag = false;
#if SMP_DEBUG_PROFILED_TYPE_INFERENCE
	DebugFlag |= (0 == strcmp("dohanoi", this->GetFuncName()));
#endif

	// for each instruction in this function 
	for (InstIter = this->Instrs.begin(); InstIter != this->Instrs.end(); ++InstIter) {
		SMPInstr *CurrInst = (*InstIter);
		// lookup whether a load at this instruction was profiled as always numeric 
		InstructionInformation* ii = pi->GetInfo(CurrInst->GetAddr());
		if (ii && DebugFlag)
			SMP_msg("Found instruction information for %lx\n", (unsigned long) CurrInst->GetAddr());
		if (ii && ii->isNumeric()) {
#if SMP_DEBUG_PROFILED_TYPE_INFERENCE
			SMP_msg("Found instruction information for %lx and it's numeric!\n", (unsigned long) CurrInst->GetAddr());
#endif
			CurrInst->UpdateMemLoadTypes((SMPOperandType)(NUMERIC|PROF_BASE));
		}

		// lookup whether this instruction has been profiled as an indirect call
		set<ea_t> indirect_call_targets = pi->GetIndirectCallTargets(CurrInst->GetAddr());

		for (set<ea_t>::iterator ict_iter = indirect_call_targets.begin();
			ict_iter != indirect_call_targets.end();
			++ict_iter)
		{
			ea_t target = *ict_iter;
			pair<set<ea_t>::iterator, bool> InsertResult;
			InsertResult = this->IndirectCallTargets.insert(target);
			if (InsertResult.second && (!vector_exists(target, AllCallTargets)))
				AllCallTargets.push_back(target);

		}

	}
	return;
}	// end of SMPFunction::ApplyProfilerInformation

// For the UNINIT type DEF DefOp, see if all its USEs have a single type.
//  If so, set the DEF to that type and return type,
//  else return UNINIT.
// If DefAddr == BADADDR, then the DEF is in a Phi function, not an instruction.
SMPOperandType SMPFunction::InferGlobalDefType(op_t DefOp, int SSANum, SMPBasicBlock *DefBlock, bool CallInst, ea_t DefAddr) {
	bool DebugFlag = false;
	bool FoundNumeric = false;
	bool FoundPointer = false;
	bool FoundUnknown = false;
	bool FoundUninit = false;
	bool FoundDEF;
	bool DefEscapes = true;

#if SMP_DEBUG_TYPE_INFERENCE
	DebugFlag |= (0 == strcmp("mem_init", this->GetFuncName()));
#endif

	if (DebugFlag) {
		SMP_msg("InferGlobalDefType for SSANum %d of ", SSANum);
		PrintOperand(DefOp);
		SMP_msg("\n");
	}

	vector<SMPInstr *>::iterator InstIter;

	assert(0 <= SSANum);
	set<DefOrUse, LessDefUse>::iterator CurrUse, CurrDef;
	// Go through all instructions in the block and find the instructions
	//  that have USEs of DefOp with SSANum. If all USEs in the chain have
	//  a single type (other than UNINIT), change the DEF type to match the
	//  USE type and set changed to true.
	SMPOperandType UseType = UNINIT;
	SMPOperandType PtrType = UNINIT;

	if (BADADDR == DefAddr) { // DEF is in a Phi function
		FoundDEF = true;
	}
	else { // DEF is in an instruction
		FoundDEF = false; // need to see the DefAddr first
	}

	for (InstIter = DefBlock->GetFirstInst(); InstIter != DefBlock->GetLastInst(); ++InstIter) {
		SMPInstr *CurrInst = (*InstIter);
		if ((!FoundDEF) && (DefAddr == CurrInst->GetAddr())) {
			FoundDEF = true;
		}
		else if (FoundDEF) {
			CurrDef = CurrInst->FindDef(DefOp);
			if (CurrDef != CurrInst->GetLastDef()) {
				// Found re-DEF of DefOp.
				DefEscapes = false;
			}
		}
		// NOTE: Following instructions should be inside if (FoundDEF) condition.
		CurrUse = CurrInst->FindUse(DefOp);
		if (CurrUse != CurrInst->GetLastUse()) { // found a USE of DefOp
			if (CurrUse->GetSSANum() == SSANum) { // matched SSA number
				UseType = CurrUse->GetType();
				FoundNumeric |= (IsNumeric(UseType));
				FoundUnknown |= (IsUnknown(UseType));
				FoundUninit |= (IsEqType(UNINIT, UseType));
				if (IsDataPtr(UseType)) {
					if (FoundPointer) {
						if (IsNotEqType(PtrType, UseType)) {
#if SMP_DEBUG_TYPE_INFERENCE
							SMP_msg("WARNING: Differing ptr types in global chain:");
							SMP_msg(" Prev: %d Current: %d %s\n", PtrType, UseType,
								CurrInst->GetDisasm());
#endif
							PtrType = POINTER;
						}
					}
					else {
						FoundPointer = true;
						PtrType = UseType;
					}
				}
			} // end if matched SSA #
		} // end if found a USE of DefOp
	} // end for all instructions

	if (DefEscapes) { // did not find re-def
		DefEscapes = DefBlock->IsLiveOut(DefOp);
	}


	if (DefEscapes) { // Need to recurse into successor blocks
		list<SMPBasicBlock *>::iterator SuccIter;
		ea_t TempAddr;
		this->ResetProcessedBlocks(); // set up recursion
		for (SuccIter = DefBlock->GetFirstSucc(); SuccIter != DefBlock->GetLastSucc(); ++SuccIter) {
			SMPBasicBlock *CurrBlock = (*SuccIter);
			set<SMPPhiFunction, LessPhi>::iterator PhiIter = CurrBlock->FindPhi(DefOp);
			TempAddr = DefAddr;
			if (PhiIter != CurrBlock->GetLastPhi()) {
				TempAddr = BADADDR;  // signals that DefOp will get re-DEFed in a Phi function.
			}
			else if (BADADDR == TempAddr) { // was BADADDR coming in to this function
				// We don't want to pass BADADDR down the recursion chain, because it will be interpreted
				//  by each successor block to mean that DefOp was a Phi USE that got re-DEFed in a Phi function
				//  within itself. Pass the dummy address that indicates LiveIn to the block.
				TempAddr = CurrBlock->GetFirstAddr() - 1;
			}
			// Should we screen the recursive call below using CurrBlock->IsLiveIn(DefOp) for speed?  !!!!****!!!!
			CurrBlock->InferGlobalDefType(DefOp, SSANum, TempAddr, FoundNumeric, FoundPointer, FoundUnknown, FoundUninit, PtrType);
		}
	}

	// Do we have a consistent type?
	// If we see any definite POINTER uses, we must set the DEF
	//  to type POINTER or a refinement of it.
	if (FoundPointer)
		UseType = PtrType;
	else if (FoundNumeric && !FoundUninit && !FoundUnknown)
		UseType = NUMERIC;
	else
		return UNINIT; // no POINTER, but no consistent type

	assert(UNINIT != UseType);
	if (DebugFlag) SMP_msg("Inferring global DEF of type %d\n", UseType);

	return UseType;
} // end of SMPFunction::InferGlobalDefType()

// Mark NUMERIC (and propagate) any DEF that starts at small immed. value and gets only small inc/dec operations.
void SMPFunction::FindCounterVariables(void) {
	// We define a counter variable as one that starts out as a small immediate value and then is only updated
	//  via small additions and subtractions. This cannot produce a POINTER, so it must be NUMERIC. This routine
	//  helps get the NUMERIC inference past the phi function barrier, e.g.:
	//
	//  mov eax,0    ; might be NULL POINTER or might be NUMERIC
	//  eax2 := phi(eax1, eax0)  ; still don't know type
	//  label1:    ; top of loop
	//   :
	//  add eax,4  ; increment induction variable; eax1 := eax0 + 4
	//  cmp eax,looplimit
	//  jl label1
	//
	//  Viewed in isolation, adding 4 to EAX could be a pointer operation or a numeric operation, and
	//   the same is true for initializing to zero. Viewed together, these statements obviously cannot be
	//   producing a POINTER value, as 0,4,8, etc. are not a sequence of POINTER values.

	list<SMPInstr *>::iterator InstIter;
	for (InstIter = this->Instrs.begin(); InstIter != this->Instrs.end(); ++InstIter) {
		SMPInstr *CurrInst = (*InstIter);
		bool ValueFound;
		uval_t ConstValue;
		if (CurrInst->MDIsSimpleAssignment(ValueFound, ConstValue)) {
			if (ValueFound && (0 == ConstValue)) {
				// Start small: Find init to zero, then track it. Init to small values after we test.
				set<DefOrUse, LessDefUse>::iterator DefIter = CurrInst->GetFirstNonFlagsDef();
				if (DefIter == CurrInst->GetLastDef()) {
					// Must have been a simple assignment to a flag, e.g. clc (clear the carry flag).
					continue;
				}
				op_t DefOp = DefIter->GetOp();
				if (o_reg == DefOp.type) {
					list<pair<int, ea_t> > CounterSSANums;  // SSA numbers that are definitely counters for DefOp
					int DefSSANum = DefIter->GetSSANum();
					ea_t DefAddr = CurrInst->GetAddr();
					pair<int, ea_t> ListItem(DefSSANum, DefAddr);
					CounterSSANums.push_back(ListItem);
					SMPBasicBlock *CurrBlock = CurrInst->GetBlock();
					int BlockNum = CurrBlock->GetNumber();
					bool LocalName = CurrBlock->IsLocalName(DefOp);
					if (this->CounterVarHelper(DefOp, DefSSANum, BlockNum, LocalName, CounterSSANums)) {
						while (!CounterSSANums.empty()) {
							int CurrSSANum = CounterSSANums.front().first;
							ea_t CurrDefAddr = CounterSSANums.front().second;
							bool Propagated;
							if (LocalName) {
								Propagated = CurrBlock->PropagateLocalDefType(DefOp, NUMERIC, CurrDefAddr, CurrSSANum, false);
							}
							else {
								this->ResetProcessedBlocks();
								Propagated = CurrBlock->PropagateGlobalDefType(DefOp, NUMERIC, CurrSSANum, false);
							}
							CounterSSANums.pop_front();
						}
					}
				} // end if o_reg type
			} // end if const value of 0
		} // end if simple assignment
	} // end for all instructions

	return;
} // end of SMPFunction::FindCounterVariables()

// recursive helper for FindCounterVariables()
// Return true if we added to the DefSSANums list.
bool SMPFunction::CounterVarHelper(op_t DefOp, int DefSSANum, int BlockNum, bool LocalName, list<pair<int, ea_t> > CounterSSANums) {
	bool ListExpanded = false;
	size_t IncomingListSize = CounterSSANums.size();
	set<int> NonEscapingRegisterHashes;

	// First, examine the Phi list to find uses of DefOp/DefSSANum.
	// Next, examine instructions to find uses of DefOp/DefSSANum. They must be counter operations if DefOp is re-defed.

	// As a first cut, we will just find the following pattern:
	// 1. Counter-style DEF reaches the end of the current block.
	// 2. Successor block is a single-block loop with counter DEF appearing as a USE in a phi function.
	// 3. Within the single-block loop, Phi DEF is used in a counter-style operation, with new DEF becoming a Phi USE at top of block.
	// We will expand this to loops that are not in a single block later.
	SMPBasicBlock *CurrBlock = this->GetBlockByNum((size_t) BlockNum);
	assert(NULL != CurrBlock);
	ea_t DefAddr = CounterSSANums.front().second;
	if (CurrBlock->DoesDefReachBlockEnd(DefAddr, DefOp, DefSSANum, NonEscapingRegisterHashes)) {
		NonEscapingRegisterHashes.clear(); // Not memoizing for this use of DoesDefReachBlockEnd()
		bool LoopSuccFound = false;
		list<SMPBasicBlock *>::iterator SuccIter;
		SMPBasicBlock *SuccBlock;
		int PhiDefSSANum;
		set<SMPPhiFunction, LessPhi>::iterator PhiIter;
		for (SuccIter = CurrBlock->GetFirstSucc(); SuccIter != CurrBlock->GetLastSucc(); ++SuccIter) {
			SuccBlock = (*SuccIter);
			if (SuccBlock->IsSelfLoop()) {
				PhiIter = SuccBlock->FindPhi(DefOp);
				if (PhiIter != SuccBlock->GetLastPhi()) { // Found a Phi function that could match
					size_t PhiSize = PhiIter->GetPhiListSize();
					for (size_t index = 0; index < PhiSize; ++index) {
						int PhiUseSSANum = PhiIter->GetUseSSANum(index);
						if (PhiUseSSANum == DefSSANum) {
							// Our DEF is a USE in the phi function at the top of SuccBlock. Success.
							PhiDefSSANum = PhiIter->GetDefSSANum();
							LoopSuccFound = true;
							break;
						}
					}
				}
				if (LoopSuccFound) {
					break;
				}
			}
		}
		if (LoopSuccFound) {
			// SuccBlock points to a one-block loop with PhiIter pointing to a phi function that has
			//  DefOp/DefSSANum as a phi use, and DefOp/PhiDefSSANum as its phi def. Are the uses of
			//  DefOp/PhiDefSSANum within SuccBlock merely counter redefinitions?
			vector<SMPInstr *>::iterator InstIter;
			for (InstIter = SuccBlock->GetFirstInst(); InstIter != SuccBlock->GetLastInst(); ++InstIter) {
				set<DefOrUse, LessDefUse>::iterator DefIter, UseIter;
				SMPInstr *CurrInst = (*InstIter);
				DefIter = CurrInst->FindDef(DefOp);
				if (DefIter != CurrInst->GetLastDef()) {
					// Found a redefinition of DefOp. Is it just a counter operation that redefines DefOp?
					if (CurrInst->IsCounterOperation()) {
						// We will add the new DEF SSA # to the list of counter SSAs.
						pair<int, ea_t> CounterPair(DefIter->GetSSANum(), CurrInst->GetAddr());
						CounterSSANums.push_back(CounterPair);
						// We don't need to push the PhiDefSSANum discovered earlier, because if
						//  it follows the simple pattern of only using two counter DEFs as its USEs,
						//  one from before the loop and one from within the loop, then both of its USEs
						//  will get set to NUMERIC and propagation will occur naturally. If it does not
						//  fit this simple pattern, we don't want to force it to be NUMERIC yet.
					}
					else {
						// Problem: we redefined DefOp with a non-counter operation. We want to terminate
						//  the chain of detection of counter variables.
						break;
					}
				}
				else {
					UseIter = CurrInst->FindUse(DefOp);
					if (UseIter != CurrInst->GetLastUse()) {
						// Found USE of DefOp. See if it is a POINTER use, which would
						//  invalidate the hypothesis that DefOp is a counter.
						SMPOperandType UseType = UseIter->GetType();
						if (IsDataPtr(UseType) || IsEqType(UseType, CODEPTR)) {
							// Any apparent counter operations so far have really been pointer arithmetic.
							//  We need to restore the list to its incoming state.
							while (IncomingListSize < CounterSSANums.size()) {
								CounterSSANums.pop_back();
							}
							break; // terminate search
						}
					}
				}
			} // end for all insts in SuccBlock
		} // end if LoopSuccFound
	} // end if original pre-loop DEF reaches the end of its block

	ListExpanded = (CounterSSANums.size() > IncomingListSize);
	return ListExpanded;
} // end of SMPFunction::CounterVarHelper()

#define SMP_SIMPLE_CONDITIONAL_TYPE_PROPAGATION 1
#if SMP_SIMPLE_CONDITIONAL_TYPE_PROPAGATION
// The simple form of conditional type propagation observes that we
//  simply need to apply the meet operator over Phi function USEs and
//  then propagate any DEF type changes using PropagateGlobalDefType().
//  The outermost iteration over all type inference methods in InferTypes()
//  will take care of all the propagation that is handled by the work list
//  processing in the textbook algorithm.
// Iteration convergence might be slower in the simple approach, but the code
//  is much simpler to debug.
bool SMPFunction::ConditionalTypePropagation(void) {
	bool changed = false;
	SMPBasicBlock *CurrBlock;
	vector<SMPBasicBlock *>::iterator CurrRPO;
	set<SMPPhiFunction, LessPhi>::iterator CurrPhi;

	for (CurrRPO = this->RPOBlocks.begin(); CurrRPO != this->RPOBlocks.end(); ++CurrRPO) {
		CurrBlock = *CurrRPO;
		SMPOperandType MeetType;
		for (CurrPhi = CurrBlock->GetFirstPhi(); CurrPhi != CurrBlock->GetLastPhi(); ++CurrPhi) {
			MeetType = CurrPhi->ConditionalMeetType();
			// Here we use a straight equality test, not our macros,
			//  because we consider it a change if the MeetType is
			//  profiler derived and the DEFType is not.
			if (MeetType == CurrPhi->GetDefType())
				continue;
			// Change the DEF type to the MeetType and propagate.
			op_t DefOp = CurrPhi->GetAnyOp();
			bool IsMemOp = (o_reg != DefOp.type);
			CurrPhi = CurrBlock->SetPhiDefType(DefOp, MeetType);
			changed = true;
			this->ResetProcessedBlocks();
			changed |= CurrBlock->PropagateGlobalDefType(DefOp,
				MeetType, CurrPhi->GetDefSSANum(), IsMemOp);
		} // end for all phi functions in the current block
	} // end for all blocks

	return changed;
} // end of SMPFunction::ConditionalTypePropagation()

#else  // not SMP_SIMPLE_CONDITIONAL_TYPE_PROPAGATION

// Apply the SCC (Sparse Conditional Constant) propagation algorithm to
//  propagate types starting from unresolved Phi DEFs.
bool SMPFunction::ConditionalTypePropagation(void) {
	bool changed = false;

	// Collections of Phi functions and instructions that have a DEF
	//  with type UNINIT for the current global name.
	map<int, set<SMPPhiFunction, LessPhi>::iterator> UninitDEFPhis;
	vector<list<SMPInstr>::iterator> UninitDEFInsts;

	// Work lists of Phi functions and instructions that need to be processed
	//  according to the SCC algorithm.
	list<map<int, set<SMPPhiFunction, LessPhi>::iterator>::iterator> PhiWorkList;
	list<vector<list<SMPInstr>::iterator>::iterator> InstWorkList;

	// Iterate through all global names that are either (1) registers
	//  or (2) stack locations in SAFE functions.
	set<op_t, LessOp>::iterator CurrGlob;
	for (CurrGlob = this->GetFirstGlobalName(); CurrGlob != this->GetLastGlobalName(); ++CurrGlob) {
		op_t GlobalOp = *CurrGlob;
		list<SMPBasicBlock>::iterator CurrBlock;
		vector<list<SMPBasicBlock>::iterator>::iterator CurrRPO;
		if (MDIsIndirectMemoryOpnd(GlobalOp, this->UseFP))
			continue; // need alias analysis to process indirect accesses
		if ((GlobalOp.type != o_reg)
			&& (!((this->GetReturnAddressStatus() == FUNC_SAFE) && MDIsStackAccessOpnd(GlobalOp, this->UseFP))))
			continue; // not register, not safe stack access

		// Set up a map (indexed by SSANum) of iterators to Phi functions
		//  for the current global name that have UNINIT as the Phi DEF type.
		UninitDEFPhis.clear();
		UninitDEFInsts.clear();
		for (CurrRPO = this->RPOBlocks.begin(); CurrRPO != this->RPOBlocks.end(); ++CurrRPO) {
			CurrBlock = *CurrRPO;
			set<SMPPhiFunction, LessPhi>::iterator CurrPhi;
			CurrPhi = CurrBlock->FindPhi(GlobalOp);
			if (CurrPhi != CurrBlock->GetLastPhi()) {
				// Found Phi function for current global name.
				if (IsEqType(CurrPhi->GetDefType(), UNINIT)) {
					// Phi DEF is UNINIT; add Phi to the map.
					pair<int, set<SMPPhiFunction, LessPhi>::iterator> TempPair(CurrPhi->GetDefSSANum(), CurrPhi);
					bool Inserted = false;
					map<int, set<SMPPhiFunction, LessPhi>::iterator>::iterator WhereIns;
					pair<map<int, set<SMPPhiFunction, LessPhi>::iterator>::iterator, bool> Result(WhereIns, Inserted);
					Result = UninitDEFPhis.insert(TempPair);
					assert(Result.second == true);
				}
			}
		} // end for all blocks

		// If any Phi DEF had UNINIT as its type, set up a vector of
		//  iterators to instructions that have UNINIT as the DEF type
		//  for the current global name.
		if (UninitDEFPhis.empty())
			continue;
		list<SMPInstr *>::iterator InstIter;
		for (InstIter = this->Instrs.begin(); InstIter != this->Instrs.end(); ++InstIter) {
			SMPInstr *CurrInst = (*InstIter);
			set<DefOrUse, LessDefUse>::iterator CurrDef = CurrInst->FindDef(GlobalOp);
			if (CurrDef != CurrInst->GetLastDef()) {
				// Found DEF of current global name.
				if (IsEqType(UNINIT, CurrDef->GetType())) {
					UninitDEFInsts.push_back(CurrInst);
				}
			}
		} // end for all instructions

		// Put all UNINIT Phi DEFs that have at least one USE
		//  that is not UNINIT onto the PhiWorkList.
		map<int, set<SMPPhiFunction, LessPhi>::iterator>::iterator CurrUnPhi;
		for (CurrUnPhi = UninitDEFPhis.begin(); CurrUnPhi != UninitDEFPhis.end(); ++CurrUnPhi) {
			pair<int, set<SMPPhiFunction, LessPhi>::iterator> PhiDefPair(*CurrUnPhi);
			if (PhiDefPair.second->HasTypedUses()) {
				PhiWorkList.push_back(CurrUnPhi);
			}
		}

		// Iterate until both work lists are empty:
		while (!(PhiWorkList.empty() && InstWorkList.empty())) {
			// Process Phi items first.
			while (!PhiWorkList.empty()) {
				// If applying the meet operator over the Phi USE types
				//  would produce a new DEF type, change the DEF type and
				//  propagate it, adding Phi functions and instructions that
				//  received the propagated type to their respective work lists.
				map<int, set<SMPPhiFunction, LessPhi>::iterator>::iterator MapIter;
				MapIter = PhiWorkList.front();
				PhiWorkList.pop_front();  // remove from work list
				pair<int, set<SMPPhiFunction, LessPhi>::iterator> PhiDefPair;
				PhiDefPair.first = MapIter->first;
				PhiDefPair.second = MapIter->second;
				set<SMPPhiFunction, LessPhi>::iterator CurrPhi = PhiDefPair.second;
				SMPOperandType MeetType = CurrPhi->ConditionalMeetType();
				// Here we use a straight equality test, not our macros,
				//  because we consider it a change if the MeetType is
				//  profiler derived and the DEFType is not.
				if (MeetType == CurrPhi->GetDefType())
					continue;
				// At this point, we need to set the DEFType to the MeetType
				//  and propagate the change. We have a map of all the
				//  critical Phi functions for this global name, as well
				//  as a vector of the relevant instructions for this name.
				CurrPhi->SetDefType(MeetType);
				changed = true;
				int DefSSANum = CurrPhi->GetDefSSANum();
				map<int, set<SMPPhiFunction, LessPhi>::iterator>::iterator PhiIter;
				vector<list<SMPInstr>::iterator>::iterator InstIter;
				// Propagate to Phi functions first.
				for (PhiIter = UninitDEFPhis.begin(); PhiIter != UninitDEFPhis.end(); ++PhiIter) {
					if (DefSSANum == PhiIter->first)
						continue;  // Skip the Phi that we just changed
					for (size_t index = 0; index < PhiIter->second->GetPhiListSize(); ++index) {
						if (DefSSANum == PhiIter->second->GetUseSSANum(index)) {
							// Matched SSA # to USE. Propagate new type.
							PhiIter->second->SetRefType(index, MeetType);
							// Add this phi function to the work list.
							PhiWorkList.push_back(PhiIter);
						}
					}
				}
#define SMP_COND_TYPE_PROP_TO_INSTS 0
#if SMP_COND_TYPE_PROP_TO_INSTS
				// Propagate to instructions with uninit DEFs of global name.
				//  The idea is that the instructions that hold up type propagation
				//  are the ones that USE and then DEF the same global name.
				//  For example, "increment EAX" has to know the type of
				//  the USE of EAX in order to set the type of the DEF.
#endif
			} // end while the PhiWorkList is not empty
#if SMP_COND_TYPE_PROP_TO_INSTS
			// The PhiWorkList is empty at this point, so process
			//  instructions on the InstWorkList.
#endif
		} // end while both work lists are not empty

	} // end for all global names
	return changed;
} // end of SMPFunction::ConditionalTypePropagation()
#endif  // end if SMP_SIMPLE_CONDITIONAL_TYPE_PROPAGATION else ...

// Propagate signedness FG info from DEFs to USEs whenever there is no USE sign info.
bool SMPFunction::PropagateSignedness(void) {
	bool changed = false;
#if STARS_AGGRESSIVE_SIGNEDNESS_PROPAGATION
	map<int, struct FineGrainedInfo>::iterator UseFGIter, DefFGIter;
	list<SMPBasicBlock *>::iterator BlockIter;
	for (UseFGIter = this->GlobalUseFGInfoBySSA.begin(); UseFGIter != this->GlobalUseFGInfoBySSA.end(); ++UseFGIter) {
		struct FineGrainedInfo UseFG = UseFGIter->second;
		if (0 == (UseFG.SignMiscInfo & FG_MASK_SIGNEDNESS_BITS)) {
			// No signedness info. Propagate any signedness info from DEF.
			int UseHashValue = UseFGIter->first;
			unsigned short DefSignMask = this->GetDefSignMiscInfo(UseHashValue);
			DefSignMask &= FG_MASK_SIGNEDNESS_BITS;
			if (0 != DefSignMask) {
				// DEF has signedness info.
				UseFGIter->second.SignMiscInfo |= DefSignMask;
				changed = true;
			}
		}
	}
	// See if we have DEF signedness info for DEFs with no corresponding USE map entries.
	for (DefFGIter = this->GlobalDefFGInfoBySSA.begin(); DefFGIter != this->GlobalDefFGInfoBySSA.end(); ++DefFGIter) {
		struct FineGrainedInfo DefFG = DefFGIter->second;
		unsigned short DefSignMask = (DefFG.SignMiscInfo & FG_MASK_SIGNEDNESS_BITS);
		if (0 != DefSignMask) {
			// Has signedness info. See if USE has no entry.
			int DefHashValue = DefFGIter->first;
			UseFGIter = this->GlobalUseFGInfoBySSA.find(DefHashValue);
			if (UseFGIter == this->GlobalUseFGInfoBySSA.end()) {
				this->UpdateUseSignMiscInfo(DefHashValue, DefSignMask);
				changed = true;
			}
		}
	}
	// Do the same processsing for block-local registers.
	for (BlockIter = this->Blocks.begin(); BlockIter != this->Blocks.end(); ++BlockIter) {
		bool NewChange = (*BlockIter)->PropagateDEFSignedness();
		changed = changed || NewChange;
	}
#endif
	return changed;
} // end of SMPFunction::PropagateSignedness()

// Detect and mark special cases before emitting numeric error annotations.
void SMPFunction::MarkSpecialNumericErrorCases(void) {
	list<SMPBasicBlock *>::iterator BlockIter;
	vector<SMPInstr *>::reverse_iterator InstIter;
	SMPBasicBlock *CurrBlock;
	SMPInstr *CurrInst;
	bool DebugFlag = (0 == strcmp("sub_8063BE0", this->GetFuncName()));

	set<int> NonEscapingRegisterHashes; // memoization optimization: set of register/SSA# hashes that do not reach end of block

#if STARS_BUILD_LOOP_BITSET
	// Now that we know how many loops we have, we can allocate the loops data structure.
	this->FuncLoopsByBlock.resize(this->BlockCount);
	for (size_t BlockIndex = 0; BlockIndex < this->BlockCount; ++BlockIndex) {
		this->FuncLoopsByBlock.at(BlockIndex).AllocateBits(this->LoopCount);
	}

	if (this->LoopCount > 0) {
		this->DetectLoops();
	}
#endif

	// Special-case preparatory analyses.
	for (BlockIter = this->Blocks.begin(); BlockIter != this->Blocks.end(); ++BlockIter) {
		CurrBlock = (*BlockIter);
		CurrBlock->AnalyzePrepForNumericAnnotations();
	}

	if (this->LoopCount == 0) {
		return;
	}

	// Loop through blocks and detect tight loops of hashing arithmetic.
	for (BlockIter = this->Blocks.begin(); BlockIter != this->Blocks.end(); ++BlockIter) {
		CurrBlock = (*BlockIter);
		int BlockNum = CurrBlock->GetNumber();
#if 0
		if (CurrBlock->IsLoopTailBlock() && CurrBlock->IsLoopHeaderBlock()) {
#else
		if (this->IsBlockInAnyLoop(BlockNum)) {
#endif
			// We have a one-block loop to itself. This is the simple case we want
			//  to start with, as hash functions we have observed are tight loops of arithmetic computations.
			//  The next question is whether we can find the kind of shift/rotate that is common to hashing, plus
			//  at least one addition.
			bool ShiftFound = false;
			bool AddFound = false;
			op_t DefOp = InitOp, AddDefOp = InitOp;
			set<DefOrUse, LessDefUse>::iterator DefIter;
			NonEscapingRegisterHashes.clear();

			for (InstIter = CurrBlock->GetRevInstBegin(); InstIter != CurrBlock->GetRevInstEnd(); ++InstIter) {
				CurrInst = (*InstIter);
				if ((!ShiftFound) && CurrInst->MDIsHashingArithmetic()) {
					// If the operand being shifted is never used in any assignment or arithmetic
					//  except as an address register computation within a memory operand, then the
					//  shifted value does not reach the top of the loop and get shifts accumulated.
					//  In that case, we are not dealing with a shift-and-add type of hash function.
					//  So, do not claim success unless the later addition DEF reaches the end
					//  of the block.
					DefIter = CurrInst->GetFirstNonFlagsDef();
					ea_t DefAddr = CurrInst->GetAddr();
					DefOp = DefIter->GetOp();
					ea_t AdditionAddr = BADADDR;
					ShiftFound = CurrBlock->IsDefInvolvedInAddition(DefAddr, DefOp, AdditionAddr);
					if (ShiftFound) {
						SMPInstr *AdditionInst = this->GetInstFromAddr(AdditionAddr);
						DefIter = AdditionInst->GetFirstNonFlagsDef();
						AddDefOp = DefIter->GetOp();
						AddFound = CurrBlock->DoesDefReachBlockEnd(AdditionAddr, AddDefOp, DefIter->GetSSANum(), NonEscapingRegisterHashes);
						if (AddFound) {
							break;
						}
						else {
							// Reset ShiftFound and look for a different shift.
							ShiftFound = false;
						}
					}
				}
			}
			if (ShiftFound && AddFound) {
				// We found a tight hashing loop. Mark all the overflowing and underflowing opcodes as benign.
				//  NOTE: We could do loop-variant analysis to ensure that the shifted and added values are actually
				//  changing within the loop, but if they are not, they are probably not exploitable overflows anyway,
				//  and the loop-invariant overflow would happen on every loop iteration based on initial values, which
				//  is a pattern we have never seen for this kind of code.
				vector<SMPInstr *>::iterator ForwardInstIter;
				for (ForwardInstIter = CurrBlock->GetFirstInst(); ForwardInstIter != CurrBlock->GetLastInst(); ++ForwardInstIter) {
					CurrInst = (*ForwardInstIter);
					if (CurrInst->MDIsOverflowingOpcode() || CurrInst->MDIsUnderflowingOpcode() || CurrInst->MDIsLoadEffectiveAddressInstr()) {
						CurrInst->SetHashOperation();
					}
				}
			}
		} // end if loop header and loop tail
	} // end for all blocks

	NonEscapingRegisterHashes.clear();
	return;
} // end of SMPFunction::MarkSpecialNumericErrorCases()

// Emit all annotations for the function, including all per-instruction
//  annotations.
void SMPFunction::EmitAnnotations(FILE *AnnotFile, FILE *InfoAnnotFile) {
	// Emit annotation for the function as a whole.
	list<SMPBasicBlock *>::iterator BlockIter;
	SMPBasicBlock *CurrBlock;
	bool FuncHasProblems = ((!this->AnalyzedSP) || (!this->HasGoodRTLs()) || (this->HasUnresolvedIndirectCalls())
		|| (this->HasUnresolvedIndirectJumps()) || (this->HasSharedChunks()));

	if (this->StaticFunc) {
		SMP_fprintf(AnnotFile,	"%10lx %6zu FUNC LOCAL  %s ", (unsigned long) this->FuncInfo.startEA,
			this->Size, this->GetFuncName());
	}
	else {
		SMP_fprintf(AnnotFile,	"%10lx %6zu FUNC GLOBAL %s ", (unsigned long) this->FuncInfo.startEA,
			this->Size, this->GetFuncName());
	}
	switch (this->GetReturnAddressStatus())
	{
		case FUNC_UNKNOWN:
		{
			SMP_fprintf(AnnotFile, "FUNC_UNKNOWN ");
			break;
		}
		case FUNC_SAFE:
		{
			SMP_fprintf(AnnotFile, "FUNC_SAFE ");
			break;
		}
		case FUNC_UNSAFE:
		{
			SMP_fprintf(AnnotFile, "FUNC_UNSAFE ");
			break;
		}
		default:
			assert(0);	
	}
	if (this->UseFP) {
		SMP_fprintf(AnnotFile, "USEFP ");
	}
	else {
		SMP_fprintf(AnnotFile, "NOFP ");
	}
	if (this->FuncInfo.does_return()) {
		SMP_fprintf(AnnotFile, "RET ");
	}
	else {
		SMP_fprintf(AnnotFile, "NORET ");
	}

	if (this->IsLeaf())
		SMP_fprintf(AnnotFile, "FUNC_LEAF ");
	// store the return address
	SMP_fprintf(AnnotFile,"%10lx ", (unsigned long) (this->FuncInfo.endEA - 1));

	if (this->IsLibFunc())
		SMP_fprintf(AnnotFile, "LIBRARY ");
	SMP_fprintf(AnnotFile, "\n");

	// Emit annotations about how to restore register values
	SMP_fprintf(AnnotFile, "%10lx %6d FUNC FRAMERESTORE ", (unsigned long) this->FuncInfo.startEA, 0);
	for(int i = R_ax; i <= R_di; i++)
	{
		SMP_fprintf(AnnotFile, "%d %d %d ", i, this->SavedRegLoc[i], this->ReturnRegTypes[i]);
	}
	SMP_fprintf(AnnotFile, "ZZ\n");

	SMP_fprintf(AnnotFile, "%10lx %6d FUNC MMSAFENESS ", (unsigned long) this->FuncInfo.startEA, 0);
	if (!IsSpecSafe())
		SMP_fprintf(AnnotFile, "UNSAFE\n");
	else if (!IsSafe())
		SMP_fprintf(AnnotFile, "SPECSAFE\n");
	else {
		assert(IsSafe());
		SMP_fprintf(AnnotFile, "SAFE\n");
	}

	// If function has problems that limited our analyses, emit an information annotation so that
	//  other tools can be aware of which analyses will be sound.
	if (FuncHasProblems) {
		SMP_fprintf(InfoAnnotFile,	"%10lx %6zu FUNC PROBLEM %s ", (unsigned long) this->FuncInfo.startEA,
			this->Size, this->GetFuncName());
		if (!this->AnalyzedSP) {
			SMP_fprintf(InfoAnnotFile, "STACKANALYSIS ");
		}
		if (this->HasSharedChunks()) {
			SMP_fprintf(InfoAnnotFile, "CHUNKS ");
		}
		if (this->HasUnresolvedIndirectJumps()) {
			SMP_fprintf(InfoAnnotFile, "JUMPUNRESOLVED ");
		}
		if (this->HasUnresolvedIndirectCalls()) {
			SMP_fprintf(InfoAnnotFile, "CALLUNRESOLVED ");
		}
		if (!this->HasGoodRTLs()) {
			SMP_fprintf(InfoAnnotFile, "BADRTLS ");
		}
		SMP_fprintf(InfoAnnotFile, "\n");
	}

	// Find and mark special cases that will affect the integer error annotations.
	this->MarkSpecialNumericErrorCases();

	// Loop through all instructions in the function.
	// Output optimization annotations for those
	//  instructions that do not require full computation
	//  of their memory metadata by the Memory Monitor SDT.
	list<size_t> LoopList; // for current block
	int CurrBlockNum = SMP_BLOCKNUM_UNINIT;
	list<SMPInstr *>::iterator InstIter = Instrs.begin();
#if SMP_USE_SSA_FNOP_MARKER
	++InstIter;  // skip marker instruction
#endif
	bool AllocSeen = false; // Reached LocalVarsAllocInstr yet?
	bool DeallocTrigger = false;
	for ( ; InstIter != Instrs.end(); ++InstIter) {
		SMPInstr *CurrInst = (*InstIter);
		ea_t addr = CurrInst->GetAddr();
		CurrBlock = CurrInst->GetBlock();
		int BlockNum = CurrBlock->GetNumber();
		if (BlockNum != CurrBlockNum) {
			CurrBlockNum = BlockNum;
			if (0 < this->LoopCount) {
				LoopList.clear();
				this->BuildLoopList(BlockNum, LoopList);
			}
		}

		SMP_fprintf(AnnotFile, "%10lx %6zu INSTR BELONGTO %lx \n",
			(unsigned long) addr, CurrInst->GetSize(), (unsigned long) GetStartAddr());
		SMPitype CurrDataFlow = CurrInst->GetDataFlowType();
		if ((CurrDataFlow == INDIR_JUMP) || (CurrDataFlow == INDIR_CALL)) {
			SMP_xref_t xrefs;
			for (bool ok = xrefs.SMP_first_from(addr, XREF_ALL); ok; ok = xrefs.SMP_next_from()) {
				if (xrefs.GetTo() != 0) {
					if (xrefs.GetIscode() && (xrefs.GetType() != fl_F)) {
						// Found a code target, with its address in xrefs.to
						PrintCodeToCodeXref(addr, xrefs.GetTo(), CurrInst->GetSize());
					}
				}
			}
		}

		if (this->LocalVarsAllocInstr == addr) {
			AllocSeen = true;
			if (this->NeedsStackReferent)
				this->EmitStackFrameAnnotations(AnnotFile, CurrInst);
			else {
				int OptType = CurrInst->GetOptType(); 
				if (5 == OptType) { // ADD or SUB
					// Prevent mmStrata from extending the caller's stack frame
					//  to include the new allocation.
					SMP_fprintf(AnnotFile, "%10lx %6d INSTR LOCAL SafeFrameAlloc %s \n",
						(unsigned long) addr, -1, CurrInst->GetDisasm());
				}
				else if (CurrInst->MDIsPushInstr()) {
					SMP_fprintf(AnnotFile, "%10lx %6d INSTR LOCAL NoWarn %s \n",
						(unsigned long) addr, -3, CurrInst->GetDisasm());
				}
				// mmStrata ignores the DATAREF annotations anyway, so even though
				//  they are not needed, emit them for use by Strata and other tools
				//  in other projects besides MEDS.
				this->EmitStackFrameAnnotations(AnnotFile, CurrInst);
			}
		}
		// If this is the instruction which deallocated space
		//  for local variables, we set a flag to remind us to 
		//  emit an annotation on the next instruction.
		// mmStrata wants the instruction AFTER the
		//  deallocating instruction, so that it processes
		//  the deallocation after it happens. It inserts
		//  instrumentation before an instruction, not
		//  after, so it will insert the deallocating
		//  instrumentation before the first POP of callee-saved regs,
		//  if there are any, or before the return, otherwise.
		if (addr == this->LocalVarsDeallocInstr) {
			DeallocTrigger = true;
		}
		else if (DeallocTrigger) { // Time for annotation
			SMP_fprintf(AnnotFile,	"%10lx %6lu DEALLOC STACK esp - %lu %s\n", (unsigned long) addr,
				(unsigned long) this->LocalVarsSize, (unsigned long) this->LocalVarsSize, CurrInst->GetDisasm());
			DeallocTrigger = false;
		}

#ifndef SMP_REDUCED_ANALYSIS
		if (this->StackPtrAnalysisSucceeded() && this->HasGoodRTLs() && !this->HasUnresolvedIndirectJumps() && !this->HasSharedChunks()) {
			CurrInst->EmitTypeAnnotations(this->UseFP, AllocSeen, this->NeedsStackReferent, AnnotFile, InfoAnnotFile);
			CurrInst->EmitIntegerErrorAnnotations(InfoAnnotFile, LoopList);
		}
		else
#endif
			CurrInst->EmitAnnotations(this->UseFP, AllocSeen, this->NeedsStackReferent, AnnotFile, InfoAnnotFile);

		if (CurrInst->MDIsReturnInstr() && this->GetReturnAddressStatus() == FUNC_SAFE)
			CurrInst->EmitSafeReturn(AnnotFile);
	}  // end for all instructions

	// Loop through all basic blocks and emit profiling request annotations
	//  for those blocks that have unsafe memory writes in them.
	this->SafeBlocks = 0;
	this->UnsafeBlocks = 0;
	for (BlockIter = this->Blocks.begin(); BlockIter != this->Blocks.end(); ++BlockIter) {
		CurrBlock = (*BlockIter);
		if (CurrBlock->MaybeAliasedWrite()) {
			++(this->UnsafeBlocks);
#if SMP_OPTIMIZE_BLOCK_PROFILING
			vector<SMPInstr *>::iterator CurrInst;
			CurrInst = CurrBlock->GetFirstInst();
			ea_t addr = (*CurrInst)->GetAddr();
			SMP_fprintf(AnnotFile,	"%10x %6d BLOCK PROFILECOUNT %s\n", addr,
				(*CurrInst)->GetCmd().size, (*CurrInst)->GetDisasm());
#endif
		}
		else {
			++(this->SafeBlocks);
		}
	}
	// Free loop memory.
	LoopList.clear();
	this->FuncLoopsByBlock.clear();
#if SMP_SHRINK_TO_FIT
	vector<STARSBitSet>(this->FuncLoopsByBlock).swap(this->FuncLoopsByBlock);
#endif

	return;
} // end of SMPFunction::EmitAnnotations()

// Debug output dump.
void SMPFunction::Dump(void) {
	list<SMPBasicBlock *>::iterator CurrBlock;
	SMP_msg("Debug dump for function: %s\n", this->GetFuncName());
	SMP_msg("UseFP: %d  LocalVarsAllocInstr: %lx\n", this->UseFP,
		(unsigned long) this->LocalVarsAllocInstr);
	for (size_t index = 0; index < this->IDom.size(); ++index) {
		SMP_msg("IDOM for %zu: %d\n", index, this->IDom.at(index));
	}
	for (size_t index = 0; index < this->DomTree.size(); ++index) {
		SMP_msg("DomTree for %zu: ", index);
		list<int>::iterator DomIter;
		for (DomIter = this->DomTree.at(index).second.begin();
			DomIter != this->DomTree.at(index).second.end();
			++DomIter) {
				SMP_msg("%d ", *DomIter);
		}
		SMP_msg("\n");
	}
	SMP_msg("Global names: \n");
	set<op_t, LessOp>::iterator NameIter;
	for (NameIter = this->GlobalNames.begin(); NameIter != this->GlobalNames.end(); ++NameIter) {
		SMP_msg("index: %d ", ExtractGlobalIndex(*NameIter));
		PrintListOperand(*NameIter);
		SMP_msg("\n");
	}
	SMP_msg("Blocks each name is defined in: \n");
	for (size_t index = 0; index < this->BlocksDefinedIn.size(); ++index) {
		SMP_msg("Name index: %zu Blocks: ", index);
		list<int>::iterator BlockIter;
		for (BlockIter = this->BlocksDefinedIn.at(index).begin();
			BlockIter != this->BlocksDefinedIn.at(index).end();
			++BlockIter) {
			SMP_msg("%d ", *BlockIter);
		}
		SMP_msg("\n");
	}
	for (CurrBlock = this->Blocks.begin(); CurrBlock != this->Blocks.end(); ++CurrBlock) {
		// Dump out the function number and data flow sets before the instructions.
		(*CurrBlock)->Dump();
	}
	SMP_msg("End of debug dump for function: %s\n", this->GetFuncName());
	return;
} // end of SMPFunction::Dump()


// Analyzes the function to see if the return address can be marked as safe 
void SMPFunction::MarkFunctionSafe() {
#if SMP_DEBUG_FUNC
	SMP_msg(" Analyzing function %s and isLeaf = %d \n ", this->GetFuncName(), this->IsLeaf());
#endif
	bool HasCallTargets = false;
	bool HasStackPointerCopy = false;
	bool HasStackPointerPush = false;
	bool HasIndirectGlobalWrite = false;
	bool WritesAboveLocalFrame = false;		// Direct writes above local frame
	bool WritesAboveLocalFrameIndirect = false;	// Indirect writes above local frame
	bool HasIndexedStackWrite = false;
	bool HasIndirectWrite = false;
	bool IsIndirectCallTarget = false; // could be called indirectly
	bool IsTailCallTarget = false; // could be called by jump instruction used as tail call
	bool HasNoCallers = this->AllCallSources.empty();

	this->ReturnAddrStatus = FUNC_SAFE;
	this->SafeFunc = true;

	if (!this->AllCallTargets.empty()) {
		HasCallTargets = true;
	}

#if SMP_USE_SWITCH_TABLE_INFO
	if (this->UnresolvedIndirectJumps) {
#else
	if (this->IndirectJumps) {
#endif
#if SMP_DEBUG_FUNC
		SMP_msg("Function %s marked as unsafe due to indirect jumps\n", this->GetFuncName());
#endif
	}

#if SMP_DECLARE_INDIRECT_TARGETS_UNSAFE
	ea_t FirstAddr = this->FirstEA;
	SMP_xref_t xrefs;
	for (bool ok = xrefs.SMP_first_to(FirstAddr, XREF_ALL); ok; ok = xrefs.SMP_next_to()) {
		ea_t FromAddr = xrefs.GetFrom();
		if (FromAddr != 0) {
			if (!xrefs.GetIscode()) { // found data xref
				IsIndirectCallTarget = true; // addr of func appears in data; assume indirect calls to func
			}
			else { // found code xref; see if it is a jump used as a tail call
				// These tail calls could be a problem for fast returns if they go from unsafe to safe functions.
				insn_t TempCmd;
				ulong TempFeatures;
				bool CmdOK = SMPGetCmd(FromAddr, TempCmd, TempFeatures);
				if (!CmdOK) {
					// Better be conservative and assume it could be a tail call.
					IsTailCallTarget = true;
					SMP_msg("ERROR: Could not decode instruction at %lx from within MarkFunctionSafe(); assuming tail call\n", (unsigned long) FromAddr);
				}
				else if (TempCmd.itype != MD_CALL_INSTRUCTION) { // not a call instruction; must be jump of some sort
					IsTailCallTarget = true;
				}
			}
		}
	}
	this->PossibleIndirectCallTarget = IsIndirectCallTarget;
	this->PossibleTailCallTarget = IsTailCallTarget;
#endif

	list<SMPInstr *>::iterator Instructions = Instrs.begin();
	SMPInstr *CurrInst;
#if SMP_USE_SSA_FNOP_MARKER
	++Instructions;  // skip marker instruction
#endif

	// While processing the stack pointer writes, the prologue code for
	//  saving the frame register and allocating local variables needs to be
	//  handled.
	bool SaveEBP = false;
	bool XferESPtoEBP = false;
	for ( ; Instructions != Instrs.end(); ++Instructions) {
		CurrInst = (*Instructions);
#if SMP_VERBOSE_DEBUG_FUNC 
		SMP_msg(" Total number of defs for this instruction %d\n", CurrInst->NumDefs());
#endif
		if (!SaveEBP) { // still looking for "push ebp"
			if (CurrInst->MDIsPushInstr() && CurrInst->GetCmd().Operands[0].is_reg(MD_FRAME_POINTER_REG)) {
				SaveEBP = true;
				continue;
			}
		}
		else if (!XferESPtoEBP) { // found "push ebp", looking for "mov ebp,esp"
			insn_t CurrCmd = CurrInst->GetCmd();
			if ((CurrCmd.itype == NN_mov)
					&& (CurrInst->GetFirstDef()->GetOp().is_reg(MD_FRAME_POINTER_REG))
					&& (CurrInst->GetFirstUse()->GetOp().is_reg(MD_STACK_POINTER_REG))) {
				XferESPtoEBP = true;
				continue;
			}
		}
		ea_t address = CurrInst->GetAddr();
		if (address == this->LocalVarsAllocInstr ||
		    address == this->LocalVarsDeallocInstr)
			continue;

		if (CurrInst->MDIsStackPointerCopy(this->UseFP)) {
			HasStackPointerCopy = true;
			if (CurrInst->MDIsLoadEffectiveAddressInstr()) {
				// If an lea instruction loads an address above
				//  the stack frame, we must assume that writes
				//  above the stack frame could occur.
				op_t TempOp = CurrInst->GetLeaMemUseOp();
				if (this->WritesAboveLocalFrame(TempOp, CurrInst->AreDefsNormalized()))
					WritesAboveLocalFrameIndirect = true;
			}
#if SMP_DEBUG_FUNC 
			SMP_msg(" Function %s marked as unsafe due to stack pointer copy \n ", this->GetFuncName());
			SMP_msg("%s %x \n", CurrInst->GetDisasm(), CurrInst->GetAddr());
#endif
		}
		if (CurrInst->MDIsPushInstr()) {
			// not exactly sure how to handle this instruction
			// for the moment if its a push on a esp or usefp & ebp
			// mark as unsafe
			if (CurrInst->GetCmd().Operands[0].is_reg(MD_STACK_POINTER_REG) || 	 
					(this->UseFP && CurrInst->GetCmd().Operands[0].is_reg(MD_FRAME_POINTER_REG))) {
				HasStackPointerPush = true;
#if SMP_DEBUG_FUNC 
				SMP_msg(" Function %s marked as unsafe due to push on ebp or esp outside of function header \n", this->GetFuncName());	
				SMP_msg("%s %x\n", CurrInst->GetDisasm(), CurrInst->GetAddr());
#endif
			}
			continue;
		}
		if (CurrInst->MDIsPopInstr() || CurrInst->MDIsReturnInstr()) {
			// ignore pops and returns for the moment
			 continue;
		}
		set<DefOrUse, LessDefUse>::iterator setIterator;
		for (setIterator = CurrInst->GetFirstDef(); setIterator != CurrInst->GetLastDef(); ++setIterator) {
			op_t Operand = setIterator->GetOp();
			int BaseReg;
			int IndexReg;
			ushort ScaleFactor;
			ea_t offset;
			if (Operand.type == o_mem) {
				// now o_mem can have sib byte as well, as
				// reported by IDA. Check if the base reg is R_none
				// and index reg is R_none. If they are, then this is
				// a direct global write and can be marked safe.
				MDExtractAddressFields(Operand, BaseReg, IndexReg, ScaleFactor, offset);
				if ((BaseReg == R_none) && (IndexReg == R_none)) {
					// go onto next def
					continue;
				}
				else {
					HasIndirectGlobalWrite = true;
				}
			}
			else if (Operand.type == o_displ) {
				MDExtractAddressFields(Operand, BaseReg, IndexReg, ScaleFactor, offset);
				bool FramePointerRelative = (this->UseFP && (BaseReg == MD_FRAME_POINTER_REG));
				bool StackPointerRelative = (BaseReg == MD_STACK_POINTER_REG);
				if (StackPointerRelative || FramePointerRelative) {
					if (IndexReg == R_none) {
						bool tempWritesAboveLocalFrame = this->WritesAboveLocalFrame(Operand, CurrInst->AreDefsNormalized());
						WritesAboveLocalFrame |= tempWritesAboveLocalFrame;
#if SMP_DEBUG_FUNC 
						if (tempWritesAboveLocalFrame) {
							SMP_msg(" Function %s marked as unsafe due to direct write above loc "
								"variables offset=%x  loc=%x\n ", this->GetFuncName(), 
								offset, this->LocalVarsSize);	
							SMP_msg("Write above local frame in %s : offset: %d ",
								this->GetFuncName(), offset);
							SMP_msg("LocalVarsSize: %d OutgoingArgsSize: %d frsize: %d frregs: %d",
								this->LocalVarsSize, this->OutgoingArgsSize, 
								this->FuncInfo.frsize, this->FuncInfo.frregs);
							Instructions->Dump();
						}
#endif
					}
					else {
						bool tempWritesAboveLocalFrameIndirect = this->IndexedWritesAboveLocalFrame(Operand);

						/* separate indirect writes to this frame from indirect writes to another frame */
						if (tempWritesAboveLocalFrameIndirect) {
							WritesAboveLocalFrameIndirect = true;
#if SMP_DEBUG_FUNC 
							SMP_msg(" Function %s marked as unsafe due to indexed stack write above "
								"loc variable offset\n", this->GetFuncName());	
							SMP_msg("%s %x\n", CurrInst->GetDisasm(), CurrInst->GetAddr());
#endif
						}
						else {
							HasIndexedStackWrite = true;
#if SMP_DEBUG_FUNC 
							SMP_msg(" Function %s marked as unsafe due to indexed stack write\n", 
								this->GetFuncName());	
							SMP_msg("%s %x\n", CurrInst->GetDisasm(), CurrInst->GetAddr());
#endif
						}
					}
				}
				else {
					/* check whether there is profiler information for this indirect reference */
					HasIndirectWrite = true;
				}
			}
			else if (Operand.type == o_phrase) {
				// so phrase is of the form [BASE_REG + IND ]
				// if the index register is missing just make sure that
				// the displacement is below stack frame top
				MDExtractAddressFields(Operand, BaseReg, IndexReg, ScaleFactor, offset);
				// check the base reg
				// if index reg is used mark as unsafe 
				if (MDIsStackPtrReg(BaseReg, this->UseFP)) {
					if (IndexReg == R_none) {
						/* addressing mode is *esp or *ebp */
						continue;
					}
					else {
						HasIndexedStackWrite = true;
#if SMP_DEBUG_FUNC 
						SMP_msg(" Function %s marked as unsafe due to indexed stack write\n", this->GetFuncName());	
						SMP_msg("%s %x\n", CurrInst->GetDisasm(), CurrInst->GetAddr());
#endif
					}
				}
				else {
					/* check whether there is profiler information for this indirect reference */
					HasIndirectWrite = true;
				}
			}
			// else not memory, and we don't care.
		} // end for all DEFs in current instruction
	} // end for all instructions

	// For mmStrata bounds checking of the stack frame, we don't care
	//  about indirect writes unless they are to the stack.
	bool SpecUnsafe = (HasStackPointerCopy || HasStackPointerPush 
		|| HasIndexedStackWrite || this->SharedChunks
		|| this->UnresolvedIndirectJumps);
	bool Unsafe = SpecUnsafe || this->UnresolvedIndirectCalls;

	this->SafeFunc = (!Unsafe);
	this->SpecSafeFunc = (!SpecUnsafe);

	this->WritesAboveRA = WritesAboveLocalFrameIndirect;
	this->SafeCallee = (!Unsafe) && (!WritesAboveLocalFrameIndirect) && this->AnalyzedSP;
	this->SpecSafeCallee = (!SpecUnsafe) && (!WritesAboveLocalFrameIndirect) && this->AnalyzedSP;
	this->NeedsStackReferent = Unsafe;
	this->SpecNeedsStackReferent = SpecUnsafe;

	this->HasIndirectWrites = (HasIndexedStackWrite || HasIndirectWrite
		|| WritesAboveLocalFrameIndirect || HasIndirectGlobalWrite);

	bool UnsafeReturnAddr = (Unsafe || WritesAboveLocalFrame || WritesAboveLocalFrameIndirect || HasIndirectGlobalWrite 
		|| HasIndirectWrite || (!this->AnalyzedSP));
#if SMP_DECLARE_INDIRECT_TARGETS_UNSAFE
	if (!UnsafeReturnAddr && this->PossibleIndirectCallTarget) {
		SMP_msg("INFO: Function at %lx becoming UNSAFE because it is indirect call target.\n", (unsigned long) this->FirstEA);
		UnsafeReturnAddr =  true;
	}
	else if (!UnsafeReturnAddr && this->PossibleTailCallTarget) {
		SMP_msg("INFO: Function at %lx becoming UNSAFE because it is tail call target.\n", (unsigned long) this->FirstEA);
		UnsafeReturnAddr =  true;
	}
	else if (!UnsafeReturnAddr && HasNoCallers) {
		SMP_msg("INFO: Function at %lx becoming UNSAFE because it has no callers.\n", (unsigned long) this->FirstEA);
		UnsafeReturnAddr =  true;
	}

#endif

	if (UnsafeReturnAddr) {
		this->SetReturnAddressStatus(FUNC_UNSAFE);
#if SMP_DEBUG_FUNC_SAFETY
		SMP_msg("UNSAFE function %s ", this->GetFuncName());
		SMP_msg("StackPtrCopy: %d StackPtrPush: %d IndirectGlobal: %d ",
			HasStackPointerCopy, HasStackPointerPush, HasIndirectGlobalWrite);
		SMP_msg("WritesAboveFrame: %d IndirectStack: %d IndirectWrite: %d ",
			WritesAboveLocalFrame, HasIndexedStackWrite, HasIndirectWrite);
		SMP_msg("AnalyzedSP: %d UnresolvedCalls: %d UnresolvedJumps: %d SharedChunks: %d IsLeaf: %d ",
			this->AnalyzedSP, this->UnresolvedIndirectCalls, this->UnresolvedIndirectJumps,
			this->SharedChunks, this->IsLeaf());
		SMP_msg("IndirCallTarget: %d TailCallTarget: %d HasNoCallers: %d\n", this->PossibleIndirectCallTarget,
			this->PossibleTailCallTarget, HasNoCallers);
#endif
	}
	else if (HasCallTargets) {
		this->SetReturnAddressStatus(FUNC_SAFE_IF_CALLEES_ARE_SAFE);
	}

#if SMP_DEBUG_FUNC
	if (this->GetReturnAddressStatus() == FUNC_SAFE)
		SMP_msg("Function %s is SAFE\n", GetFuncName());
	else if (this->GetReturnAddressStatus() == FUNC_UNSAFE)
		SMP_msg("Function %s is UNSAFE\n", GetFuncName());
	else if (this->GetReturnAddressStatus() == FUNC_SAFE_IF_CALLEES_ARE_SAFE)
		SMP_msg("Function %s is SAFE_IF_CALLEES_ARE_SAFE\n", GetFuncName());

	if (!Unsafe) 
		SMP_msg("Function %s is mmSAFE\n", GetFuncName());
	else 
		SMP_msg("Function %s is mmUNSAFE\n", GetFuncName());

	if (!SpecUnsafe) 
		SMP_msg("Function %s is Speculatively mmSAFE\n", GetFuncName());
	else 
		SMP_msg("Function %s is Speculatively mmUNSAFE\n", GetFuncName());

#endif
	return;
} // end of SMPFunction::MarkFunctionSafe()