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

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

#include <cstring>
#include <cstdlib>

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

#include "SMPDataFlowAnalysis.h"
#include "SMPStaticAnalyzer.h"
#include "SMPFunction.h"
#include "SMPBasicBlock.h"
#include "SMPInstr.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 0
#define SMP_DEBUG_DATAFLOW 0
#define SMP_DEBUG_TYPE_INFERENCE 0
#define SMP_DEBUG_STACK_GRANULARITY 0
#define SMP_DEBUG_FUNC 0
#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

// 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

// Insert a floating no-op instruction at top of each function to hold SSA DEFs
//  of LiveIn names?
#define SMP_USE_SSA_FNOP_MARKER 1

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

// 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;


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

// Constructor
SMPFunction::SMPFunction(func_t *Info) {
	this->FuncInfo = *Info;
	this->IndirectCalls = false;
	this->IndirectJumps = false;
	this->UnresolvedIndirectJumps = false;
	this->SharedChunks = false;
	this->CallsAlloca = false;
	this->BuiltRTLs = false;
	this->UseFP = false;
	this->OutgoingArgsSize = 0;
	this->BlockCount = 0;
	this->ReturnAddrStatus = FUNC_UNKNOWN;
	this->SetIsSpeculative(false);

	this->Instrs.clear();
	this->Blocks.clear();
	this->DirectCallTargets.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->ReturnRegTypes.clear();
	this->SavedRegLoc.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);
	}

	return;
} // end of SMPFunction() constructor

// 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()

// 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) {
	bool FoundAllocInstr = false;
	bool FoundDeallocInstr = false;
	bool DebugFlag = false;
#if SMP_DEBUG_FRAMEFIXUP
	DebugFlag |= (0 == strcmp(".init_proc", this->GetFuncName()));
#endif

	// 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->FuncInfo));

	// 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.
	bool FrameInfoFixed = this->MDFixFrameInfo();
#if SMP_DEBUG_CONTROLFLOW
	msg("Returned from MDFixFrameInfo()\n");
#endif
#if SMP_DEBUG_FRAMEFIXUP
	if (FrameInfoFixed) {
		msg("Fixed stack frame size info: %s\n", this->FuncName);
		SMPBasicBlock CurrBlock = this->Blocks.front();
		msg("First basic block:\n");
		for (list<list<SMPInstr>::iterator>::iterator CurrInstr = CurrBlock.GetFirstInstr();
			CurrInstr != CurrBlock.GetLastInstr();
			++CurrInstr) {
			msg("%s\n", (*CurrInstr)->GetDisasm());
		}
	}
#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) msg("Searching for alloc and dealloc\n");
		for (list<SMPInstr>::iterator CurrInstr = this->Instrs.begin();
			CurrInstr != this->Instrs.end();
			++CurrInstr) {

#if SMP_USE_SSA_FNOP_MARKER
			if (this->Instrs.begin() == CurrInstr)
				continue;  // skip marker instruction
#endif

			ea_t addr = CurrInstr->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
				&& CurrInstr->MDIsFrameAllocInstr()) {
#if SMP_DEBUG_CONTROLFLOW
				msg("Returned from MDIsFrameAllocInstr()\n");
#endif
				this->LocalVarsAllocInstr = addr;
				FoundAllocInstr = true;
				if (DebugFlag) msg("Found alloc: %s\n", CurrInstr->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_CONTROLFLOW
				msg("Returned from MDFixUseFP()\n");
#endif
#if SMP_DEBUG_FRAMEFIXUP
				if (FixedUseFP) {
					msg("Fixed UseFP in %s\n", this->FuncName);
				}
#endif
			}
			else if (FoundAllocInstr) {
				// We can now start searching for the DeallocInstr.
				if (CurrInstr->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
					msg("Returned from MDIsFrameDeallocInstr()\n");
#endif
					this->LocalVarsDeallocInstr = addr;
					FoundDeallocInstr = true;
				}
				else {
					if (DebugFlag) msg("Not dealloc: %s\n", CurrInstr->GetDisasm());
				}
			}
		} // end for (list<SMPInstr>::iterator CurrInstr ... )
		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
			msg("Returned from FindAllocPoint()\n");
#endif
#if SMP_DEBUG_FRAMEFIXUP
			if (BADADDR == this->LocalVarsAllocInstr) {
				msg("ERROR: Could not find stack frame allocation in %s\n",
					FuncName);
				msg("LocalVarsSize: %d  SavedRegsSize: %d ArgsSize: %d\n",
					LocalVarsSize, CalleeSavedRegsSize, IncomingArgsSize);
			}
			else {
				msg("FindAllocPoint found %x for function %s\n",
					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.
			msg("ERROR: Could not find stack frame deallocation in %s\n",
				FuncName);
		}
#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;
		for (list<SMPInstr>::iterator CurrInstr = this->Instrs.begin();
			CurrInstr != this->Instrs.end();
			++CurrInstr) {
#if SMP_USE_SSA_FNOP_MARKER
			if (this->Instrs.begin() == CurrInstr)
				continue;  // skip marker instruction
#endif

			insn_t CurrCmd = CurrInstr->GetCmd();
			ea_t addr = CurrInstr->GetAddr();
			if (CurrCmd.itype == NN_push)
				SaveAddr = addr;
			else
				break;
		}
		this->LocalVarsAllocInstr = SaveAddr;
		this->LocalVarsDeallocInstr = 0;
	} // end if (LocalVarsSize > 0) ... else ...

#if 0
	// Now we need to do the corresponding operations from the
	//  end of the function to find the DeallocInstr in the
	//  function epilogue. Because there is no addition to the
	//  stack pointer to deallocate the local vars region, the
	//  function epilogue will consist of (optional) pops of
	//  callee-saved regs, followed by the return instruction.
	//  Working backwards, we should find a return and then 
	//  stop when we do not find any more pops.
	if (0 >= LocalVarsSize) {
		this->LocalVarsDeallocInstr = NULL;
	}
	else {
		SaveAddr = this->FuncInfo.endEA - 1;
		bool FoundRet = false;
		do {
			ea_t addr = get_item_head(SaveAddr);
			flags_t InstrFlags = getFlags(addr);
			if (isCode(addr) && isHead(addr)) {
				ua_ana0(addr);
				if (!FoundRet) { // Just starting out.
					if (MDIsReturnInstr(cmd)) {
						FoundRet = true;
						SaveAddr = addr - 1;
					}
					else {
						msg("ERROR: Last instruction not a return.\n");
					}
				}
				else { // Should be 0 or more POPs before the return.
					if (MDIsPopInstr(cmd)) {
						SaveAddr = addr - 1;
					}
					else if (FrameAllocInstr(cmd, this->LocalVarsSize)) {
						this->LocalVarsDeallocInstr = addr;
					}
					else {
						msg("ERROR: Frame deallocation not prior to POPs.\n");
						this->LocalVarsDeallocInstr = SaveAddr + 1;
					}
				} // end if (!FoundRet) ... else ...
			}
			else {
				--SaveAddr;
			} // end if (isCode(addr) && isHead(addr))
		} while (NULL == this->LocalVarsDeallocInstr);
	} // end if (0 >= this->LocalVarsSize)
#endif // 0

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

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

	// Get callee-saved regs info for remediation use.
	if (FoundAllocInstr) {
		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 ahve 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();
	for (list<list<SMPInstr>::iterator>::iterator CurrIter = CurrBlock.GetFirstInstr();
		CurrIter != CurrBlock.GetLastInstr();
		++CurrIter) {
#if SMP_USE_SSA_FNOP_MARKER
		if (CurrBlock.GetFirstInstr() == CurrIter)
			continue;  // skip marker instruction
#endif

		list<SMPInstr>::iterator 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) 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) msg("libc_csu_init OtherPushesSize: %d  %s\n", OtherPushesSize,
					CurrInstr->GetDisasm());
			}
		}
		else if (CurrInstr->MDIsFrameAllocInstr()) {
			if (DebugFlag) 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)
							msg("Total frame size changed: %s\n", this->FuncName);
#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
							msg("Only callee regs size changed: %s\n", this->FuncName);
#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) msg("libc_csu_init OldFrameTotal: %d  %s\n", OldFrameTotal);
		if (OldFrameTotal == SavedRegsSize) {
			this->CalleeSavedRegsSize = (ushort) SavedRegsSize;
			this->LocalVarsSize = 0;
			Changed = true;
		}
#if SMP_DEBUG_FRAMEFIXUP
		else {
			msg("Could not update frame sizes: %s\n", this->FuncName);
		}
#endif
	}

#if SMP_DEBUG_FRAMEFIXUP
	if ((0 < OtherPushesSize) && (0 < NewLocalsSize))
		msg("Extra pushes found of size %d in %s\n", OtherPushesSize,
			this->FuncName);
#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) {
	bool DebugFlag = (0 == strcmp("_dl_runtime_resolve", this->GetFuncName()));
	sval_t TargetSize = - ((sval_t) OriginalLocSize);  // negate; stack grows down 

#if SMP_DEBUG_FRAMEFIXUP
	if (DebugFlag)
		msg("%s OriginalLocSize: %d\n", this->GetFuncName(), OriginalLocSize);
