sourcepawn/decompiler/code_analyzer.cpp
author David Anderson <dvander@alliedmods.net>
Sat Sep 27 15:34:59 2008 -0500 (2008-09-27)
changeset 2325 7a24ee5557fb
parent 2322 2125ced692ac
permissions -rw-r--r--
Fixed building on GCC and some valgrind warnings. Read .dbg.natives table now.
     1 #include <assert.h>
     2 #include <string.h>
     3 #include <stdlib.h>
     4 #include "decompiler.h"
     5 #include "code_analyzer.h"
     6 #include "platform_util.h"
     7 
     8 struct Block;
     9 
    10 #define PCM_BRANCH_TARGET		(1<<0)
    11 #define PCM_OPCODE				(1<<1)
    12 #define PCM_HAS_BLOCK			(1<<2)
    13 #define PCM_NUM_BITS			3
    14 
    15 #define NEXT_OP(cip, op)		cip += (dc->opdef[op].params + 1) * sizeof(cell_t)
    16 
    17 struct Edge
    18 {
    19 	Edge *next;
    20 	Block *target;
    21 	uint32_t ip;
    22 };
    23 
    24 struct Block
    25 {
    26 	cell_t ip_start;
    27 	cell_t ip_end;
    28 	Edge *edge_list;
    29 	Edge *final_edge;
    30 	Block *next_in_table;
    31 };
    32 
    33 struct ControlFlowGraph
    34 {
    35 	int err;
    36 	unsigned int max_blocks;
    37 	unsigned int max_edges;
    38 	unsigned int used_blocks;
    39 	unsigned int used_edges;
    40 	Block *blocks;
    41 	Edge *edges;
    42 	Block *entry;
    43 	FunctionInfo *func;
    44 };
    45 
    46 DefineNode::DefineNode(BaseNode *o, const char *fmt, ...) : BaseNode(_OP_DEFINE), other(o)
    47 {
    48 	va_list ap;
    49 	
    50 	va_start(ap, fmt);
    51 	Sp_FormatArgs(name, sizeof(name), fmt, ap);
    52 	va_end(ap);
    53 }
    54 
    55 static FunctionInfo *sp_InferFuncPrototype(sp_decomp_t *dc, uint32_t code_addr, bool is_public)
    56 {
    57 	sp_tag_t *pTag;
    58 	sp_file_t *plugin;
    59 	FunctionInfo *info;
    60 	sp_fdbg_symbol_t *sym;
    61 
    62 	plugin = dc->plugin;
    63 	info = new FunctionInfo;
    64 	memset(info, 0, sizeof(FunctionInfo));
    65 
    66 	info->code_addr = code_addr;
    67 	
    68 	if ((sym = Sp_FindFunctionSym(plugin, code_addr)) != NULL)
    69 	{
    70 		Sp_Format(info->name, sizeof(info->name), "%s", plugin->debug.stringbase + sym->name);
    71 		if (sym->tagid != 0)
    72 		{
    73 			info->tag = Sp_FindTag(plugin, sym->tagid);
    74 		}
    75 	}
    76 	else
    77 	{
    78 		Sp_Format(info->name, sizeof(info->name), "function_%x", code_addr);
    79 		for (uint32_t i = 0; i < plugin->num_publics; i++)
    80 		{
    81 			if (plugin->publics[i].code_offs == code_addr)
    82 			{
    83 				Sp_Format(info->name,
    84 					sizeof(info->name),
    85 					"%s",
    86 					plugin->publics[i].name);
    87 				break;
    88 			}
    89 		}
    90 	}
    91 	info->sym = sym;
    92 	info->is_public = is_public;
    93 	
    94 
    95 	/* Search for all locals */
    96 	{
    97 		uint32_t i;
    98 		uint8_t *cursor;
    99 
   100 		cursor = (uint8_t *)plugin->debug.symbols;
   101 		for (i = 0; i < plugin->debug.syms_num; i++)
   102 		{
   103 			sym = (sp_fdbg_symbol_t *)cursor;
   104 
   105 			if (sym->ident == SP_SYM_VARIABLE
   106 				|| sym->ident == SP_SYM_REFARRAY
   107 				|| sym->ident == SP_SYM_REFERENCE
   108 				|| sym->ident == SP_SYM_ARRAY)
   109 			{
   110 				if (code_addr >= sym->codestart
   111 					&& code_addr < sym->codeend
   112 					&& sym->addr >= 0xC
   113 					&& (sym->addr & 0x3) == 0
   114 					&& ((sym->addr - 0xC) >> 2) < SP_MAX_EXEC_PARAMS
   115 					&& sym->vclass == 1)
   116 				{
   117 					unsigned int num;
   118 
   119 					num = (sym->addr - 0xC) >> 2;
   120 					info->known_args[num].sym = sym;
   121 					if (num + 1 > info->num_known_args)
   122 					{
   123 						info->num_known_args = num + 1;
   124 					}
   125 				}
   126 			}
   127 
   128 			cursor += sizeof(sp_fdbg_symbol_t);
   129 			if (sym->dimcount > 0)
   130 			{
   131 				cursor += sizeof(sp_fdbg_arraydim_t) * sym->dimcount;
   132 			}
   133 		}
   134 	}
   135 
   136 	/* Map all arguments into place. */
   137 	for (unsigned int i = 0; i < info->num_known_args; i++)
   138 	{
   139 		if ((sym = info->known_args[i].sym) == NULL)
   140 		{
   141 			continue;
   142 		}
   143 		if (sym->tagid != 0 && (pTag = Sp_FindTag(plugin, sym->tagid)) != NULL)
   144 		{
   145 			info->known_args[i].tag = pTag;
   146 		}
   147 		info->known_args[i].name = plugin->debug.stringbase + sym->name;
   148 		
   149 		info->known_args[i].dimcount = sym->dimcount;
   150 		if (sym->dimcount > 0)
   151 		{
   152 			info->known_args[i].dims = 
   153 				(sp_fdbg_arraydim_t *)((char *)sym + sizeof(sp_fdbg_symbol_t));
   154 		}
   155 	}
   156 
   157 	return info;
   158 }
   159 
   160 static FunctionInfo *sp_GetFuncPrototype(sp_decomp_t *dc,
   161 										 uint32_t code_addr,
   162 										 bool known,
   163 										 bool is_public = false);
   164 static FunctionInfo *sp_GetFuncPrototype(sp_decomp_t *dc,
   165 										 uint32_t code_addr,
   166 										 bool known,
   167 										 bool is_public)
   168 {
   169 	FunctionInfo *func;
   170 
   171 	func = dc->funcs;
   172 	while (func != NULL)
   173 	{
   174 		if (func->code_addr == code_addr)
   175 		{
   176 			return func;
   177 		}
   178 		func = func->next;
   179 	}
   180 
   181 	/* See if this is public. */
   182 	if (!known)
   183 	{
   184 		is_public = false;
   185 		for (unsigned int i = 0; i < dc->plugin->num_publics; i++)
   186 		{
   187 			if (dc->plugin->publics[i].code_offs == code_addr)
   188 			{
   189 				is_public = true;
   190 				break;
   191 			}
   192 		}
   193 	}
   194 
   195 	func = sp_InferFuncPrototype(dc, code_addr, is_public);
   196 	func->next = dc->funcs;
   197 	dc->funcs = func;
   198 
   199 	return func;
   200 }
   201 
   202 static void sp_CacheLocals(sp_decomp_t *dc, FunctionInfo *info)
   203 {
   204 	sp_file_t *plugin;
   205 	sp_fdbg_symbol_t *sym;
   206 
   207 	plugin = dc->plugin;
   208 
   209 	/* Search for all locals */
   210 	{
   211 		uint32_t i;
   212 		uint8_t *cursor;
   213 
   214 		cursor = (uint8_t *)plugin->debug.symbols;
   215 		for (i = 0; i < plugin->debug.syms_num; i++)
   216 		{
   217 			sym = (sp_fdbg_symbol_t *)cursor;
   218 
   219 			if ((sym->codestart >= info->code_addr && sym->codestart < info->code_end)
   220 				&& (sym->codeend <= info->code_end && sym->codeend >= info->code_addr)
   221 				&& sym->vclass == 1)
   222 			{
   223 				info->num_known_vars++;
   224 			}
   225 
   226 			cursor += sizeof(sp_fdbg_symbol_t);
   227 			if (sym->dimcount > 0)
   228 			{
   229 				cursor += sizeof(sp_fdbg_arraydim_t) * sym->dimcount;
   230 			}
   231 		}
   232 	}
   233 
   234 	/* Map all locals into place. */
   235 	if (info->num_known_vars)
   236 	{
   237 		uint32_t i, num;
   238 		uint8_t *cursor;
   239 
   240 		num = 0;
   241 		info->known_vars = new FuncVar[info->num_known_vars];
   242 		memset(info->known_vars, 0, sizeof(FuncVar) * info->num_known_vars);
   243 
   244 		cursor = (uint8_t *)plugin->debug.symbols;
   245 		for (i = 0; i < plugin->debug.syms_num; i++)
   246 		{
   247 			sym = (sp_fdbg_symbol_t *)cursor;
   248 
   249 			if (sym->ident == SP_SYM_VARIABLE
   250 				|| sym->ident == SP_SYM_REFARRAY
   251 				|| sym->ident == SP_SYM_REFERENCE
   252 				|| sym->ident == SP_SYM_ARRAY)
   253 			{
   254 				/* Detect all function variables. */
   255 				if ((sym->codestart >= info->code_addr && sym->codestart < info->code_end)
   256 					&& (sym->codeend <= info->code_end && sym->codeend >= info->code_addr)
   257 					&& sym->vclass == 1)
   258 				{
   259 					assert(num < info->num_known_vars);
   260 					info->known_vars[num].sym = sym;
   261 					info->known_vars[num].name = plugin->debug.stringbase + sym->name;
   262 					info->known_vars[num].tag = 
   263 						(sym->tagid == 0) ? NULL : Sp_FindTag(plugin, sym->tagid);
   264 					info->known_vars[num].dimcount = sym->dimcount;
   265 					info->known_vars[num].dims = 
   266 						(sym->dimcount == 0)
   267 						? NULL
   268 						: (sp_fdbg_arraydim_t *)(cursor + sizeof(sp_fdbg_symbol_t));
   269 					num++;
   270 				}
   271 			}
   272 
   273 			cursor += sizeof(sp_fdbg_symbol_t);
   274 			if (sym->dimcount > 0)
   275 			{
   276 				cursor += sizeof(sp_fdbg_arraydim_t) * sym->dimcount;
   277 			}
   278 		}
   279 
   280 		assert(num == info->num_known_vars);
   281 	}
   282 }
   283 
   284 static void sp_PrintFunctionPrototype(PrintBuffer *printer, sp_decomp_t *dc, FunctionInfo *func)
   285 {
   286 	FuncVar *var;
   287 	
   288 	if (func->is_public)
   289 	{
   290 		printer->Append("public ");
   291 	}
   292 	if (func->tag != NULL)
   293 	{
   294 		printer->Append("%s:", func->tag->name);
   295 	}
   296 	printer->Append("%s(", func->name);
   297 
   298 	for (unsigned int i = 0; i < func->num_known_args; i++)
   299 	{
   300 		var = &func->known_args[i];
   301 		if (var->sym == NULL)
   302 		{
   303 			printer->Append("unknown_arg_%d%s, ", i, i == func->num_known_args - 1 ? "" : ",");
   304 			continue;
   305 		}
   306 		if (var->sym->ident == SP_SYM_REFERENCE)
   307 		{
   308 			printer->Append("&");
   309 		}
   310 		if (var->tag != NULL)
   311 		{
   312 			printer->Append("%s:", var->tag->name);
   313 		}
   314 		printer->Append("%s", var->name);
   315 
   316 		if (var->sym->dimcount > 0)
   317 		{
   318 			sp_fdbg_arraydim_t *dims = 
   319 				(sp_fdbg_arraydim_t *)((char *)var->sym + sizeof(sp_fdbg_symbol_t));
   320 
   321 			for (uint16_t j = 0; j < var->sym->dimcount; j++)
   322 			{
   323 				if (dims[j].size == 0)
   324 				{
   325 					printer->Append("[]");
   326 				}
   327 				else
   328 				{
   329 					printer->Append("[%d]", dims[j].size);
   330 				}
   331 			}
   332 		}
   333 
   334 		if (i != func->num_known_args - 1)
   335 		{
   336 			printer->Append(", ");
   337 		}
   338 	}
   339 
   340 	printer->Append(")");
   341 }
   342 
   343 void sp_DebugExprTree(PrintBuffer *buffer, BaseNode *node, bool is_stmt=false)
   344 {
   345 	switch (node->op)
   346 	{
   347 	case _OP_DEFINE:
   348 		{
   349 			DefineNode *def = (DefineNode *)node;
   350 
   351 			buffer->Append("new %s = ", def->name);
   352 			sp_DebugExprTree(buffer, def->other, is_stmt);
   353 			break;
   354 		}
   355 	case OP_CALL:
   356 		{
   357 			CallNode *call = (CallNode *)node;
   358 
   359 			buffer->Append("%s(", call->func->name);
   360 			for (unsigned int i = 0; i < call->argc; i++)
   361 			{
   362 				sp_DebugExprTree(buffer, call->args[i], false);
   363 			}
   364 			buffer->Append(")");
   365 			break;
   366 		}
   367 	case _OP_USE:
   368 		{
   369 			UseNode *unode = (UseNode *)node;
   370 
   371 			buffer->Append("%s", unode->def->name);
   372 			break;
   373 		}
   374 	case _OP_VAR:
   375 		{
   376 			VarNode *var_node = (VarNode *)node;
   377 			buffer->Append("%s", var_node->var->name);
   378 			break;
   379 		}
   380 	case _OP_NEW:
   381 		{
   382 			DeclNode *d_node = (DeclNode *)node;
   383 
   384 			if (d_node->expr == NULL)
   385 			{
   386 				buffer->Append("decl ");
   387 				sp_DebugExprTree(buffer, d_node->var, true);
   388 			}
   389 			else
   390 			{
   391 				buffer->Append("new ");
   392 				sp_DebugExprTree(buffer, d_node->var, true);
   393 				buffer->Append(" = ");
   394 				sp_DebugExprTree(buffer, d_node->expr, true);
   395 			}
   396 
   397 			break;
   398 		}
   399 	case _OP_STMT:
   400 	case OP_RETN:
   401 		{
   402 			StmtNode *u_node = (StmtNode *)node;
   403 
   404 			while (u_node != NULL)
   405 			{
   406 				buffer->Append("\t");
   407 				if (u_node->op == OP_RETN)
   408 				{
   409 					buffer->Append("return ");
   410 				}
   411 				sp_DebugExprTree(buffer, u_node->node, true);
   412 				buffer->Append(";\n");
   413 				u_node = u_node->next;
   414 			}
   415 			break;
   416 		}
   417 	case _OP_CONST:
   418 		{
   419 			ConstNode *c_node = (ConstNode *)node;
   420 
   421 			buffer->Append("%d", c_node->val);
   422 
   423 			break;
   424 		}
   425 	case OP_ADD:
   426 	case OP_ADD_C:
   427 	case OP_SMUL:
   428 	case OP_SMUL_C:
   429 	case OP_SDIV:
   430 	case OP_SUB_ALT:
   431 	case _OP_STORE:
   432 	case _OP_MODULO:
   433 		{
   434 			BinOpNode *bin_node = (BinOpNode *)node;
   435 
   436 			if (!is_stmt)
   437 			{
   438 				buffer->Append("(");
   439 			}
   440 			sp_DebugExprTree(buffer, bin_node->left);
   441 
   442 			switch (node->op)
   443 			{
   444 			case OP_ADD:
   445 			case OP_ADD_C:
   446 				{
   447 					buffer->Append(" + ");
   448 					break;
   449 				}
   450 			case OP_SMUL:
   451 			case OP_SMUL_C:
   452 				{
   453 					buffer->Append(" * ");
   454 					break;
   455 				}
   456 			case _OP_STORE:
   457 				{
   458 					buffer->Append(" = ");
   459 					break;
   460 				}
   461 			case OP_SUB_ALT:
   462 				{
   463 					buffer->Append(" - ");
   464 					break;
   465 				}
   466 			case OP_SDIV:
   467 				{
   468 					buffer->Append(" / ");
   469 					break;
   470 				}
   471 			case _OP_MODULO:
   472 				{
   473 					buffer->Append(" % ");
   474 					break;
   475 				}
   476 			}
   477 
   478 			sp_DebugExprTree(buffer, bin_node->right, node->op == _OP_STORE);
   479 			if (!is_stmt)
   480 			{
   481 				buffer->Append(")");
   482 			}
   483 
   484 			break;
   485 		}
   486 	}
   487 }
   488 
   489 void sp_DebugPrint(FunctionInfo *info, sp_decomp_t *dc, BaseNode *node)
   490 {
   491 	PrintBuffer buffer;
   492 
   493 	sp_PrintFunctionPrototype(&buffer, dc, info);
   494 	buffer.Append("\n{\n");
   495 	sp_DebugExprTree(&buffer, node, true);
   496 	buffer.Append("}\n");
   497 	buffer.Dump(stdout);
   498 }
   499 
   500 #define PCODE_VAL(pcode, offs)			*(cell_t *)((char *)(pcode)+(offs))
   501 #define PCODE_PARAM(pcode, offs, num)	*(cell_t *)((char *)(pcode)+(offs)+((num)*sizeof(cell_t)))
   502 
   503 FuncVar *sp_FindGraphVar(FunctionInfo *func, ucell_t cip, cell_t sp, cell_t stack)
   504 {
   505 	if (stack >= 0xC)
   506 	{
   507 		if ((stack & 0x3) != 0)
   508 		{
   509 			return NULL;
   510 		}
   511 		stack -= 0xC;
   512 		stack >>= 2;
   513 		if (stack >= SP_MAX_EXEC_PARAMS)
   514 		{
   515 			return NULL;
   516 		}
   517 		if (func->known_args[stack].sym == NULL)
   518 		{
   519 			return NULL;
   520 		}
   521 		return &func->known_args[stack];
   522 	}
   523 	else if (stack < 0)
   524 	{
   525 		FuncVar *var;
   526 
   527 		if (stack < sp)
   528 		{
   529 			return NULL;
   530 		}
   531 
   532 		for (unsigned int i = 0; i < func->num_known_vars; i++)
   533 		{
   534 			var = &func->known_vars[i];
   535 
   536 			if (cip >= var->sym->codestart
   537 				&& cip <= var->sym->codeend
   538 				&& stack == var->sym->addr)
   539 			{
   540 				return var;
   541 			}
   542 		}
   543 
   544 		return NULL;
   545 	}
   546 	else
   547 	{
   548 		return NULL;
   549 	}
   550 }
   551 
   552 #define CHECK_VALUE(v)							\
   553 	assert(v != NULL);							\
   554 	if (v == NULL) {							\
   555 		err = SP_ERROR_INVALID_INSTRUCTION;		\
   556 		goto return_error;						\
   557 	}
   558 
   559 void *operator new(size_t size, ControlFlowGraph *graph)
   560 {
   561 	return malloc(size);
   562 }
   563 
   564 void *operator new[](size_t size, ControlFlowGraph *graph)
   565 {
   566 	return malloc(size);
   567 }
   568 
   569 void operator delete(void *mem, ControlFlowGraph *graph)
   570 {
   571 	free(mem);
   572 }
   573 
   574 void operator delete[](void *mem, ControlFlowGraph *graph)
   575 {
   576 	free(mem);
   577 }
   578 
   579 #define MAX_STACK_ENTRIES		256
   580 
   581 struct StackEntry
   582 {
   583 	StackEntry()
   584 	{
   585 	}
   586 	StackEntry(cell_t d, BaseNode *e) : depth(d), expr(e)
   587 	{
   588 	}
   589 	cell_t depth;
   590 	BaseNode *expr;
   591 };
   592 
   593 int sp_AnalyzeGraph(sp_decomp_t *dc, ControlFlowGraph *graph)
   594 {
   595 	int err;
   596 	cell_t sp;
   597 	Block *block;
   598 	cell_t *pcode;
   599 	cell_t cip, cip_end;
   600 	StmtNode *root, *rtemp;
   601 	StmtNode *root_tail;
   602 	BaseNode *pri, *alt;
   603 	FunctionInfo *func, *tfunc;
   604 	cell_t p1, p2, op;
   605 	FuncVar *v1, *v2;
   606 	unsigned int callnumber = 0;
   607 	unsigned int stack_entries = 0;
   608 	StackEntry eval_stack[MAX_STACK_ENTRIES];
   609 
   610 	/* Init everything.
   611 	 * Stack pointer starts off at 0.
   612 	 */
   613 	sp = 0;
   614 	pri = NULL;
   615 	alt = NULL;
   616 	root = NULL;
   617 	func = graph->func;
   618 	block = graph->entry;
   619 	pcode = (cell_t *)dc->plugin->pcode;
   620 
   621 	cip = block->ip_start;
   622 	cip_end = block->ip_end;
   623 
   624 	root_tail = root = new (graph) StmtNode(_OP_STMT, NULL, NULL);
   625 
   626 	while (cip < cip_end)
   627 	{
   628 		op = PCODE_VAL(pcode, cip);
   629 
   630 		switch (op)
   631 		{
   632 		case OP_PROC:
   633 		case OP_BREAK:
   634 			{
   635 				break;
   636 			}
   637 		case OP_CALL:
   638 		case OP_SYSREQ_N:
   639 			{
   640 				p1 = PCODE_PARAM(pcode, cip, 1);
   641 				if (op == OP_CALL)
   642 				{
   643 					tfunc = sp_GetFuncPrototype(dc, p1, false);
   644 				}
   645 				else if (op == OP_SYSREQ_N)
   646 				{
   647 					assert(dc->natives);
   648 					assert(uint32_t(p1) < dc->plugin->num_natives);
   649 					tfunc = &dc->natives[p1];
   650 				}
   651 				CHECK_VALUE(tfunc);
   652 
   653 				/* Sanity checks, :TODO: runtime checks later. */
   654 				assert(stack_entries >= 1);
   655 
   656 				if (op == OP_SYSREQ_N)
   657 				{
   658 					p2 = PCODE_PARAM(pcode, cip, 2);
   659 				}
   660 				else
   661 				{
   662 					/* Try to read the value off the stack. */
   663 					ConstNode *cnode;
   664 					cnode = (ConstNode *)eval_stack[stack_entries-1].expr;
   665 					/* Sanity checks, :TODO: runtime checks later. */
   666 					assert(cnode->op == _OP_CONST);
   667 					assert(cnode->val >= 0);
   668 					assert(uint32_t(cnode->val) == tfunc->num_known_args);
   669 					p2 = cnode->val;
   670 					stack_entries--;
   671 				}
   672 
   673 				assert(uint32_t(p2) <= stack_entries);
   674 				
   675 				/* Build arg SSA */
   676 				BaseNode **nodes = new (graph) BaseNode *[p2];
   677 				for (cell_t argno = 0; argno < p2; argno++, stack_entries--)
   678 				{
   679 					nodes[argno] = eval_stack[stack_entries-1].expr;
   680 				}
   681 
   682 				/* Get rid of any args we pushed. */
   683 				sp += p2 * sizeof(cell_t);
   684 				if (op == OP_CALL)
   685 				{
   686 					sp += sizeof(cell_t);
   687 				}
   688 				assert(sp <= 0);
   689 
   690 				/* Build function call SSA */
   691 				pri = new (graph) CallNode(tfunc, nodes, p2);
   692 				pri = new (graph) DefineNode(pri, "call%03x", ++callnumber);
   693 				rtemp = new (graph) StmtNode(_OP_STMT, pri, NULL);
   694 				root_tail->next = rtemp;
   695 				root_tail = rtemp;
   696 				pri = new (graph) UseNode((DefineNode *)pri);
   697 				
   698 				break;
   699 			}
   700 		case OP_CONST_PRI:
   701 			{
   702 				p1 = PCODE_PARAM(pcode, cip, 1);
   703 				pri = new (graph) ConstNode(p1);
   704 				break;
   705 			}
   706 		case OP_PUSH_C:
   707 		case OP_PUSH2_C:
   708 		case OP_PUSH3_C:
   709 		case OP_PUSH5_C:
   710 			{
   711 				for (int N = 1; N <= dc->opdef[op].params; N++)
   712 				{
   713 					p1 = PCODE_PARAM(pcode, cip, N);
   714 
   715 					/* Adjust stack pointer. */
   716 					sp -= sizeof(cell_t);
   717 
   718 					if ((v1 = sp_FindGraphVar(func, cip, sp, sp)) == NULL)
   719 					{
   720 						/* Add a new stack entry. */
   721 						assert(stack_entries < MAX_STACK_ENTRIES);
   722 						eval_stack[stack_entries++] = StackEntry(sp, new ConstNode(p1));
   723 					}
   724 					else
   725 					{
   726 						assert(v1->new_stmt == NULL);
   727 						if (v1->new_stmt == NULL)
   728 						{
   729 							v1->new_stmt = new (graph) DeclNode(
   730 								new (graph) VarNode(v1),
   731 								new (graph) ConstNode(p1));
   732 							rtemp = new (graph) StmtNode(
   733 								_OP_STMT,
   734 								v1->new_stmt,
   735 								NULL);
   736 							root_tail->next = rtemp;
   737 							root_tail = rtemp;
   738 						}
   739 					}
   740 				}
   741 				break;
   742 			}
   743 		case OP_PUSH_S:
   744 			{
   745 				p1 = PCODE_PARAM(pcode, cip, 1);
   746 				v1 = sp_FindGraphVar(func, cip, sp, p1);
   747 				CHECK_VALUE(v1);
   748 
   749 				/* Adjust stack pointer. */
   750 				sp -= sizeof(cell_t);
   751 
   752 				/* Right now, don't allow aliasing or overflows. */
   753 				assert(sp_FindGraphVar(func, cip, sp, sp) == NULL);
   754 				assert(stack_entries < MAX_STACK_ENTRIES);
   755 
   756 				/* Add a new stack entry. */
   757 				eval_stack[stack_entries++] = StackEntry(sp, new (graph) VarNode(v1));
   758 				break;
   759 			}
   760 		case OP_PUSH_PRI:
   761 			{
   762 				CHECK_VALUE(pri);
   763 
   764 				/* Adjust stack pointer. */
   765 				sp -= sizeof(cell_t);
   766 				
   767 				/* Right now, don't allow aliasing or overflows. */
   768 				assert(sp_FindGraphVar(func, cip, sp, sp) == NULL);
   769 				assert(stack_entries < MAX_STACK_ENTRIES);
   770 
   771 				/* Add a new stack entry. */
   772 				eval_stack[stack_entries++] = StackEntry(sp, pri);
   773 				break;
   774 			}
   775 		case OP_POP_ALT:
   776 			{
   777 				assert(stack_entries > 0);
   778 				assert(eval_stack[stack_entries - 1].depth == sp);
   779 
   780 				alt = eval_stack[--stack_entries].expr;
   781 				sp += sizeof(cell_t);
   782 				assert(sp <= 0);
   783 				break;
   784 			}
   785 		case OP_STACK:
   786 			{
   787 				p1 = PCODE_PARAM(pcode, cip, 1);
   788 				sp += p1;
   789 				assert(sp <= 0);
   790 				if (p1 < 0)
   791 				{
   792 					/* Find if we should track a new variable declaration. */
   793 					v1 = sp_FindGraphVar(func, cip, sp, sp);
   794 					CHECK_VALUE(v1);
   795 					assert(v1->new_stmt == NULL);
   796 					if (v1->new_stmt == NULL)
   797 					{
   798 						v1->new_stmt = new (graph) DeclNode(
   799 							new (graph) VarNode(v1),
   800 							NULL);
   801 						rtemp = new (graph) StmtNode(
   802 							_OP_STMT,
   803 							v1->new_stmt,
   804 							NULL);
   805 						root_tail->next = rtemp;
   806 						root_tail = rtemp;
   807 					}
   808 					assert(abs(p1) >> 2 == 1);
   809 				}
   810 				else
   811 				{
   812 					/* Erase anything left over on the evaluation stack. */
   813 					while (stack_entries > 0
   814 						   && eval_stack[stack_entries - 1].depth < sp)
   815 					{
   816 						assert(0);
   817 						stack_entries--;
   818 					}
   819 				}
   820 				break;
   821 			}
   822 		case OP_ZERO_PRI:
   823 			{
   824 				pri = new (graph) ConstNode(0);
   825 				break;
   826 			}
   827 		case OP_MOVE_ALT:
   828 			{
   829 				CHECK_VALUE(pri);
   830 				alt = pri;
   831 				break;
   832 			}
   833 		case OP_LOAD_S_PRI:
   834 			{
   835 				p1 = PCODE_PARAM(pcode, cip, 1);
   836 				v1 = sp_FindGraphVar(func, cip, sp, p1);
   837 				CHECK_VALUE(v1);
   838 				pri = new (graph) VarNode(v1);
   839 				break;
   840 			}
   841 		case OP_LOAD_S_ALT:
   842 			{
   843 				p1 = PCODE_PARAM(pcode, cip, 1);
   844 				v1 = sp_FindGraphVar(func, cip, sp, p1);
   845 				CHECK_VALUE(v1);
   846 				alt = new (graph) VarNode(v1);
   847 				break;
   848 			}
   849 		case OP_STOR_S_PRI:
   850 			{
   851 				p1 = PCODE_PARAM(pcode, cip, 1);
   852 				v1 = sp_FindGraphVar(func, cip, sp, p1);
   853 				CHECK_VALUE(v1);
   854 				CHECK_VALUE(pri);
   855 				rtemp = new (graph) StmtNode(
   856 					_OP_STMT,
   857 					new (graph) BinOpNode(_OP_STORE, new (graph) VarNode(v1), pri),
   858 					NULL);
   859 				root_tail->next = rtemp;
   860 				root_tail = rtemp;
   861 
   862 				/** 
   863 				 * We create a varnode to simulate a load here.
   864 				 * This helps accidental duplication of the expression tree.
   865 				 */
   866 				pri = new (graph) VarNode(v1);	
   867 				break;
   868 			}
   869 		case OP_LOAD_S_BOTH:
   870 			{
   871 				p1 = PCODE_PARAM(pcode, cip, 1);
   872 				p2 = PCODE_PARAM(pcode, cip, 2);
   873 				v1 = sp_FindGraphVar(func, cip, sp, p1);
   874 				v2 = sp_FindGraphVar(func, cip, sp, p2);
   875 				CHECK_VALUE(v1);
   876 				CHECK_VALUE(v2);
   877 				pri = new (graph) VarNode(v1);
   878 				alt = new (graph) VarNode(v2);
   879 				break;
   880 			}
   881 		case OP_ADD:
   882 		case OP_SMUL:
   883 			{
   884 				CHECK_VALUE(pri);
   885 				CHECK_VALUE(alt);
   886 				pri = new (graph) BinOpNode(op, pri, alt);
   887 				break;
   888 			}
   889 		case OP_SUB_ALT:
   890 			{
   891 				CHECK_VALUE(pri);
   892 				CHECK_VALUE(alt);
   893 				pri = new (graph) BinOpNode(op, alt, pri);
   894 				break;
   895 			}
   896 		case OP_SDIV:
   897 			{
   898 				CHECK_VALUE(pri);
   899 				CHECK_VALUE(alt);
   900 				pri = new (graph) BinOpNode(OP_SDIV, pri, alt);
   901 				alt = new (graph) BinOpNode(_OP_MODULO, pri, alt);
   902 				break;
   903 			}
   904 		case OP_SDIV_ALT:
   905 			{
   906 				CHECK_VALUE(pri);
   907 				CHECK_VALUE(alt);
   908 				pri = new (graph) BinOpNode(OP_SDIV, alt, pri);
   909 				alt = new (graph) BinOpNode(_OP_MODULO, alt, pri);
   910 				break;
   911 			}
   912 		case OP_ADD_C:
   913 		case OP_SMUL_C:
   914 			{
   915 				p1 = PCODE_PARAM(pcode, cip, 1);
   916 				CHECK_VALUE(pri);
   917 				pri = new (graph) BinOpNode(op, pri, new (graph) ConstNode(p1));
   918 				break;
   919 			}
   920 		case OP_RETN:
   921 			{
   922 				CHECK_VALUE(pri);
   923 				rtemp = new (graph) StmtNode(op, pri, NULL);
   924 				root_tail->next = rtemp;
   925 				root_tail = rtemp;
   926 				break;
   927 			}
   928 		default:
   929 			{
   930 				assert(0);
   931 				break;
   932 			}
   933 		}
   934 
   935 		NEXT_OP(cip, op);
   936 	}
   937 
   938 	sp_DebugPrint(graph->func, dc, root->next);
   939 
   940 	return SP_ERROR_NONE;
   941 
   942 return_error:
   943 	return err;
   944 }
   945 
   946 #undef CHECK_FUNCVAR
   947 
   948 inline Block *sp_BlockFromMap(sp_decomp_t *dc, ControlFlowGraph *graph, cell_t cip)
   949 {
   950 	cell_t val;
   951 
   952 	assert(PCODE_VAL(dc->pcode_map, cip) & PCM_HAS_BLOCK);
   953 
   954 	val = PCODE_VAL(dc->pcode_map, cip);
   955 	val >>= PCM_NUM_BITS;
   956 
   957 	assert(val >= 0 && val < (cell_t)graph->used_blocks);
   958 
   959 	return &graph->blocks[val];
   960 }
   961 
   962 void sp_InsertBlock(sp_decomp_t *dc, unsigned int index, cell_t cip)
   963 {
   964 	cell_t val;
   965 
   966 	val = PCODE_VAL(dc->pcode_map, cip);
   967 
   968 	assert(!(val & PCM_HAS_BLOCK));
   969 	assert(index < 0x20000000);
   970 
   971 	val |= PCM_HAS_BLOCK;
   972 	val |= index << 3;
   973 
   974 	PCODE_VAL(dc->pcode_map, cip) = val;
   975 }
   976 
   977 static Block *sp_BuildBlocks(sp_decomp_t *dc, ControlFlowGraph *graph, cell_t cip)
   978 {
   979 	cell_t op;
   980 	bool is_branch;
   981 	cell_t target;
   982 	Block *block;
   983 	Edge *edge_tail;
   984 	Block *outgoing;
   985 	cell_t cip_end;
   986 	cell_t *pcode;
   987 
   988 	target = 0;
   989 	cip_end = graph->func->code_end;
   990 	pcode = (cell_t *)dc->plugin->pcode;
   991 
   992 	if (PCODE_VAL(dc->pcode_map, cip) & PCM_HAS_BLOCK)
   993 	{
   994 		return sp_BlockFromMap(dc, graph, cip);
   995 	}
   996 
   997 	/* We can't add a new block if we hit our limit. */
   998 	assert(graph->used_blocks < graph->max_blocks);
   999 	if (graph->used_blocks >= graph->max_blocks)
  1000 	{
  1001 		return NULL;
  1002 	}
  1003 
  1004 	edge_tail = NULL;
  1005 
  1006 	/* Reserve a new block. */
  1007 	block = &graph->blocks[graph->used_blocks++];
  1008 	block->ip_start = cip;
  1009 	
  1010 	/* Enter us into the map. */
  1011 	sp_InsertBlock(dc, graph->used_blocks - 1, cip);
  1012 
  1013 	/* Walk the code. */
  1014 	while (cip < cip_end)
  1015 	{
  1016 		/* Check whether this is the start of a new block. */
  1017 		if (cip != block->ip_start
  1018 			&& (PCODE_VAL(dc->pcode_map, cip) & PCM_BRANCH_TARGET))
  1019 		{
  1020 			block->ip_end = cip;
  1021 			if ((outgoing = sp_BuildBlocks(dc, graph, cip)) == NULL)
  1022 			{
  1023 				return NULL;
  1024 			}
  1025 			/* :TODO: add edge */
  1026 			return block;
  1027 		}
  1028 
  1029 		is_branch = false;
  1030 		op = PCODE_VAL(pcode, cip);
  1031 		NEXT_OP(cip, op);
  1032 
  1033 		if (is_branch)
  1034 		{
  1035 			/* Check that branch offsets go to valid instructions. */
  1036 			if (!(PCODE_VAL(dc->pcode_map, target) & PCM_OPCODE))
  1037 			{
  1038 				graph->err = SP_ERROR_INVALID_INSTRUCTION;
  1039 				return NULL;
  1040 			}
  1041 
  1042 			/* Get our target block. */
  1043 			if ((outgoing = sp_BuildBlocks(dc, graph, target)) == NULL)
  1044 			{
  1045 				return NULL;
  1046 			}
  1047 			/* :TODO: add edge */
  1048 		}
  1049 		else if (op == OP_RETN /* :TODO: || op == OP_RET*/)
  1050 		{
  1051 			block->ip_end = cip;
  1052 			return block;
  1053 		}
  1054 	}
  1055 
  1056 	graph->err = SP_ERROR_INVALID_INSTRUCTION;
  1057 
  1058 	return NULL;
  1059 }
  1060 
  1061 
  1062 int Sp_DecompFunction(sp_decomp_t *dc, uint32_t code_addr, bool is_public)
  1063 {
  1064 	int err;
  1065 	cell_t op;
  1066 	ucell_t cip;
  1067 	cell_t *pcode;
  1068 	ucell_t cip_end;
  1069 	sp_file_t *plugin;
  1070 	FunctionInfo *func;
  1071 	ControlFlowGraph graph;
  1072 	
  1073 	func = NULL;
  1074 	plugin = dc->plugin;
  1075 	memset(&graph, 0, sizeof(graph));
  1076 
  1077 	if (code_addr >= plugin->pcode_size)
  1078 	{
  1079 		err = SP_ERROR_INVALID_INSTRUCTION;
  1080 		goto return_error;
  1081 	}
  1082 
  1083 	pcode = (cell_t *)plugin->pcode;
  1084 
  1085 	if (PCODE_VAL(pcode, code_addr) != OP_PROC)
  1086 	{
  1087 		err = SP_ERROR_INVALID_INSTRUCTION;
  1088 		goto return_error;
  1089 	}
  1090 
  1091 	cip = code_addr + sizeof(cell_t);
  1092 
  1093 	/* See if we have an existing function stored. */
  1094 	func = sp_GetFuncPrototype(dc, code_addr, true, is_public);
  1095 
  1096 	while (cip < plugin->pcode_size)
  1097 	{
  1098 		op = PCODE_VAL(pcode, cip);
  1099 		if (op >= OP_TOTAL || op < 0)
  1100 		{
  1101 			err = SP_ERROR_INVALID_INSTRUCTION;
  1102 		}
  1103 		if (dc->opdef[op].name == NULL)
  1104 		{
  1105 			err = SP_ERROR_INVALID_INSTRUCTION;
  1106 		}
  1107 		if (op == OP_PROC)
  1108 		{
  1109 			break;
  1110 		}
  1111 		NEXT_OP(cip, op);
  1112 	}
  1113 	cip_end = cip;
  1114 
  1115 	func->code_end = cip_end;
  1116 
  1117 	/* Now we can cache all local vars. */
  1118 	sp_CacheLocals(dc, func);
  1119 
  1120 	/** 
  1121 	 * Make the entry point as the first block.
  1122 	 * It needs to be flagged as well so it doesn't get double counted.
  1123 	 */
  1124 	memset(&PCODE_VAL(dc->pcode_map, code_addr), 0, cip_end - code_addr);
  1125 		   
  1126 	graph.max_blocks = 1;
  1127 	graph.func = func;
  1128 	PCODE_VAL(dc->pcode_map, code_addr) |= PCM_BRANCH_TARGET;
  1129 
  1130 	/* Walk the code. */
  1131 	{
  1132 		cell_t target;
  1133 		bool is_branch;
  1134 
  1135 		target = 0;
  1136 		cip = code_addr;
  1137 		while (cip < cip_end)
  1138 		{
  1139 			/* Get opcode */
  1140 			op = PCODE_VAL(pcode, cip);
  1141 			/* Mark as not a branch */
  1142 			is_branch = false;
  1143 			/* Make sure we know this is a valid target */
  1144 			PCODE_VAL(dc->pcode_map, cip) |= PCM_OPCODE;
  1145 
  1146 			if (is_branch)
  1147 			{
  1148 				/**
  1149 				 * Keep track of where branches are and how many blocks we need.
  1150 				 */
  1151 				if (!(PCODE_VAL(dc->pcode_map, target) & PCM_BRANCH_TARGET))
  1152 				{
  1153 					PCODE_VAL(dc->pcode_map, target) |= PCM_BRANCH_TARGET;
  1154 					graph.max_blocks++;
  1155 
  1156 					/**
  1157 					 * If we're creating a new block, estimate that we need to create a new edge 
  1158 					 * as well.
  1159 					 */
  1160 					graph.max_edges++;
  1161 				}
  1162 
  1163                 /**
  1164                  * In this algorithm, jumps do not terminate a block unless they are unconditional.
  1165                  * This reduces the number of blocks and edges.
  1166                  *
  1167                  * A property of this is that jumps are edges, so the number of edges is identical 
  1168 				 * to the number of jumps.
  1169                  */
  1170 				graph.max_edges++;
  1171 			}
  1172 
  1173 			NEXT_OP(cip, op);
  1174 		}
  1175 	}
  1176 
  1177 	/* Initialize memory needed for the graph. */
  1178 	graph.blocks = new Block[graph.max_blocks];
  1179 	memset(graph.blocks, 0, sizeof(Block) * graph.max_blocks);
  1180 	
  1181 	if (graph.max_edges != 0)
  1182 	{
  1183 		graph.edges = new Edge[graph.max_edges];
  1184 		memset(graph.edges, 0, sizeof(Edge) * graph.max_edges);
  1185 	}
  1186 
  1187 	if ((graph.entry = sp_BuildBlocks(dc, &graph, code_addr)) == NULL)
  1188 	{
  1189 		if ((err = graph.err) == SP_ERROR_NONE)
  1190 		{
  1191 			err = SP_ERROR_ABORTED;
  1192 		}
  1193 		goto return_error;
  1194 	}
  1195 
  1196 	if ((err = sp_AnalyzeGraph(dc, &graph)) != SP_ERROR_NONE)
  1197 	{
  1198 		goto return_error;
  1199 	}
  1200 
  1201 	return SP_ERROR_NONE;
  1202 
  1203 return_error:
  1204 	return err;
  1205 }