#endif

	if (this->AnalyzedSP) {
		// Limit our analysis to the first basic block in the function.
		list<SMPInstr>::iterator CurrInstr;
		for (CurrInstr = this->Instrs.begin(); CurrInstr != this->Instrs.end();	++CurrInstr) {
#if SMP_USE_SSA_FNOP_MARKER
			if (this->Instrs.begin() == CurrInstr)
				continue;  // skip marker instruction
#endif

			ea_t addr = CurrInstr->GetAddr();
			// get_spd() returns a cumulative delta of ESP
			sval_t sp_delta = get_spd(&(this->FuncInfo), addr);
#if SMP_DEBUG_FRAMEFIXUP
			if (DebugFlag)
				msg("%s delta: %d at %x\n", this->GetFuncName(), sp_delta, addr);
#endif
			if (sp_delta == TargetSize) { // <= instead of == here?  **!!**
				// Previous instruction hit the frame size.
				if (CurrInstr == this->Instrs.begin()) {
					return BADADDR;  // cannot back up from first instruction
				}
				else {
					ea_t PrevAddr = (--CurrInstr)->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 (CurrInstr->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 (CurrInstr->IsBasicBlockTerminator())
					return BADADDR;
				list<SMPInstr>::iterator NextInstr = CurrInstr;
				++NextInstr;
				if (NextInstr == this->Instrs.end())
					return BADADDR;
				sp_delta = get_spd(&(this->FuncInfo), NextInstr->GetAddr());
				if (sp_delta == TargetSize) {
					// CurrInstr 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 {
		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) {
	list<SMPInstr>::iterator CurrInstr = this->Instrs.begin();
	ea_t addr = CurrInstr->GetAddr();

#if SMP_USE_SSA_FNOP_MARKER
	if (this->Instrs.begin() == CurrInstr)
		++CurrInstr;  // skip marker instruction
#endif

	if (!(this->UseFP)) {
		// 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 {
			FirstBlockProcessed = CurrInstr->IsLastInBlock();
			if (!EBPSaved) { // still looking for "push ebp"
				if (CurrInstr->MDIsPushInstr() && CurrInstr->GetCmd().Operands[0].is_reg(R_bp)) {
					EBPSaved = true;
				}
			}
			else if (!ESPintoEBP) { // found "push ebp", looking for "mov ebp,esp"
				insn_t CurrCmd = CurrInstr->GetCmd();
				if ((CurrCmd.itype == NN_mov) 
					&& (CurrInstr->GetFirstDef()->GetOp().is_reg(R_bp))
					&& (CurrInstr->GetFirstUse()->GetOp().is_reg(R_sp))) {
					ESPintoEBP = true;
					FirstBlockProcessed = true; // exit loop
				}
			}
			++CurrInstr;
			addr = CurrInstr->GetAddr();
			// 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).
			FirstBlockProcessed |= (addr >= this->LocalVarsAllocInstr);
		} 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;
		return ESPintoEBP;
	} // 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 = CurrInstr->GetFirstDef();
		while (CurrDef != CurrInstr->GetLastDef()) {
			if (CurrDef->GetOp().is_reg(R_bp))
				return false; // EBP got set before locals were allocated
			++CurrDef;
		}
		++CurrInstr;
		addr = CurrInstr->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;
	msg("MDFixUseFP reset UseFP to false for %s\n", this->GetFuncName());
	return true;
} // 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 CurrInst;
	int RegIndex;
	func_t *CurrFunc = get_func(this->GetStartAddr());
	assert(NULL != CurrFunc);

	for (CurrInst = this->Instrs.begin(); CurrInst != this->Instrs.end(); ++CurrInst) {
		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) {
					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 {
					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 CurrBlock;
	list<list<SMPInstr>::iterator>::iterator InstIter;
	vector<SMPOperandType> RegTypes;

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

// 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.
	bool DebugFlag = false;
#if SMP_DEBUG_STACK_GRANULARITY
	DebugFlag |= (0 == strcmp("qSort3", this->GetFuncName()));
#endif
	func_t *FuncPtr = get_func(this->FuncInfo.startEA);
	if (NULL == FuncPtr) {
		msg("ERROR in SMPFunction::SemiNaiveLocalVarID; no func ptr\n");
	}
	assert(NULL != FuncPtr);
	struc_t *StackFrame = get_frame(FuncPtr);

	if (NULL == StackFrame) {
		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[MAXSTR] = {'\0'};
		if (NULL == Member) {
			msg("NULL stack frame member pointer in %s\n", this->GetFuncName());
			break;
		}
		get_member_name(Member->id, MemberName, MAXSTR - 1);
		if (MemberName == NULL) {
#if SMP_DEBUG_STACK_GRANULARITY
			msg("NULL stack frame member in %s\n", this->GetFuncName());
#endif
			continue;
		}
		offset = Member->soff;
		if (MemberName[0] == ' ') {
#if SMP_DEBUG_STACK_GRANULARITY
			msg("NULL stack frame name at offset %d in %s\n", offset, this->GetFuncName());
#endif
			MemberName[1] = '\0';
		}
		if (DebugFlag) {
			msg("%s local var %s at offset %d\n", this->GetFuncName(), MemberName, offset);
		}
		if (offset >= (long) this->LocalVarsSize)
			break;  // Stop after processing locals and outgoing args
#if 0
		// We want the offset from the stack pointer after local frame allocation.
		//  This subtraction would make it relative to the original stack pointer.
		offset -= this->FuncInfo.frsize;
#endif
		struct LocalVar TempLocal;
		TempLocal.offset = offset;
		TempLocal.size = (size_t) -1; // compute later
		qstrncpy(TempLocal.VarName, MemberName, MAXSTR - 1);
		this->LocalVarTable.push_back(TempLocal);
	} // end for all stack frame members

	if (this->LocalVarTable.empty())
		return;

#if SMP_DEBUG_STACK_GRANULARITY
	msg("Computing %d local var sizes\n", this->LocalVarTable.size());
#endif
	// Now we want to fill in the size field for each local
	for (size_t VarIndex = 0; VarIndex < (this->LocalVarTable.size() - 1); ++VarIndex) {
		this->LocalVarTable[VarIndex].size = this->LocalVarTable[VarIndex + 1].offset
			- this->LocalVarTable[VarIndex].offset;
	}
#if SMP_DEBUG_STACK_GRANULARITY
	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
	if (this->LocalVarTable.size() > 0) {
		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[this->LocalVarTable.size() - 1].size = this->FuncInfo.frsize
			- SavedRegsSpace - this->LocalVarTable[this->LocalVarTable.size() - 1].offset;
	}
	this->LocalVarOffsetLimit = this->LocalVarTable.back().offset 
		+ (adiff_t) this->LocalVarTable.back().size;
	assert(this->LocalVarOffsetLimit <= (adiff_t) this->FuncInfo.frsize);
	// Find out how many of the locals are really outgoing args.
	if (this->AnalyzedSP && !this->CallsAlloca && (BADADDR != this->LocalVarsAllocInstr)) {
		this->FindOutgoingArgsSize();
	}
	else {
		msg("FindOutgoingArgsSize not called for %s ", this->GetFuncName());
		msg("AnalyzedSP: %d CallsAlloca: %d LocalVarsAllocInstr: %x \n",
			this->AnalyzedSP, this->CallsAlloca, this->LocalVarsAllocInstr);
	}
	return;
} // end of SMPFunction::SemiNaiveLocalVarID()

// 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 CurrInst;
	this->MinStackDelta = 20000; // Final value should be negative
	bool DebugFlag = false;
#if SMP_DEBUG_STACK_GRANULARITY
	DebugFlag = (0 == strcmp("error_for_asm", this->GetFuncName()));
#endif
	if (DebugFlag) {
		msg("DEBUG: Entered FindOutgoingArgsSize for %s\n", this->GetFuncName());
#if SMP_IDAPRO52_WORKAROUND
		this->OutgoingArgsSize = 16;
		return;
#endif
	}

	for (CurrInst = this->Instrs.begin(); CurrInst != this->Instrs.end(); ++CurrInst) {
#if SMP_USE_SSA_FNOP_MARKER
		if (this->Instrs.begin() == CurrInst)
			continue;  // skip marker instruction
#endif

		ea_t addr = CurrInst->GetAddr();
		sval_t sp_delta = get_spd(&(this->FuncInfo), addr);
		if (sp_delta < this->MinStackDelta)
			this->MinStackDelta = 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 NextInst = CurrInst;
			++NextInst;
			sp_delta = get_spd(&(this->FuncInfo), NextInst->GetAddr());
			this->AllocPointDelta = sp_delta;
		}
	}
#if SMP_DEBUG_STACK_GRANULARITY
	msg("AllocPointDelta: %d MinStackDelta: %d\n", this->AllocPointDelta, this->MinStackDelta);
#endif
	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.
	int limit = 0;
#if 1
	if (this->LocalVarOffsetLimit > 0)
		limit = this->LocalVarOffsetLimit;
#endif
	for (int i = this->MinStackDelta; i < limit; ++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;
		this->StackFrameMap.push_back(TempEntry);
	}

	// Fill in the VarPtr fields for each StackFrameMap entry.
	if (0 <= this->AllocPointDelta) {
		msg("FATAL ERROR: AllocPointDelta = %d in %s\n", this->AllocPointDelta, this->GetFuncName());
	}
	assert(0 > this->AllocPointDelta);
	for (size_t i = 0; i < this->LocalVarTable.size(); ++i) {
		assert(this->LocalVarTable.at(i).offset >= 0);
		// Picture that AllocPointDelta is -200, MinStackDelta 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->MinStackDelta));
		size_t limit = base + this->LocalVarTable.at(i).size;
		if (limit > this->StackFrameMap.size()) {
			msg("ERROR: base = %d limit = %d StackFrameMap size = %d\n", base, limit,
				this->StackFrameMap.size());
		}
		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.
	for (CurrInst = this->Instrs.begin(); CurrInst != this->Instrs.end(); ++CurrInst) {
#if SMP_USE_SSA_FNOP_MARKER
		if (this->Instrs.begin() == CurrInst)
			continue;  // skip marker instruction
#endif

		sval_t sp_delta = get_spd(&(this->FuncInfo), CurrInst->GetAddr());
		if (0 < sp_delta) {
			// Stack underflow; about to assert
			msg("Stack underflow at %x %s sp_delta: %d\n", CurrInst->GetAddr(),
				CurrInst->GetDisasm(), sp_delta);
		}
		assert(0 >= sp_delta);
		ea_t offset;
		size_t DataSize;
		bool UsedFramePointer;
		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(TempOp, sp_delta, offset, DataSize, UsedFramePointer)) {
					assert(0 <= offset);
					if (offset >= this->FuncInfo.frsize)
						continue;  // limit processing to outgoing args and locals
					if ((offset + DataSize) > this->StackFrameMap.size()) {
						msg("ERROR: offset = %d DataSize = %d FrameMapSize = %d\n",
							offset, DataSize, this->StackFrameMap.size());
					}
					assert((offset + DataSize) <= this->StackFrameMap.size());
					for (int j = 0; j < (int) DataSize; ++j) {
						this->StackFrameMap[offset + j].Written = true;
						if (!UsedFramePointer)
							this->StackFrameMap[offset + j].ESPRelativeAccess = true;
						else
							this->StackFrameMap[offset + j].EBPRelativeAccess = true;
					}
				}
			} // 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(TempOp, sp_delta, offset, DataSize, UsedFramePointer)) {
					assert(0 <= offset);
					if (offset >= this->FuncInfo.frsize)
						continue;  // limit processing to outgoing args and locals
					if ((offset + DataSize) > this->StackFrameMap.size()) {
						msg("ERROR: offset = %d DataSize = %d FrameMapSize = %d\n",
							offset, DataSize, this->StackFrameMap.size());
					}
					assert((offset + DataSize) <= this->StackFrameMap.size());
					for (int j = 0; j < (int) DataSize; ++j) {
						this->StackFrameMap[offset + j].Read = true;
						if (!UsedFramePointer)
							this->StackFrameMap[offset + j].ESPRelativeAccess = true;
						else
							this->StackFrameMap[offset + j].EBPRelativeAccess = true;
					}
				}
			} // 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 (this->IsLeaf()) {
		this->OutgoingArgsSize = 0;
		return;
	}

	// For non-leaf functions, set the OutgoingArgsSize to the write-only, ESP-relative
	//  region of the bottom of the StackFrameMap.
	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) {
			msg("StackFrameMap entry %d: offset: %d 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 (TempEntry.Read || TempEntry.EBPRelativeAccess || !TempEntry.Written
			|| !TempEntry.ESPRelativeAccess)
			break;
		this->OutgoingArgsSize++;
	}
	// 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.
	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 (this->OutgoingArgsSize < (TempEntry.VarPtr->offset + TempEntry.VarPtr->size)) {
#if SMP_DEBUG_FRAMEFIXUP
			msg("OutGoingArgsSize = %d", this->OutgoingArgsSize);
#endif
			this->OutgoingArgsSize = TempEntry.VarPtr->offset + TempEntry.VarPtr->size;
#if SMP_DEBUG_FRAMEFIXUP
			msg(" adjusted to %d\n", this->OutgoingArgsSize);
#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.
// NOTE: TempOp must be of type o_displ or o_phrase, as no other operand type could be a
//  stack memory access.
// sp_delta is the stack pointer delta of the current instruction, relative to the initial
//  stack pointer value for the function.
// Return true if a stack memory access was found in TempOp, false otherwise.
bool SMPFunction::MDGetStackOffsetAndSize(op_t TempOp, sval_t sp_delta, ea_t &offset, size_t &DataSize, bool &FP) {
	int BaseReg;
	int IndexReg;
	ushort ScaleFactor;

	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]
	}
	if ((BaseReg == R_sp) || (IndexReg == R_sp)) {
		// ESP-relative constant offset
		offset += sp_delta; // base offsets from entry ESP value
		offset -= this->MinStackDelta; // convert to StackFrameMap index
		// Get size of data written
		DataSize = GetOpDataSize(TempOp);
		FP = false;
		return true;
	}
	else if (this->UseFP && ((BaseReg == R_bp) || (IndexReg == R_bp))) {
		offset -= this->FuncInfo.frregs; // base offsets from entry ESP value
		offset -= this->MinStackDelta; // convert to StackFrameMap index
		DataSize = GetOpDataSize(TempOp);
		FP = true;
		return true;
	}
	else {
		return false;
	}
} // end of SMPFunction::MDGetStackOffsetAndSize()

// Find evidence of calls to alloca(), which appear as stack space allocations (i.e.
//  subtractions 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) {
	list<SMPInstr>::iterator CurrInst;
	for (CurrInst = this->Instrs.begin(); CurrInst != this->Instrs.end(); ++CurrInst) {
#if SMP_USE_SSA_FNOP_MARKER
		if (this->Instrs.begin() == CurrInst)
			continue;  // skip marker instruction
#endif

		if ((CurrInst->GetAddr() > this->LocalVarsAllocInstr) && CurrInst->MDIsFrameAllocInstr()) {
			return true;
		}
	}
	return false;
} // end of SMPFunction::FindAlloca()

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

#if 0
	if (0 < IncomingArgsSize) {
		qfprintf(AnnotFile, "%10x %6d INARGS STACK esp + %d %s \n",
				addr, IncomingArgsSize,
				(LocalVarsSize + CalleeSavedRegsSize + RetAddrSize),
				Instr->GetDisasm());
	}
#endif
	if (0 < RetAddrSize) {
		qfprintf(AnnotFile, "%10x %6d MEMORYHOLE STACK esp + %d ReturnAddress \n",
				addr, RetAddrSize, (LocalVarsSize + CalleeSavedRegsSize));
	}
	if (0 < CalleeSavedRegsSize) {
		qfprintf(AnnotFile, "%10x %6d MEMORYHOLE STACK esp + %d CalleeSavedRegs \n",
				addr, CalleeSavedRegsSize, LocalVarsSize);
	}
	if (0 < LocalVarsSize) {
		unsigned long ParentReferentID = DataReferentID++;
		qfprintf(AnnotFile, "%10x %6d DATAREF STACK %d esp + %d PARENT LocalFrame LOCALFRAME\n",
				addr, 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) {
				qfprintf(AnnotFile, "%10x %6d DATAREF STACK %d esp + %d CHILDOF %d OFFSET %d OutArgsRegion OUTARGS\n",
					addr, this->OutgoingArgsSize, DataReferentID, 0, ParentReferentID, 0);
				++DataReferentID;
			}
#if SMP_DEBUG_STACK_GRANULARITY
			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
				msg("Entry %d offset %d 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;
				qfprintf(AnnotFile, "%10x %6d DATAREF STACK %d esp + %d CHILDOF %d OFFSET %d LOCALVAR %s \n",
					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() 

// 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) {
	list<SMPInstr>::iterator FirstInBlock = this->Instrs.end();
	   // For starting a basic block
	list<SMPInstr>::iterator LastInBlock = this->Instrs.end();
	   // Terminating a basic block

#if SMP_DEBUG_CONTROLFLOW
	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));
	get_func_name(this->FuncInfo.startEA, this->FuncName,
		sizeof(this->FuncName) - 1);
	this->BlockCount = 0;
	this->AnalyzedSP = this->FuncInfo.analyzed_sp();

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

	// Cycle through all chunks that belong to the function.
	func_tail_iterator_t FuncTail(&(this->FuncInfo));
	size_t ChunkCounter = 0;
	for (bool ChunkOK = FuncTail.main(); ChunkOK; ChunkOK = FuncTail.next()) {
		const area_t &CurrChunk = FuncTail.chunk();
		++ChunkCounter;
		if (1 < ChunkCounter) {
			this->SharedChunks = true;
#if SMP_DEBUG_CHUNKS
			msg("Found tail chunk for %s at %x\n", this->FuncName, CurrChunk.startEA);
#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) && isCode(InstrFlags)) {
				SMPInstr CurrInst = SMPInstr(addr);
				// Fill in the instruction data members.
#if SMP_DEBUG_CONTROLFLOW
				msg("SMPFunction::Analyze: calling CurrInst::Analyze.\n");
#endif
				CurrInst.Analyze();
				if (SMPBinaryDebug) {
					msg("Disasm:  %s \n", CurrInst.GetDisasm());
				}
#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 = SMPInstr(addr - 1);
					MarkerInst.AnalyzeMarker();
					assert(FirstInBlock == this->Instrs.end());
					this->Instrs.push_back(MarkerInst);
				}
#endif
				if (this->AnalyzedSP) {
					// Audit the IDA SP analysis.
					sval_t sp_delta = get_spd(&(this->FuncInfo), addr);
					// 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;
						msg("Resetting AnalyzedSP to false for %s\n", this->GetFuncName());
						msg("Underflowing instruction: %s sp_delta: %d\n", CurrInst.GetDisasm(),
							sp_delta);
					}
					else if (sp_delta == 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();
							msg("Found tail call at %x from %s: %s\n", addr, this->GetFuncName(),
								CurrInst.GetDisasm());
							// Just like a return instruction, we must make
							//  DEF-USE chains reach the tail call.
							CurrInst.MDAddRegUse(R_ax, false);
							CurrInst.MDAddRegUse(R_bx, false);
							CurrInst.MDAddRegUse(R_cx, false);
							CurrInst.MDAddRegUse(R_dx, false);
							CurrInst.MDAddRegUse(R_bp, false);
							CurrInst.MDAddRegUse(R_si, false);
							CurrInst.MDAddRegUse(R_di, false);
						}
					}
				}

				if (CurrInst.GetDataFlowType() == INDIR_CALL)
					this->IndirectCalls = true;
				else if (CurrInst.GetDataFlowType() == INDIR_JUMP)
					this->IndirectJumps = true;
				else if (CurrInst.GetDataFlowType() == CALL) {
					set<DefOrUse, LessDefUse>::iterator CurrUse;
					for (CurrUse = CurrInst.GetFirstUse(); CurrUse != CurrInst.GetLastUse(); ++CurrUse) {
						optype_t OpType = CurrUse->GetOp().type;
						if ((OpType == o_near) || (OpType == o_far)) {
							ea_t CallTarget = CurrUse->GetOp().addr;
							this->DirectCallTargets.push_back(CallTarget);
						}
					}
				}

				// 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
					msg("SMPFunction::Analyze: hit special jump target case.\n");
#endif
					LastInBlock = --(this->Instrs.end());
					SMPBasicBlock CurrBlock = SMPBasicBlock(this, FirstInBlock,
						LastInBlock);
					CurrBlock.Analyze();
					// If not the first chunk in the function, it is a shared
					//  tail chunk.
					if (ChunkCounter > 1) {
						CurrBlock.SetShared();
					}
					FirstInBlock = this->Instrs.end();
					LastInBlock = this->Instrs.end();
					this->Blocks.push_back(CurrBlock);
					this->BlockCount += 1;
				}

#if SMP_DEBUG_CONTROLFLOW
		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
					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
		msg("SMPFunction::Analyze: found block terminator.\n");
#endif
					LastInBlock = --(this->Instrs.end());
					SMPBasicBlock CurrBlock = SMPBasicBlock(this, FirstInBlock, LastInBlock);
					CurrBlock.Analyze();
					// If not the first chunk in the function, it is a shared
					//  tail chunk.
					if (ChunkCounter > 1) {
						CurrBlock.SetShared();
					}
					FirstInBlock = this->Instrs.end();
					LastInBlock = this->Instrs.end();
					this->Blocks.push_back(CurrBlock);
					this->BlockCount += 1;

					// 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;
					}
				}
			} // end if (isHead(InstrFlags) && 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 CurrBlock = SMPBasicBlock(this, FirstInBlock, LastInBlock);
			CurrBlock.Analyze();
			// If not the first chunk in the function, it is a shared
			//  tail chunk.
			if (ChunkCounter > 1) {
				CurrBlock.SetShared();
			}
			FirstInBlock = this->Instrs.end();
			LastInBlock = this->Instrs.end();
			this->Blocks.push_back(CurrBlock);
			this->BlockCount += 1;
		}
	} // end for (bool ChunkOK = ...)

	// Now that we have all instructions and basic blocks, link each instruction
	//  to its basic block. Note that the instruction has to be linked to the copy
	//  of the basic block in this->Blocks(), not to the original SMPBasicBlock
	//  object that was constructed and destructed on the stack above. (Ouch!
	//  Very painful memory corruption debugging lesson.)
	list<SMPBasicBlock>::iterator CurrBlock;
	list<list<SMPInstr>::iterator>::iterator InstIter;
	for (CurrBlock = this->Blocks.begin(); CurrBlock != this->Blocks.end(); ++CurrBlock) {
		for (InstIter = CurrBlock->GetFirstInstr(); InstIter != CurrBlock->GetLastInstr(); ++InstIter) {
			(*InstIter)->SetBlock(CurrBlock->GetThisBlock());
		}
	}

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

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

	// Set up basic block links and map of instructions to blocks.
	if (!(this->HasSharedChunks())) {
		bool DumpFlag = false;
#if SMP_DEBUG_DATAFLOW
		DumpFlag |= (0 == strcmp("__do_global_dtors_aux", this->GetFuncName()));
		DumpFlag |= (0 == strcmp("dohanoi", this->GetFuncName()));
		DumpFlag |= (0 == strcmp("weightadj", this->GetFuncName()));
#endif
		this->SetLinks();
		this->RPONumberBlocks();

#if SMP_DEBUG_CONTROLFLOW
		msg("SMPFunction::Analyze: set stack frame info.\n");
#endif
		// Figure out the stack frame and related info.
		this->SetStackFrameInfo();

#if SMP_COMPUTE_LVA_SSA
#if SMP_USE_SWITCH_TABLE_INFO
		if (!(this->HasUnresolvedIndirectJumps())) {
#else
		if (!(this->HasIndirectJumps())) {
#endif
			list<SMPInstr>::iterator CurrInst;
			bool GoodRTL;
			this->BuiltRTLs = true;
			for (CurrInst = this->Instrs.begin(); CurrInst != this->Instrs.end(); ++CurrInst) {
				// Build tree RTLs for the instruction.
				GoodRTL = CurrInst->BuildRTL();
				this->BuiltRTLs = (this->BuiltRTLs && GoodRTL);
#if SMP_DEBUG_BUILD_RTL
				if (!GoodRTL) {
					msg("ERROR: Cannot build RTL at %x for %s\n", CurrInst->GetAddr(), 
						CurrInst->GetDisasm());
				}
#endif
				if (GoodRTL)
					CurrInst->SyncAllRTs();
			} // end for all instructions
			this->LiveVariableAnalysis();
			this->ComputeSSA();
			if (DumpFlag) 
				this->Dump();
		} // end if not indirect jumps
#endif // SMP_COMPUTE_LVA_SSA
	} // end if not shared chunks
	else { // has shared chunks; still want to compute stack frame info
#if SMP_DEBUG_CONTROLFLOW
		msg("SMPFunction::Analyze: set stack frame info.\n");
#endif
#ifdef SMP_DEBUG_FUNC
		msg(" %s has shared chunks \n", this->GetFuncName());
#endif
		// Figure out the stack frame and related info.
		this->SetStackFrameInfo();
	}
	this->MarkFunctionSafe();
} // end of SMPFunction::Analyze()

// 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, IndexOp, ReturnOp, DefOp, UseOp;
	BaseOp.type = o_reg;
	IndexOp.type = o_reg;
	ReturnOp.type = o_reg;
	list<SMPInstr>::iterator CurrInst;
	set<DefOrUse, LessDefUse>::iterator CurrDef;
	set<DefOrUse, LessDefUse>::iterator CurrUse;
	set<DefOrUse, LessDefUse>::iterator NextUse;
	bool DebugFlag = false;
	if (0 == strcmp("gl_transform_vb_part1", this->GetFuncName())) {
		DebugFlag = true;
	}

	do {
		changed = false;
		for (CurrInst = this->Instrs.begin(); CurrInst != this->Instrs.end(); ++CurrInst) {
			// Skip the SSA marker instruction.
			if (NN_fnop == CurrInst->GetCmd().itype)
				continue;

			CurrDef = CurrInst->GetFirstDef();
			while (CurrDef != CurrInst->GetLastDef()) {
				if (DEF_METADATA_UNANALYZED == CurrDef->GetMetadataStatus()) {
					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 (DefOp.is_reg(R_sp) 
						|| (this->UseFP && DefOp.is_reg(R_bp))) {
						// 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.
						CurrDef = CurrInst->SetDefMetadata(DefOp, DEF_METADATA_USED);
						changed = true;
						MDExtractAddressFields(DefOp, BaseReg, IndexReg,
							ScaleFactor, offset);
						if (R_none != BaseReg) {
							BaseOp.reg = MDCanonicalizeSubReg((ushort) BaseReg);
							if (BaseOp.is_reg(R_sp) 
								|| (this->UseFP && BaseOp.is_reg(R_bp))) {
								; // do nothing; DEF handled by case above
							}
							else {
								CurrUse = CurrInst->FindUse(BaseOp);
								if (CurrUse == CurrInst->GetLastUse()) {
									msg("ERROR: BaseReg %d not in USE list at %x for %s\n",
										BaseOp.reg, CurrInst->GetAddr(),
										CurrInst->GetDisasm());
								}
								assert(CurrUse != CurrInst->GetLastUse());
								if (this->IsGlobalName(BaseOp)) {
									changed |= this->PropagateGlobalMetadata(BaseOp,
										DEF_METADATA_USED, CurrUse->GetSSANum());
								}
								else {
									changed |= CurrInst->GetBlock()->PropagateLocalMetadata(BaseOp,
										DEF_METADATA_USED, CurrUse->GetSSANum());
								}
							}
						} // end if R_none != BaseReg
						if (R_none != IndexReg) {
							IndexOp.reg = MDCanonicalizeSubReg((ushort) IndexReg);
							if (IndexOp.is_reg(R_sp) 
								|| (this->UseFP && IndexOp.is_reg(R_bp))) {
								; // do nothing; DEF handled by case above
							}
							else {
								CurrUse = CurrInst->FindUse(IndexOp);
								if (CurrUse == CurrInst->GetLastUse()) {
									msg("ERROR: IndexReg %d not in USE list at %x for %s\n",
										IndexOp.reg, 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());
								}
								else {
									changed |= CurrInst->GetBlock()->PropagateLocalMetadata(IndexOp,
										DEF_METADATA_USED, CurrUse->GetSSANum());
								}
							}
						} // 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 ((o_reg == ReturnOp.type) &&
						(!ReturnOp.is_reg(X86_FLAGS_REG))) {
						if (this->IsGlobalName(ReturnOp)) {
							changed |= this->PropagateGlobalMetadata(ReturnOp,
									DEF_METADATA_USED, CurrUse->GetSSANum());
						}
						else {
							changed |= CurrInst->GetBlock()->PropagateLocalMetadata(ReturnOp,
									DEF_METADATA_USED, CurrUse->GetSSANum());
						}
					}
					CurrUse = NextUse;
				} // end while all USEs
			} // end if RETURN
			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.
				CurrUse = CurrInst->GetFirstUse();
				while (CurrUse != CurrInst->GetLastUse()) {
					NextUse = CurrUse;
					++NextUse;
					UseOp = CurrUse->GetOp();
					// NOTE: **!!** To be less conservative, we
					//  should propagate less for exchange category
					//  instructions.
					if ((UseOp.type == o_reg) && (!UseOp.is_reg(R_sp))
						&& (!(this->UseFP && UseOp.is_reg(R_bp)))
						&& (!UseOp.is_reg(X86_FLAGS_REG))) {

						if (this->IsGlobalName(UseOp)) {
							changed |= this->PropagateGlobalMetadata(UseOp,
									DEF_METADATA_USED, CurrUse->GetSSANum());
						}
						else {
							changed |= CurrInst->GetBlock()->PropagateLocalMetadata(UseOp,
									DEF_METADATA_USED, CurrUse->GetSSANum());
						}
					} // end if register
					CurrUse = NextUse;
				} // end while all USEs
			}
		} // end for all instructions
	} while (changed);

	// All DEFs that still have status DEF_METADATA_UNANALYZED can now
	//  be marked as DEF_METADATA_UNUSED.
	for (CurrInst = this->Instrs.begin(); CurrInst != this->Instrs.end(); ++CurrInst) {
		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) {
	bool changed = false;

	if ((0 > SSANum) || (o_void == UseOp.type))
		return false;

	// Find the DEF of UseOp with SSANum.
	bool FoundDef = false;
	list<SMPInstr>::iterator CurrInst;

	for (CurrInst = this->Instrs.begin(); CurrInst != this->Instrs.end(); ++CurrInst) {
		set<DefOrUse, LessDefUse>::iterator CurrDef;
		set<DefOrUse, LessDefUse>::iterator CurrUse;
		CurrDef = CurrInst->FindDef(UseOp);
		if (CurrDef != CurrInst->GetLastDef()) {
			if (SSANum == CurrDef->GetSSANum()) {
				FoundDef = true;
				if (Status != CurrDef->GetMetadataStatus()) {
					CurrDef = CurrInst->SetDefMetadata(UseOp, Status);
					changed = (CurrDef != CurrInst->GetLastDef());

					// 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.
					//  (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,
					//  but the register is both DEF and USE and we need
					//  to propagate through the register.
					if (CurrInst->HasSourceMemoryOperand()) {
						if (3 == CurrInst->GetOptType()) { // move inst
							break; // 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());
							break;
						}
					} // 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.
					CurrUse = CurrInst->GetFirstUse();
					while (CurrUse != CurrInst->GetLastUse()) {
						op_t UseOp = CurrUse->GetOp();
						// NOTE: **!!** To be less conservative, we
						//  should propagate less for exchange category
						//  instructions.
						if ((UseOp.type == o_reg) && (!UseOp.is_reg(R_sp))
							&& (!(this->UseFP && UseOp.is_reg(R_bp)))
							&& (!UseOp.is_reg(X86_FLAGS_REG))) {

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

	if (!FoundDef) {
		// Check the Phi functions
		list<SMPBasicBlock>::iterator CurrBlock;
		for (CurrBlock = this->Blocks.begin(); CurrBlock != this->Blocks.end(); ++CurrBlock) {
			set<SMPPhiFunction, LessPhi>::iterator DefPhi;
			DefPhi = CurrBlock->FindPhi(UseOp);
			if (DefPhi != CurrBlock->GetLastPhi()) {
				if (SSANum == DefPhi->GetDefSSANum()) {
					if (Status != DefPhi->GetDefMetadata()) {
						DefPhi = CurrBlock->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);
							}
						}
					}
					FoundDef = true;
					break;
				}
			}
		} // end for all blocks
	} // end if !FoundDef

	if (!FoundDef) {
		msg("ERROR: Could not find DEF of SSANum %d for: ");
		PrintOperand(UseOp);
		msg(" in function %s\n", this->GetFuncName());
	}

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

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

#if 0
	DumpFlag |= (0 == strcmp("_nl_find_msg", this->GetFuncName()));
	if (DumpFlag)
		this->Dump();
#endif
	this->ComputeIDoms();
	this->ComputeDomFrontiers();
	this->ComputeGlobalNames();
	this->ComputeBlocksDefinedIn();

	this->InsertPhiFunctions();
	this->BuildDominatorTree();
	this->SSARenumber();
	list<SMPBasicBlock>::iterator CurrBlock;
	for (CurrBlock = this->Blocks.begin(); CurrBlock != this->Blocks.end(); ++CurrBlock) {
		CurrBlock->SetLocalNames();
		CurrBlock->SSALocalRenumber();
		if (DebugFlag) CurrBlock->Dump();

#if SMP_FULL_LIVENESS_ANALYSIS
		CurrBlock->CreateGlobalChains();
#endif
#if 1
		CurrBlock->MarkDeadRegs();
#endif
	}
#if SMP_DEBUG_DATAFLOW
	if (DumpFlag)
		this->Dump();
#endif
	return;
} // end of SMPFunction::ComputeSSA()

// 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 CurrBlock;
#if SMP_DEBUG_DATAFLOW
	msg("SetLinks called for %s\n", this->GetFuncName());
#endif
	// First, set up the map of instructions to basic blocks.
	for (CurrBlock = this->Blocks.begin(); CurrBlock != this->Blocks.end(); ++CurrBlock) {
		list<list<SMPInstr>::iterator>::iterator CurrInst;
		for (CurrInst = CurrBlock->GetFirstInstr();
			CurrInst != CurrBlock->GetLastInstr();
			++CurrInst) {
				pair<ea_t, list<SMPBasicBlock>::iterator> MapItem((*CurrInst)->GetAddr(),CurrBlock);
				InstBlockMap.insert(MapItem);
		}
	}

#if SMP_DEBUG_DATAFLOW
	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 (CurrBlock = this->Blocks.begin(); CurrBlock != this->Blocks.end(); ++CurrBlock) {
		list<SMPInstr>::iterator CurrInst = *(--(CurrBlock->GetLastInstr()));
		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 TailCallFlag = CondTailCall && CurrInst->IsCondTailCall();
		bool IndirJumpFlag = (INDIR_JUMP == CurrInst->GetDataFlowType());
		xrefblk_t CurrXrefs;
		bool LinkedToTarget = false;
		for (bool ok = CurrXrefs.first_from(CurrInst->GetAddr(), XREF_ALL);
			ok;
			ok = CurrXrefs.next_from()) {
				if ((CurrXrefs.to != 0) && (CurrXrefs.iscode)) {
					// Found a code target, with its address in CurrXrefs.to
					if ((CallFlag || TailCallFlag) 
						&& (CurrXrefs.to != (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, list<SMPBasicBlock>::iterator>::iterator MapEntry;
					MapEntry = this->InstBlockMap.find(CurrXrefs.to);
					if (MapEntry == this->InstBlockMap.end()) {
						msg("WARNING: addr %x not found in map for %s\n", CurrXrefs.to,
							this->GetFuncName());
						msg(" Referenced from %s\n", CurrInst->GetDisasm());
					}
					else {
						list<SMPBasicBlock>::iterator 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) {
							msg("Switch table link: jump at %x target at %x\n",
								CurrInst->GetAddr(), CurrXrefs.to);
						}
#endif
					}
				}
		} // end for all xrefs
		if (IndirJumpFlag && (!LinkedToTarget)) {
			this->UnresolvedIndirectJumps = true;
			msg("WARNING: Unresolved indirect jump at %x\n",	CurrInst->GetAddr());
		}
	} // end for all blocks

	// 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.
#if SMP_USE_SWITCH_TABLE_INFO
	if (!(this->HasUnresolvedIndirectJumps())) {
#else
	if (!(this->HasIndirectJumps())) {
#endif
		bool changed;
		do {
			changed = false;
			CurrBlock = this->Blocks.begin();
			++CurrBlock; // don't delete the top block, no matter what.
			while (CurrBlock != this->Blocks.end()) {
				if (CurrBlock->GetFirstPred() == CurrBlock->GetLastPred()) {
					if (CurrBlock->AllNops())
						msg("Removing all nops block at %x\n", CurrBlock->GetFirstAddr());
					else
						msg("Removing block with no predecessors at %x\n", CurrBlock->GetFirstAddr());
					// Remove this block from the predecessors list of its successors.
					list<list<SMPBasicBlock>::iterator>::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.
					list<list<SMPInstr>::iterator>::iterator InstIter;
					for (InstIter = CurrBlock->GetFirstInstr(); InstIter != CurrBlock->GetLastInstr(); ++InstIter) {
						list<SMPInstr>::iterator DummyIter = this->Instrs.erase(*InstIter);
					}
					// Finally, remove the block from the blocks list.
					CurrBlock = this->Blocks.erase(CurrBlock);
					this->BlockCount -= 1;
					changed = true;
				}
				else
					++CurrBlock;
			} // end while all blocks after the first one
		} while (changed);
	} // end if not indirect jumps

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

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

	// Number the first block with 0.
	list<SMPBasicBlock>::iterator CurrBlock = this->Blocks.begin();
#if 0
	if (this->RPOBlocks.capacity() <= (size_t) this->BlockCount) {
		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<list<SMPBasicBlock>::iterator>::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<list<SMPBasicBlock>::iterator>::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
				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<list<SMPBasicBlock>::iterator>::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
			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.
	if (this->HasIndirectJumps()) {
		for (CurrBlock = this->Blocks.begin(); CurrBlock != this->Blocks.end(); ++CurrBlock) {
			if (SMP_BLOCKNUM_UNINIT == CurrBlock->GetNumber()) {
				msg("Numbering indirectly reachable block at %x\n", 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 CurrBlock;
#if SMP_DEBUG_DATAFLOW
	msg("LiveVariableAnalysis for %s\n", this->GetFuncName());
	bool DebugFlag = (0 == strcmp("__ieee754_pow", this->GetFuncName()));
#endif

	for (CurrBlock = this->Blocks.begin(); CurrBlock != this->Blocks.end(); ++CurrBlock) {
		// Initialize the Killed and UpwardExposed sets for each block.
		CurrBlock->InitKilledExposed();
	}

	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 (CurrBlock = this->Blocks.begin(); CurrBlock != this->Blocks.end(); ++CurrBlock) {
			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[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();
	for (UpExposedIter = this->Blocks.begin()->GetFirstUpExposed();
		UpExposedIter != this->Blocks.begin()->GetLastUpExposed();
		++UpExposedIter) {
			// Add DEF with SSANum of 0.
			MarkerInst->AddDef(*UpExposedIter, UNINIT, 0);
			// Add to the VarKill set.
			this->Blocks.begin()->AddVarKill(*UpExposedIter);
	}
	for (LiveOutIter = this->Blocks.begin()->GetFirstLiveOut();
		LiveOutIter != this->Blocks.begin()->GetLastLiveOut();
		++LiveOutIter) {
			if (!(this->Blocks.begin()->IsVarKill(*LiveOutIter))) {
				// Add DEF with SSANum of 0.
				MarkerInst->AddDef(*LiveOutIter, UNINIT, 0);
				// Add to the VarKill set.
				this->Blocks.begin()->AddVarKill(*LiveOutIter);
			}
	}
#endif

#if SMP_DEBUG_DATAFLOW
	if (DebugFlag) 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("__ieee754_pow", this->GetFuncName()));
	if (DebugFlag) 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) msg("BlockCount = %d\n", this->BlockCount);
	this->IDom[0] = 0; // Start block dominated only by itself
	bool changed;
	do {
		changed = false;
		for (size_t RPONum = 1; RPONum < (size_t) this->BlockCount; ++RPONum) {
			if (DebugFlag) msg("RPONum %d\n", RPONum);
			if (DebugFlag) {
				msg("RPOBlocks vector size: %d\n", this->RPOBlocks.size());
				for (size_t index = 0; index < this->RPOBlocks.size(); ++index) {
					msg("RPOBlocks entry %d is %d\n", index, RPOBlocks[index]->GetNumber());
				}
			}
			list<SMPBasicBlock>::iterator CurrBlock = this->RPOBlocks.at(RPONum);
			// if (DebugFlag) msg("CurrBlock: %x\n", CurrBlock._Ptr);
			list<list<SMPBasicBlock>::iterator>::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) 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) msg("Pred IDom: %d\n", PredIDOM);
				if (SMP_BLOCKNUM_UNINIT != PredIDOM) {
					NewIdom = PredNum;
					break;
				}
			}
			if (NewIdom == SMP_BLOCKNUM_UNINIT) {
				msg("Failure on NewIdom in ComputeIDoms for %s\n", this->GetFuncName());
				if (this->HasIndirectJumps()) {
					// Might be reachable only through indirect jumps.
					NewIdom = 0; // make it dominated by entry block
				}
			}
			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) msg("PredNum: %d\n", PredNum);
				// **!!** We could 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.
				if (PredNum == SMP_BLOCKNUM_UNINIT)
					continue;
				int PredIDOM = this->IDom.at(PredNum);
				if (DebugFlag) 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) msg("Old NewIdom value: %d\n", NewIdom);
				NewIdom = this->IntersectDoms(PredNum, NewIdom);
				if (DebugFlag) 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) 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 CurrBlock;
	list<SMPBasicBlock>::iterator RunnerBlock;
	for (CurrBlock = this->Blocks.begin(); CurrBlock != this->Blocks.end(); ++CurrBlock) {
		// 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<list<SMPBasicBlock>::iterator>::iterator CurrPred;
			for (CurrPred = CurrBlock->GetFirstPred(); CurrPred != CurrBlock->GetLastPred(); ++CurrPred) {
				// 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 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("__ieee754_pow", this->GetFuncName()));
#endif

	for (CurrBlock = this->Blocks.begin(); CurrBlock != this->Blocks.end(); ++CurrBlock) {
		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
			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
				msg(" already in GlobalNames.\n");
#endif
			}
			else {
				++index;
#if SMP_DEBUG_DATAFLOW
				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 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
	msg("Number of GlobalNames: %d\n", this->GlobalNames.size());
	msg("Size of BlocksDefinedIn: %d\n", this->BlocksDefinedIn.size());
#endif
	for (CurrBlock = this->Blocks.begin(); CurrBlock != this->Blocks.end(); ++CurrBlock) {
		set<op_t, LessOp>::iterator KillIter;
		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.
					msg("ComputeBlocksDefinedIn: Bad index: %d limit: %d\n", index,
						this->GlobalNames.size());
					msg("Block number %d\n", CurrBlock->GetNumber());
					msg("Killed item: ");
					PrintListOperand(*KillIter);
					msg("\n");
					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("__ieee754_pow", this->GetFuncName()));
#endif
	if (DebugFlag) msg("GlobalNames size: %d\n", this->GlobalNames.size());
	for (NameIter = this->GlobalNames.begin(); NameIter != this->GlobalNames.end(); ++NameIter) {
		int CurrNameIndex = (int) (ExtractGlobalIndex(*NameIter));
		if (DebugFlag) 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
			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
				msg("WorkIter: %d\n", *WorkIter);
#endif
				if (DebugFlag && (*WorkIter > this->BlockCount)) {
					msg("ERROR: WorkList block # %d out of range.\n", *WorkIter);
				}
				list<SMPBasicBlock>::iterator WorkBlock = this->RPOBlocks[*WorkIter];
				for (DomFrontIter = WorkBlock->GetFirstDomFrontier();
					DomFrontIter != WorkBlock->GetLastDomFrontier();
					++DomFrontIter) {
#if SMP_DEBUG_DATAFLOW
					msg("DomFront: %d\n", *DomFrontIter);
#endif
					if (DebugFlag && (*DomFrontIter > this->BlockCount)) {
						msg("ERROR: DomFront block # %d out of range.\n", *DomFrontIter);
					}
					list<SMPBasicBlock>::iterator 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
							msg("Added phi for name %d at top of block %d\n", CurrNameIndex, PhiBlock->GetNumber());
#endif
						}
					}
					else {
						if (DebugFlag) {
							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) {
					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) 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()

// 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);
	list<SMPBasicBlock>::iterator CurrBlock = this->RPOBlocks.at((size_t) BlockNumber);

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

	if (DumpFlag) 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) {
		GlobalNameIndex = CurrPhi->GetIndex();
		assert(0 <= GlobalNameIndex);
		int NewSSANum = this->SSANewNumber((size_t) GlobalNameIndex);
#if 0
			// g++ is a pain in the neck and won't allow changes to the set item
			//  through CurrPhi, which it types as a const iterator, so this next line does
			//  not compile in g++.
		CurrPhi->SetSSADef(NewSSANum);
#else
		SMPPhiFunction TempPhi = (*CurrPhi);
		TempPhi.SetSSADef(NewSSANum);
		TempPhiList.push_back(TempPhi);
#endif
	}
	// Go back through the Phi function set and replace the items that need to be updated.
	//  Thank you g++ for being a pain.
	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) msg("Processed phi functions at top.\n");

	// For each instruction in the block, rename all global USEs and then all global DEFs.
	list<list<SMPInstr>::iterator>::iterator CurrInst;
	for (CurrInst = CurrBlock->GetFirstInstr(); CurrInst != CurrBlock->GetLastInstr(); ++CurrInst) {
		set<DefOrUse, LessDefUse>::iterator CurrUse = (*CurrInst)->GetFirstUse();
		while (CurrUse != (*CurrInst)->GetLastUse()) {
			// See if Use is a global name.
			set<op_t, LessOp>::iterator GlobIter = this->GlobalNames.find(CurrUse->GetOp());
			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.
					msg("Bad GlobIndex: %d\n", GlobIndex);
					msg("Error in function %s\n", 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 == GlobIter->type)) {
						// POP uses the stack offset and generates spurious
						//  uninitialized variable messages for [esp+0].
						msg("WARNING: function %s : Use of uninitialized variable: ",
							this->GetFuncName());
						msg(" Variable: ");
						PrintListOperand(*GlobIter);
						msg(" Block number: %d Address: %x Instruction: %s\n", BlockNumber,
							(*CurrInst)->GetAddr(), (*CurrInst)->GetDisasm());
					}
#endif
					NewSSANum = SMP_SSA_UNINIT;
				}
				else {
					NewSSANum = this->SSAStack.at(GlobIndex).back();
				}
				CurrUse = (*CurrInst)->SetUseSSA(CurrUse->GetOp(), NewSSANum);
			}
			++CurrUse;
		} // end for all USEs
		set<DefOrUse, LessDefUse>::iterator CurrDef = (*CurrInst)->GetFirstDef();
		while (CurrDef != (*CurrInst)->GetLastDef()) {
			// 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);
				// Set the SSA number for this DEF to the SSANewNumber top of stack
				CurrDef = (*CurrInst)->SetDefSSA(CurrDef->GetOp(), this->SSANewNumber(GlobIndex));
			}
			++CurrDef;
		} //  end for all DEFs
	} // end for all instructions
	if (DumpFlag) 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<list<SMPBasicBlock>::iterator>::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
				msg("WARNING: function %s : Path to use of uninitialized variable: ",
					this->GetFuncName());
				msg(" Variable: ");
				PrintListOperand(CurrPhi->GetAnyOp());
				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
			}
#if 0
			// g++ is a pain in the neck and won't allow changes to the set item
			//  through CurrPhi, which it types as a const iterator, so this next line does
			//  not compile in g++. C++ does not know how to distinguish between changing
			//  the field that ordering is based on, and other fields, so g++ has to be
			//  strict, I guess.
			CurrPhi->SetSSARef(ListPos, CurrSSA);
#else
			SMPPhiFunction TempPhi = (*CurrPhi);
			TempPhi.SetSSARef(ListPos, CurrSSA);
			TempPhiList.push_back(TempPhi);
			if (DumpFlag && (BlockNumber >= 3) && (BlockNumber <= 4)) {
				msg("BlockNumber: %d  ListPos: %d\n", BlockNumber, ListPos);
			}
#endif
		} // end for all phi functions in successor
		// Go back through the Phi function set and replace the items that need to be updated.
		//  Thank you g++ for being a pain.
		for (TempIter = TempPhiList.begin(); TempIter != TempPhiList.end(); ++TempIter) {
			if (DumpFlag && (BlockNumber >= 3) && (BlockNumber <= 4)) {
				msg("Special before phi dump:\n");
				set<SMPPhiFunction, LessPhi>::iterator FoundPhi;
				FoundPhi = (*SuccIter)->FindPhi(TempIter->GetAnyOp());
				FoundPhi->Dump();
			}
			// 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)) {
				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) 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) 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) msg("Popped off entries due to phi functions.\n");
	for (CurrInst = CurrBlock->GetFirstInstr(); CurrInst != CurrBlock->GetLastInstr(); ++CurrInst) {
		set<DefOrUse, LessDefUse>::iterator CurrDef;
		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) msg("Popped off entries due to instructions.\n");

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

// Main driver of SSA subscript renumbering.
void SMPFunction::SSARenumber(void) {
	if (0 >= this->GlobalNames.size())
		return;  // no names to renumber

	// Initialize stacks and counters of SSA numbers.
	size_t GlobIndex;
	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);
	return;
} // end of SMPFunction::SSARenumber()

// 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.
	//
	// The type inference system will mark DEFs and USEs in each instruction's DEF and USE
	//  sets with an inferred type. This inference 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 immportant 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;
	bool UnsafeFunc = (FUNC_SAFE != this->ReturnAddrStatus);
	bool DebugFlag = false;
#if SMP_DEBUG_TYPE_INFERENCE
	DebugFlag |= (0 == strcmp("weightadj", this->GetFuncName()));
#endif
	list<SMPInstr>::iterator CurrInst;
	set<DefOrUse, LessDefUse>::iterator CurrDef;
	set<DefOrUse, LessDefUse>::iterator NextDef;
	list<SMPBasicBlock>::iterator CurrBlock;

	if (DebugFlag) {
		this->Dump();
	}
	// One time only: Set the types of immediate values, flags register, stack and frame
	//  pointers, and floating point registers.
	if (FirstIter) {
		for (CurrInst = this->Instrs.begin(); CurrInst != this->Instrs.end(); ++CurrInst) {
			if (DebugFlag) {
				msg("SetImmedTypes for inst at %x: %s\n", CurrInst->GetAddr(), CurrInst->GetDisasm());
			}
			CurrInst->SetImmedTypes(this->UseFP);
		}
	}

	// 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 {
		do {
			changed = false;
			// 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 (CurrInst = this->Instrs.begin(); CurrInst != this->Instrs.end(); ++CurrInst) {
				if (DebugFlag) msg("Inferring types for %s\n", CurrInst->GetDisasm());
				NewChange = CurrInst->InferTypes();
				changed = (changed || NewChange);
			}
		} while (changed);
		if (DebugFlag) msg("Finished type inference steps 1 and 2.\n");
		// 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;
		for (CurrInst = this->Instrs.begin(); CurrInst != this->Instrs.end(); ++CurrInst) {
			// 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;
				if (UNINIT != CurrDef->GetType()) {
					++(this->TypedDefs);
				}
				else {
					++(this->UntypedDefs);
					op_t DefOp = CurrDef->GetOp();
					if (MDIsIndirectMemoryOpnd(DefOp, this->UseFP)
						|| (o_mem == DefOp.type)
						|| ((o_reg != DefOp.type) && UnsafeFunc)) {
						// Don't want to infer along DEF-USE chains for indirect
						//  memory accesses until we have alias analysis.
						++CurrDef;
						continue;
					}
					ea_t DefAddr = CurrInst->GetAddr();
					// Call inference method based on whether it is a block-local
					//  name or a global name.
					if (CurrInst->GetBlock()->IsLocalName(DefOp)) {
						set<op_t, LessOp>::iterator NameIter;
						NameIter = CurrInst->GetBlock()->FindLocalName(DefOp);
						assert(CurrInst->GetBlock()->GetLastLocalName() != NameIter);
						unsigned int LocIndex = ExtractGlobalIndex(*NameIter);
						NewChange = CurrInst->GetBlock()->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()));
						SMPOperandType DefType = UNINIT;
						DefType = this->InferGlobalDefType(DefOp,
							CurrDef->GetSSANum(), CurrInst->GetBlock(), CallInst);
						if (IsNotEqType(UNINIT, DefType)) {
							CurrDef = CurrInst->SetDefType(DefOp, DefType);
							--(this->UntypedDefs);
							++(this->TypedDefs);
							NewChange = true;
						}
						changed = (changed || NewChange);
					}
				}
				CurrDef = NextDef;
			} // end while all DEFs in the DEF set
		} // end for all instructions
		if (DebugFlag) msg("Finished type inference step 3.\n");
		if (!changed) { // Check for Phi function DEFs that are still UNINIT
			for (CurrBlock = this->Blocks.begin(); CurrBlock != this->Blocks.end(); ++CurrBlock) {
				changed |= CurrBlock->InferAllPhiDefTypes();
			}
		}
		if (DebugFlag) msg("Finished unconditional phi type inference.\n");

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

	} while (changed);

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

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

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

	for (CurrInst = this->Instrs.begin(); CurrInst != this->Instrs.end(); ++CurrInst) 
	{
		InstructionInformation* ii=pi->GetInfo( CurrInst->GetAddr());
		if(ii && DebugFlag)
			msg("Found instruction information for %x\n", CurrInst->GetAddr());
		if(ii && ii->isNumeric())
		{
			msg("Found instruction information for %x and it's numeric!\n", CurrInst->GetAddr());
			CurrInst->UpdateMemLoadTypes((SMPOperandType)(NUMERIC|PROF_BASE));
		}
	}
}	// 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.
SMPOperandType SMPFunction::InferGlobalDefType(op_t DefOp, int SSANum, SMPBasicBlock *DefBlock, bool CallInst) {
	bool DebugFlag = false;
	bool FoundNumeric = false;
	bool FoundPointer = false;
	bool FoundUnknown = false;
	bool FoundUninit = false;

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

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

	list<SMPInstr>::iterator InstIter;

	assert(0 <= SSANum);
	set<DefOrUse, LessDefUse>::iterator CurrUse;
	// Go through all instructions in the function 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.
	bool FirstUseSeen = false;
	SMPOperandType UseType = UNINIT;
	SMPOperandType PtrType = UNINIT;
	for (InstIter = this->Instrs.begin(); InstIter != this->Instrs.end(); ++InstIter) {
		CurrUse = InstIter->FindUse(DefOp);
		if (CurrUse != InstIter->GetLastUse()) { // found a USE of DefOp
			if (CurrUse->GetSSANum() == SSANum) { // matched SSA number
				if (!FirstUseSeen) {
					FirstUseSeen = true;
				}
				UseType = CurrUse->GetType();
				FoundNumeric |= (IsNumeric(UseType));
				FoundUnknown |= (IsUnknown(UseType));
				FoundUninit |= (IsEqType(UNINIT, UseType));
				if (IsDataPtr(UseType)) {
					if (FoundPointer) {
						if (IsNotEqType(PtrType, UseType)) {
							msg("WARNING: Differing ptr types in global chain:");
							msg(" Prev: %d Current: %d %s\n", PtrType, UseType,
								InstIter->GetDisasm());
						}
						PtrType = POINTER;
					}
					else {
						FoundPointer = true;
						PtrType = UseType;
					}
				}
			} // end if matched SSA #
		} // end if found a USE of DefOp
	} // end for all instructions

	// Now, we need to check the phi functions and see if there are Phi USEs of the DefOp.
	set<SMPPhiFunction, LessPhi>::iterator UsePhi;
	size_t BlockNum;
	for (BlockNum = 0; BlockNum < (size_t) this->BlockCount; ++BlockNum) {
		UsePhi = this->RPOBlocks.at(BlockNum)->FindPhi(DefOp);
		if (UsePhi != this->RPOBlocks.at(BlockNum)->GetLastPhi()) {
			// Found phi function for DefOp. See if we can find a USE
			//  with USE SSANum corresponding to our DEF SSANum.
			for (size_t PhiIndex = 0; PhiIndex < UsePhi->GetPhiListSize(); ++PhiIndex) {
				if (UsePhi->GetUseSSANum(PhiIndex) == SSANum) {
					// We have a Phi USE that matches our DEF.
					if (!FirstUseSeen) {
						FirstUseSeen = true;
					}
					UseType = UsePhi->GetUseType(PhiIndex);
					FoundNumeric |= (IsNumeric(UseType));
					FoundUnknown |= (IsUnknown(UseType));
					FoundUninit |= (IsEqType(UNINIT, UseType));
					if (IsDataPtr(UseType)) {
						if (FoundPointer) {
							if (IsNotEqType(PtrType, UseType)) {
								msg("WARNING: Differing ptr types in global chain at Phi:");
								msg(" Prev: %d Current: %d BlockNum: %d\n",
									PtrType, UseType, BlockNum);
							}
							PtrType = POINTER;
						}
						else {
							FoundPointer = true;
							PtrType = UseType;
						}
					}
				} // end if matched SSA #
			} // end for all Phi USEs
		} // end if found matching Phi function for DefOp
	} // end for all block numbers in the function

	if (FirstUseSeen) {
		// 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) msg("Inferring global DEF of type %d\n", UseType);
		return UseType;
	}
	else { // not FirstUseSeen
		// If the block returns, then the DEFs could be used in the caller.
		if (!(DefBlock->HasReturn())) {
			UseType = UNINIT;
			// We probably want to set the DEF type to NUMERIC if there are no uses.
			//  Have to check these cases out manually in the *.asm first.  **!!**
			//  If they are memory DEFs, we cannot optimize, so we might want to see
			//  if we can find a reg DEF with no USEs here. We also want to exclude
			//  warning messages for the caller-saved reg DEFs generated for CALLs.
			if ((o_reg == DefOp.type) && (!CallInst)) {
				;
#if SMP_WARN_UNUSED_DEFS
				msg("WARNING: global DEF with no USEs for SSANum %d DefOp: ",
					SSANum);
				PrintOperand(DefOp);
				msg("\n");
#endif
			}
		}
	}

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

#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;
	list<SMPBasicBlock>::iterator CurrBlock;
	vector<list<SMPBasicBlock>::iterator>::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();
			CurrPhi = CurrBlock->SetPhiDefType(DefOp, MeetType);
			changed = true;
			this->ResetProcessedBlocks();
			changed |= CurrBlock->PropagateGlobalDefType(DefOp,
				MeetType, CurrPhi->GetDefSSANum());
		} // 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->ReturnAddrStatus == 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 CurrInst;
		for (CurrInst = this->Instrs.begin(); CurrInst != this->Instrs.end(); ++CurrInst) {
			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 ...

// Emit all annotations for the function, including all per-instruction
//  annotations.
void SMPFunction::EmitAnnotations(FILE *AnnotFile) {
	// Emit annotation for the function as a whole.
	if (this->StaticFunc) {
		qfprintf(AnnotFile,	"%10x %6d FUNC LOCAL  %s ", this->FuncInfo.startEA,
			this->Size, this->FuncName);
	}
	else {
		qfprintf(AnnotFile,	"%10x %6d FUNC GLOBAL %s ", this->FuncInfo.startEA,
			this->Size, this->FuncName);
	}
	switch (this->ReturnAddrStatus)
	{
		case FUNC_UNKNOWN:
		{
			qfprintf(AnnotFile, "FUNC_UNKNOWN ");
			break;
		}
		case FUNC_SAFE:
		{
			qfprintf(AnnotFile, "FUNC_SAFE ");
			break;
		}
		case FUNC_UNSAFE:
		{
			qfprintf(AnnotFile, "FUNC_UNSAFE ");
			break;
		}
		default:
			assert(0);	
	}
	if (this->UseFP) {
		qfprintf(AnnotFile, "USEFP ");
	}
	else {
		qfprintf(AnnotFile, "NOFP ");
	}
	if (this->FuncInfo.does_return()) {
		qfprintf(AnnotFile, "RET ");
	}
	else {
		qfprintf(AnnotFile, "NORET ");
	}
#ifdef SMP_DEBUG_FUNC
	if (this->IsLeaf())
		qfprintf(AnnotFile, "FUNC_LEAF ");
	// store the return address
	qfprintf(AnnotFile,"%10x ", this->FuncInfo.endEA - 1);
#endif
	qfprintf(AnnotFile, "\n");

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

	// 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<SMPInstr>::iterator CurrInst;
	bool AllocSeen = false; // Reached LocalVarsAllocInstr yet?
	bool DeallocTrigger = false;
	for (CurrInst = Instrs.begin(); CurrInst != Instrs.end(); ++CurrInst) {

#if SMP_USE_SSA_FNOP_MARKER
		if (this->Instrs.begin() == CurrInst)
			continue;  // skip marker instruction
#endif

		ea_t addr = CurrInst->GetAddr();

		qfprintf(AnnotFile, "%10x %6d INSTR BELONGTO %x \n", addr, 0, GetStartAddr());

		if (this->LocalVarsAllocInstr == addr) {
			AllocSeen = true;
			if (FUNC_SAFE != this->ReturnAddrStatus)
				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
			qfprintf(AnnotFile,	"%10x %6d DEALLOC STACK esp - %d %s\n", addr,
				LocalVarsSize, LocalVarsSize, CurrInst->GetDisasm());
			DeallocTrigger = false;
		}

		if (this->HasGoodRTLs()) {
			CurrInst->EmitTypeAnnotations(this->UseFP, AllocSeen, AnnotFile);
		}
		else {
			CurrInst->EmitAnnotations(this->UseFP, AllocSeen, AnnotFile);
		}
		if (CurrInst->MDIsReturnInstr() && this->GetReturnAddressStatus() == FUNC_SAFE )
			CurrInst->EmitSafeReturn(AnnotFile);
	}  // end for all instructions
	return;
} // end of SMPFunction::EmitAnnotations()

// Debug output dump.
void SMPFunction::Dump(void) {
	list<SMPBasicBlock>::iterator CurrBlock;
	msg("Debug dump for function: %s\n", this->GetFuncName());
	msg("UseFP: %d  LocalVarsAllocInstr: %x\n", this->UseFP,
		this->LocalVarsAllocInstr);
	for (size_t index = 0; index < this->IDom.size(); ++index) {
		msg("IDOM for %d: %d\n", index, this->IDom.at(index));
	}
	for (size_t index = 0; index < this->DomTree.size(); ++index) {
		msg("DomTree for %d: ", index);
		list<int>::iterator DomIter;
		for (DomIter = this->DomTree.at(index).second.begin();
			DomIter != this->DomTree.at(index).second.end();
			++DomIter) {
				msg("%d ", *DomIter);
		}
		msg("\n");
	}
	msg("Global names: \n");
	set<op_t, LessOp>::iterator NameIter;
	for (NameIter = this->GlobalNames.begin(); NameIter != this->GlobalNames.end(); ++NameIter) {
		msg("index: %d ", ExtractGlobalIndex(*NameIter));
		PrintListOperand(*NameIter);
		msg("\n");
	}
	msg("Blocks each name is defined in: \n");
	for (size_t index = 0; index < this->BlocksDefinedIn.size(); ++index) {
		msg("Name index: %d Blocks: ", index);
		list<int>::iterator BlockIter;
		for (BlockIter = this->BlocksDefinedIn.at(index).begin();
			BlockIter != this->BlocksDefinedIn.at(index).end();
			++BlockIter) {
			msg("%d ", *BlockIter);
		}
		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();
	}
	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
	msg(" Analyzing function name %s and isLeaf=%d ", this->GetFuncName(), this->IsLeaf());
#endif
	bool HasDirectCallTargets = false;
	bool HasStackPointerCopy = false;
	bool HasStackPointerPush = false;
	bool HasIndirectGlobalWrite = false;
	bool WritesAboveLocalFrame = false;
	bool HasIndexedStackWrite = false;
	bool HasIndirectWrite = false;

	this->ReturnAddrStatus = FUNC_SAFE;

	if (!this->DirectCallTargets.empty()) {
		HasDirectCallTargets = true;
	}

#if SMP_USE_SWITCH_TABLE_INFO
	if (this->UnresolvedIndirectJumps) {
#else
	if (this->IndirectJumps) {
#endif
#if SMP_DEBUG_FUNC
		msg(" Function marked as unsafe due to indirect jumps %s\n", this->GetFuncName());
#endif
	}
	list<SMPInstr>::iterator Instructions;

	// while processing the stack pointer writes the prologue code for
	// saving frame register and allcating local variables needs to be
	// handled
	bool SaveEBP = false;
	bool XferESPtoEBP = false;
	for (Instructions = Instrs.begin(); Instructions != Instrs.end();	Instructions++) {

#if SMP_USE_SSA_FNOP_MARKER
		if (this->Instrs.begin() == Instructions)
			continue;  // skip marker instruction
#endif

#if SMP_VERBOSE_DEBUG_FUNC 
		msg(" Total number of defs for this instruction %d\n", Instructions->NumDefs());
#endif
		if (!SaveEBP) { // still looking for "push ebp"
			if (Instructions->MDIsPushInstr() && Instructions->GetCmd().Operands[0].is_reg(R_bp)) {
				SaveEBP = true;
				continue;
			}
		}
		else if (!XferESPtoEBP) { // found "push ebp", looking for "mov ebp,esp"
			insn_t CurrCmd = Instructions->GetCmd();
			if ((CurrCmd.itype == NN_mov)
					&& (Instructions->GetFirstDef()->GetOp().is_reg(R_bp))
					&& (Instructions->GetFirstUse()->GetOp().is_reg(R_sp))) {
				XferESPtoEBP = true;
				continue;
			}
		}
		ea_t address = Instructions->GetAddr();
		if (address == this->LocalVarsAllocInstr ||
		    address == this->LocalVarsDeallocInstr)
			continue;

		if (Instructions->MDIsStackPointerCopy(this->UseFP)) {
			HasStackPointerCopy = true;
#if SMP_DEBUG_FUNC 
			msg(" Function marked as unsafe %s due to stack pointer copy \n ", this->GetFuncName());
			msg("%s %x \n", (Instructions)->GetDisasm(), (Instructions)->GetAddr());
#endif
		}
		if (Instructions->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 (Instructions->GetCmd().Operands[0].is_reg(R_sp) || 	 
					( this->UseFP && Instructions->GetCmd().Operands[0].is_reg(R_bp))) {
				HasStackPointerPush = true;
#if SMP_DEBUG_FUNC 
				msg(" Function marked as unsafe %s due to push on ebp or esp outside of function header \n", this->GetFuncName());	
				msg("%s %x\n", (Instructions)->GetDisasm(), (Instructions)->GetAddr());
#endif
			}
			continue;
		}
		if (Instructions->MDIsPopInstr()) {
			// ignore pops for the moment
			 continue;
		}
		set<DefOrUse, LessDefUse>::iterator setIterator;
		for (setIterator = Instructions->GetFirstDef(); setIterator != Instructions->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;
				}
				HasIndirectGlobalWrite = true;
			}
			if (Operand.type == o_displ) {
				MDExtractAddressFields(Operand, BaseReg, IndexReg, ScaleFactor, offset);
				if ((BaseReg == R_sp) || (this->UseFP && (BaseReg == R_bp))) {
					if (IndexReg == R_none) {
						if (offset > this->LocalVarsSize ) {
							WritesAboveLocalFrame = true;
#if SMP_DEBUG_FUNC 
							msg(" Function marked as unsafe %s due to write above loc variables offset=%x  loc=%x\n ", this->GetFuncName(), offset, this->LocalVarsSize);	
							msg("%s %x\n", (Instructions)->GetDisasm(), (Instructions)->GetAddr());
#endif
						}
					}
					else {
						HasIndexedStackWrite = true;
#if SMP_DEBUG_FUNC 
						msg(" Function marked as unsafe %s due to indexed stack write\n", this->GetFuncName());	
						msg("%s %x\n", (Instructions)->GetDisasm(), (Instructions)->GetAddr());
#endif
					}
				}
				else {
					HasIndirectWrite = true;
				}
			}
			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 ((BaseReg == R_sp || (this->UseFP && BaseReg == R_bp))) {
					if (IndexReg == R_none) {
#if SMP_DEBUG_FUNC 
						msg(" Does MemOp with phrase have displ %s %x  ", this->GetFuncName(), Operand.addr);	
#endif
						continue;
					}
					else {
						HasIndexedStackWrite = true;
#if SMP_DEBUG_FUNC 
						msg(" Function marked as unsafe %s due to indexed stack write\n", this->GetFuncName());	
						msg("%s %x\n", (Instructions)->GetDisasm(), (Instructions)->GetAddr());
#endif
					}
				}
				else {
					HasIndirectWrite = true;
				}
			}
		}
	}

	if (HasStackPointerCopy || HasStackPointerPush || HasIndirectGlobalWrite
		|| WritesAboveLocalFrame || HasIndexedStackWrite || HasIndirectWrite
		|| this->UnresolvedIndirectJumps || this->IndirectCalls
		|| this->SharedChunks || (!this->AnalyzedSP)) {

		this->ReturnAddrStatus = FUNC_UNSAFE;
		msg("UNSAFE function %s ", this->GetFuncName());
		msg("StackPtrCopy: %d StackPtrPush: %d IndirectGlobal: %d ",
			HasStackPointerCopy, HasStackPointerPush, HasIndirectGlobalWrite);
		msg("WritesAboveFrame: %d IndirectStack: %d IndirectWrite: %d ",
			WritesAboveLocalFrame, HasIndexedStackWrite, HasIndirectWrite);
		msg("AnalyzedSP: %d IndirectCalls: %d UnresolvedJumps: %d SharedChunks: %d IsLeaf: %d\n",
			this->AnalyzedSP, this->IndirectCalls, this->UnresolvedIndirectJumps,
			this->SharedChunks, this->IsLeaf());
	}
	else if (HasDirectCallTargets) {
		this->ReturnAddrStatus = FUNC_UNKNOWN;
	}
	return;
} // end of SMPFunction::MarkFunctionSafe()