github.com/goccy/go-jit@v0.0.0-20200514131505-ff78d45cf6af/internal/ccall/jit-block.c (about)

     1  /*
     2   * jit-block.c - Functions for manipulating blocks.
     3   *
     4   * Copyright (C) 2004  Southern Storm Software, Pty Ltd.
     5   *
     6   * This file is part of the libjit library.
     7   *
     8   * The libjit library is free software: you can redistribute it and/or
     9   * modify it under the terms of the GNU Lesser General Public License
    10   * as published by the Free Software Foundation, either version 2.1 of
    11   * the License, or (at your option) any later version.
    12   *
    13   * The libjit library is distributed in the hope that it will be useful,
    14   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    15   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    16   * Lesser General Public License for more details.
    17   *
    18   * You should have received a copy of the GNU Lesser General Public
    19   * License along with the libjit library.  If not, see
    20   * <http://www.gnu.org/licenses/>.
    21   */
    22  
    23  #include "jit-internal.h"
    24  #include <stdlib.h>
    25  
    26  /*@
    27  
    28  @cindex jit-block.h
    29  
    30  @*/
    31  
    32  /* helper data structure for CFG DFS traversal */
    33  typedef struct _jit_block_stack_entry
    34  {
    35  	jit_block_t block;
    36  	int index;
    37  } _jit_block_stack_entry_t;
    38  
    39  
    40  static void
    41  create_edge(jit_function_t func, jit_block_t src, jit_block_t dst, int flags, int create)
    42  {
    43  	_jit_edge_t edge;
    44  
    45  	/* Create edge if required */
    46  	if(create)
    47  	{
    48  		/* Allocate memory for it */
    49  		edge = jit_memory_pool_alloc(&func->builder->edge_pool, struct _jit_edge);
    50  		if(!edge)
    51  		{
    52  			jit_exception_builtin(JIT_RESULT_OUT_OF_MEMORY);
    53  		}
    54  
    55  		/* Initialize edge fields */
    56  		edge->src = src;
    57  		edge->dst = dst;
    58  		edge->flags = flags;
    59  
    60  		/* Store edge pointers in source and destination nodes */
    61  		src->succs[src->num_succs] = edge;
    62  		dst->preds[dst->num_preds] = edge;
    63  	}
    64  
    65  	/* Count it */
    66  	++(src->num_succs);
    67  	++(dst->num_preds);
    68  }
    69  
    70  static void
    71  build_edges(jit_function_t func, int create)
    72  {
    73  	jit_block_t src, dst;
    74  	jit_insn_t insn;
    75  	int opcode, flags;
    76  	jit_label_t *labels;
    77  	int index, num_labels;
    78  
    79  	/* TODO: Handle catch, finally, filter blocks. */
    80  
    81  	for(src = func->builder->entry_block; src != func->builder->exit_block; src = src->next)
    82  	{
    83  		/* Check the last instruction of the block */
    84  		insn = _jit_block_get_last(src);
    85  		opcode = insn ? insn->opcode : JIT_OP_NOP;
    86  		if(opcode >= JIT_OP_RETURN && opcode <= JIT_OP_RETURN_SMALL_STRUCT)
    87  		{
    88  			flags = _JIT_EDGE_RETURN;
    89  			dst = func->builder->exit_block;
    90  		}
    91  		else if(opcode == JIT_OP_BR)
    92  		{
    93  			flags = _JIT_EDGE_BRANCH;
    94  			dst = jit_block_from_label(func, (jit_label_t) insn->dest);
    95  			if(!dst)
    96  			{
    97  				/* Bail out on undefined label */
    98  				jit_exception_builtin(JIT_RESULT_UNDEFINED_LABEL);
    99  			}
   100  		}
   101  		else if(opcode > JIT_OP_BR && opcode <= JIT_OP_BR_NFGE_INV)
   102  		{
   103  			flags = _JIT_EDGE_BRANCH;
   104  			dst = jit_block_from_label(func, (jit_label_t) insn->dest);
   105  			if(!dst)
   106  			{
   107  				/* Bail out on undefined label */
   108  				jit_exception_builtin(JIT_RESULT_UNDEFINED_LABEL);
   109  			}
   110  		}
   111  		else if(opcode == JIT_OP_THROW || opcode == JIT_OP_RETHROW)
   112  		{
   113  			flags = _JIT_EDGE_EXCEPT;
   114  			dst = jit_block_from_label(func, func->builder->catcher_label);
   115  			if(!dst)
   116  			{
   117  				dst = func->builder->exit_block;
   118  			}
   119  		}
   120  		else if(opcode == JIT_OP_CALL_FINALLY || opcode == JIT_OP_CALL_FILTER)
   121  		{
   122  			flags = _JIT_EDGE_EXCEPT;
   123  			dst = jit_block_from_label(func, (jit_label_t) insn->dest);
   124  			if(!dst)
   125  			{
   126  				/* Bail out on undefined label */
   127  				jit_exception_builtin(JIT_RESULT_UNDEFINED_LABEL);
   128  			}
   129  		}
   130  		else if(opcode >= JIT_OP_CALL && opcode <= JIT_OP_CALL_EXTERNAL_TAIL)
   131  		{
   132  			flags = _JIT_EDGE_EXCEPT;
   133  			dst = jit_block_from_label(func, func->builder->catcher_label);
   134  			if(!dst)
   135  			{
   136  				dst = func->builder->exit_block;
   137  			}
   138  		}
   139  		else if(opcode == JIT_OP_JUMP_TABLE)
   140  		{
   141  			labels = (jit_label_t *) insn->value1->address;
   142  			num_labels = (int) insn->value2->address;
   143  			for(index = 0; index < num_labels; index++)
   144  			{
   145  				dst = jit_block_from_label(func, labels[index]);
   146  				if(!dst)
   147  				{
   148  					/* Bail out on undefined label */
   149  					jit_exception_builtin(JIT_RESULT_UNDEFINED_LABEL);
   150  				}
   151  				create_edge(func, src, dst, _JIT_EDGE_BRANCH, create);
   152  			}
   153  			dst = 0;
   154  		}
   155  		else
   156  		{
   157  			dst = 0;
   158  		}
   159  
   160  		/* create a branch or exception edge if appropriate */
   161  		if(dst)
   162  		{
   163  			create_edge(func, src, dst, flags, create);
   164  		}
   165  		/* create a fall-through edge if appropriate */
   166  		if(!src->ends_in_dead)
   167  		{
   168  			create_edge(func, src, src->next, _JIT_EDGE_FALLTHRU, create);
   169  		}
   170  	}
   171  }
   172  
   173  static void
   174  alloc_edges(jit_function_t func)
   175  {
   176  	jit_block_t block;
   177  
   178  	for(block = func->builder->entry_block; block; block = block->next)
   179  	{
   180  		/* Allocate edges to successor nodes */
   181  		if(block->num_succs == 0)
   182  		{
   183  			block->succs = 0;
   184  		}
   185  		else
   186  		{
   187  			block->succs = jit_calloc(block->num_succs, sizeof(_jit_edge_t));
   188  			if(!block->succs)
   189  			{
   190  				jit_exception_builtin(JIT_RESULT_OUT_OF_MEMORY);
   191  			}
   192  			/* Reset edge count for the next build pass */
   193  			block->num_succs = 0;
   194  		}
   195  
   196  		/* Allocate edges to predecessor nodes */
   197  		if(block->num_preds == 0)
   198  		{
   199  			block->preds = 0;
   200  		}
   201  		else
   202  		{
   203  			block->preds = jit_calloc(block->num_preds, sizeof(_jit_edge_t));
   204  			if(!block->preds)
   205  			{
   206  				jit_exception_builtin(JIT_RESULT_OUT_OF_MEMORY);
   207  			}
   208  			/* Reset edge count for the next build pass */
   209  			block->num_preds = 0;
   210  		}
   211  	}
   212  }
   213  
   214  static void
   215  detach_edge_src(_jit_edge_t edge)
   216  {
   217  	jit_block_t block;
   218  	int index;
   219  
   220  	block = edge->src;
   221  	for(index = 0; index < block->num_succs; index++)
   222  	{
   223  		if(block->succs[index] == edge)
   224  		{
   225  			for(block->num_succs--; index < block->num_succs; index++)
   226  			{
   227  				block->succs[index] = block->succs[index + 1];
   228  			}
   229  			block->succs = jit_realloc(block->succs, block->num_succs * sizeof(_jit_edge_t));
   230  			return;
   231  		}
   232  	}
   233  }
   234  
   235  static void
   236  detach_edge_dst(_jit_edge_t edge)
   237  {
   238  	jit_block_t block;
   239  	int index;
   240  
   241  	block = edge->dst;
   242  	for(index = 0; index < block->num_preds; index++)
   243  	{
   244  		if(block->preds[index] == edge)
   245  		{
   246  			for(block->num_preds--; index < block->num_preds; index++)
   247  			{
   248  				block->preds[index] = block->preds[index + 1];
   249  			}
   250  			block->preds = jit_realloc(block->preds,
   251  						   block->num_preds * sizeof(_jit_edge_t));
   252  			return;
   253  		}
   254  	}
   255  }
   256  
   257  static void
   258  attach_edge_dst(_jit_edge_t edge, jit_block_t block)
   259  {
   260  	_jit_edge_t *preds;
   261  
   262  	preds = jit_realloc(block->preds, (block->num_preds + 1) * sizeof(_jit_edge_t));
   263  	if(!preds)
   264  	{
   265  		jit_exception_builtin(JIT_RESULT_OUT_OF_MEMORY);
   266  	}
   267  
   268  	preds[block->num_preds++] = edge;
   269  	block->preds = preds;
   270  	edge->dst = block;
   271  }
   272  
   273  /* Delete edge along with references to it */
   274  static void
   275  delete_edge(jit_function_t func, _jit_edge_t edge)
   276  {
   277  	detach_edge_src(edge);
   278  	detach_edge_dst(edge);
   279  	jit_memory_pool_dealloc(&func->builder->edge_pool, edge);
   280  }
   281  
   282  /* Block may not be deleted right when it was found useless from
   283     the control flow perspective as it might be referenced from
   284     elsewhere, for instance, from some jit_value_t */
   285  static void
   286  delete_block(jit_block_t block)
   287  {
   288  	jit_free(block->succs);
   289  	block->succs = 0;
   290  	jit_free(block->preds);
   291  	block->preds = 0;
   292  	jit_free(block->insns);
   293  	block->insns = 0;
   294  
   295  	block->next = block->func->builder->deleted_blocks;
   296  	block->func->builder->deleted_blocks = block;
   297  }
   298  
   299  /* The block is empty if it contains nothing apart from an unconditional branch */
   300  static int
   301  is_empty_block(jit_block_t block)
   302  {
   303  	int index, opcode;
   304  
   305  	index = block->num_insns;
   306  	if(index == 0)
   307  	{
   308  		return 1;
   309  	}
   310  
   311  	opcode = block->insns[--index].opcode;
   312  	if(opcode != JIT_OP_NOP && opcode != JIT_OP_MARK_OFFSET && opcode != JIT_OP_BR)
   313  	{
   314  		return 0;
   315  	}
   316  
   317  	while(index > 0)
   318  	{
   319  		opcode = block->insns[--index].opcode;
   320  		if(opcode != JIT_OP_NOP && opcode != JIT_OP_MARK_OFFSET)
   321  		{
   322  			return 0;
   323  		}
   324  	}
   325  
   326  	return 1;
   327  }
   328  
   329  #ifdef _JIT_BLOCK_DEBUG
   330  static void
   331  label_loop_check(jit_function_t func, jit_block_t block, jit_label_t label)
   332  {
   333  	jit_label_t block_label = block->label;
   334  	while(block_label != jit_label_undefined)
   335  	{
   336  		if(block_label == label)
   337  		{
   338  			abort();
   339  		}
   340  		block_label = func->builder->label_info[block_label].alias;
   341  	}
   342  }
   343  #endif
   344  
   345  /* Merge labels of the src block with labels of the dst block but retain
   346     the address_of labels.  This requires the address_of labels to be used
   347     exclusively as such, no branches are allowed to use address_of labels.
   348     This is ensured by the split_address_of() function. */
   349  static void
   350  merge_labels(jit_function_t func, jit_block_t src, jit_block_t dst)
   351  {
   352  	_jit_label_info_t *info;
   353  	jit_label_t label, alias;
   354  
   355  	label = src->label;
   356  	src->label = jit_label_undefined;
   357  
   358  #ifdef _JIT_BLOCK_DEBUG
   359  	label_loop_check(func, dst, label);
   360  #endif
   361  
   362  	while(label != jit_label_undefined)
   363  	{
   364  		info = &func->builder->label_info[label];
   365  		alias = info->alias;
   366  
   367  		if((info->flags & JIT_LABEL_ADDRESS_OF) == 0)
   368  		{
   369  			info->block = dst;
   370  			info->alias = dst->label;
   371  			dst->label = label;
   372  		}
   373  		else
   374  		{
   375  			info->alias = src->label;
   376  			src->label = label;
   377  		}
   378  
   379  		label = alias;
   380  	}
   381  }
   382  
   383  /* Merge empty block with its successor */
   384  static void
   385  merge_empty(jit_function_t func, jit_block_t block, int *changed)
   386  {
   387  	_jit_edge_t succ_edge, pred_edge, fallthru_edge;
   388  	jit_block_t succ_block;
   389  	int index;
   390  
   391  	/* Find block successor */
   392  	succ_edge = block->succs[0];
   393  	succ_block = succ_edge->dst;
   394  
   395  	/* Retarget labels bound to this block to the successor block. */
   396  	merge_labels(func, block, succ_block);
   397  
   398  	/* Retarget all incoming edges except a fallthrough edge */
   399  	fallthru_edge = 0;
   400  	for(index = 0; index < block->num_preds; index++)
   401  	{
   402  		pred_edge = block->preds[index];
   403  		if(pred_edge->flags == _JIT_EDGE_FALLTHRU)
   404  		{
   405  			fallthru_edge = pred_edge;
   406  		}
   407  		else
   408  		{
   409  			*changed = 1;
   410  			attach_edge_dst(pred_edge, succ_block);
   411  		}
   412  	}
   413  
   414  	/* Unless the block is taken address of, the incoming fallthrough edge
   415  	   can be retargeted and then the block deleted if the outgoing edge is
   416  	   also fallthrough. */
   417  	if(!block->address_of && fallthru_edge && succ_edge->flags == _JIT_EDGE_FALLTHRU)
   418  	{
   419  		*changed = 1;
   420  		attach_edge_dst(fallthru_edge, succ_block);
   421  		fallthru_edge = 0;
   422  	}
   423  
   424  	/* Free the block if there is no incoming edge left and it is not taken
   425  	   address of. Otherwise adjust the preds array accordingly.  */
   426  	if(fallthru_edge)
   427  	{
   428  		if(block->num_preds > 1)
   429  		{
   430  			block->num_preds = 1;
   431  			block->preds = jit_realloc(block->preds, sizeof(_jit_edge_t));
   432  			block->preds[0] = fallthru_edge;
   433  		}
   434  	}
   435  	else if(block->address_of)
   436  	{
   437  		if(block->num_preds > 0)
   438  		{
   439  			block->num_preds = 0;
   440  			jit_free(block->preds);
   441  			block->preds = 0;
   442  		}
   443  	}
   444  	else
   445  	{
   446  		detach_edge_dst(succ_edge);
   447  		jit_memory_pool_dealloc(&func->builder->edge_pool, succ_edge);
   448  		_jit_block_detach(block, block);
   449  		delete_block(block);
   450  	}
   451  }
   452  
   453  /* Combine non-empty block with its successor */
   454  static void
   455  combine_block(jit_function_t func, jit_block_t block, int *changed)
   456  {
   457  	jit_block_t succ_block;
   458  	int branch, num_insns, max_insns;
   459  	jit_insn_t insns;
   460  
   461  	/* Find block successor */
   462  	succ_block = block->succs[0]->dst;
   463  
   464  	/* Does block end with a (redundant) branch instruction? */
   465  	branch = (block->succs[0]->flags == _JIT_EDGE_BRANCH);
   466  
   467  	/* If the branch is there then preallocate memory for it,
   468  	   doing it here simplifies handling of the out-of-memory
   469  	   condition */
   470  	if(branch && !succ_block->max_insns)
   471  	{
   472  		succ_block->insns = jit_malloc(sizeof(struct _jit_insn));
   473  		if(!succ_block->insns)
   474  		{
   475  			jit_exception_builtin(JIT_RESULT_OUT_OF_MEMORY);
   476  		}
   477  		succ_block->max_insns = 1;
   478  	}
   479  
   480  	/* Allocate enough memory for combined instructions */
   481  	max_insns = block->max_insns;
   482  	num_insns = block->num_insns + succ_block->num_insns;
   483  	if(num_insns > max_insns)
   484  	{
   485  		max_insns = num_insns;
   486  		insns = (jit_insn_t) jit_realloc(block->insns,
   487  						 max_insns * sizeof(struct _jit_insn));
   488  		if(!insns)
   489  		{
   490  			jit_exception_builtin(JIT_RESULT_OUT_OF_MEMORY);
   491  		}
   492  	}
   493  	else
   494  	{
   495  		insns = block->insns;
   496  	}
   497  
   498  	/* Copy instruction from the successor block after the instructions
   499  	   of the original block */
   500  	if(succ_block->num_insns)
   501  	{
   502  		jit_memcpy(insns + block->num_insns,
   503  			   succ_block->insns,
   504  			   succ_block->num_insns * sizeof(struct _jit_insn));
   505  	}
   506  
   507  	/* Move combined instructions to the successor, but if there was
   508  	   a branch in the original block then keep the branch around,
   509  	   merge_empty() will take care of it if it may be optimized away.
   510  	   To reduce the number of allocations, swap the arrays around
   511  	   rather than allocating a fresh array for the empty block. */
   512  	block->insns = succ_block->insns;
   513  	block->max_insns = succ_block->max_insns;
   514  	if(branch)
   515  	{
   516  		/* Copy the branch instruction */
   517  		jit_memcpy(block->insns,
   518  			   insns + block->num_insns - 1,
   519  			   sizeof(struct _jit_insn));
   520  		/* In the combined block turn branch into NOP */
   521  		insns[block->num_insns - 1].opcode = JIT_OP_NOP;
   522  	}
   523  	block->num_insns = branch;
   524  	succ_block->insns = insns;
   525  	succ_block->max_insns = max_insns;
   526  	succ_block->num_insns = num_insns;
   527  
   528  	merge_empty(func, block, changed);
   529  }
   530  
   531  /* Allow branch optimization by splitting the label that is both a branch target
   532     and an address-of opcode source into two separate labels with single role.
   533     TODO: handle jump tables. */
   534  static void
   535  split_address_of(jit_function_t func, jit_block_t block, jit_label_t label)
   536  {
   537  	int index;
   538  	jit_insn_t insn;
   539  	jit_label_t branch_label;
   540  	jit_label_t *jump_labels;
   541  	int jump_index, num_labels;
   542  
   543  	branch_label = jit_label_undefined;
   544  
   545  	for(index = 0; index < block->num_preds; index++)
   546  	{
   547  		if(block->preds[index]->flags != _JIT_EDGE_BRANCH)
   548  		{
   549  			continue;
   550  		}
   551  
   552  		if(branch_label == jit_label_undefined)
   553  		{
   554  			branch_label = (func->builder->next_label)++;
   555  			if(!_jit_block_record_label(block, branch_label))
   556  			{
   557  				jit_exception_builtin(JIT_RESULT_OUT_OF_MEMORY);
   558  			}
   559  		}
   560  
   561  		insn = _jit_block_get_last(block->preds[index]->src);
   562  		if(insn->opcode != JIT_OP_JUMP_TABLE)
   563  		{
   564  			insn->dest = (jit_value_t)branch_label;
   565  		}
   566  		else
   567  		{
   568  			jump_labels = (jit_label_t *) insn->value1->address;
   569  			num_labels = (int) insn->value2->address;
   570  			for(jump_index = 0; jump_index < num_labels; jump_index++)
   571  			{
   572  				if(jump_labels[jump_index] == label)
   573  				{
   574  					jump_labels[jump_index] = branch_label;
   575  				}
   576  			}
   577  		}
   578  	}
   579  }
   580  
   581  /* Mark blocks that might be taken address of */
   582  static void
   583  set_address_of(jit_function_t func)
   584  {
   585  	int index, count;
   586  	jit_block_t block;
   587  
   588  	count = func->builder->max_label_info;
   589  	for(index = 0; index < count; index++)
   590  	{
   591  		block = func->builder->label_info[index].block;
   592  		if(block && (func->builder->label_info[index].flags & JIT_LABEL_ADDRESS_OF) != 0)
   593  		{
   594  			block->address_of = 1;
   595  			split_address_of(func, block, index);
   596  		}
   597  	}
   598  }
   599  
   600  /* Delete block along with references to it */
   601  static void
   602  eliminate_block(jit_block_t block)
   603  {
   604  	_jit_edge_t edge;
   605  	int index;
   606  
   607  	/* Detach block from the list */
   608  	_jit_block_detach(block, block);
   609  
   610  	/* Remove control flow graph edges */
   611  	for(index = 0; index < block->num_succs; index++)
   612  	{
   613  		edge = block->succs[index];
   614  		detach_edge_dst(edge);
   615  		jit_memory_pool_dealloc(&block->func->builder->edge_pool, edge);
   616  	}
   617  	for(index = 0; index < block->num_preds; index++)
   618  	{
   619  		edge = block->preds[index];
   620  		detach_edge_src(edge);
   621  		jit_memory_pool_dealloc(&block->func->builder->edge_pool, edge);
   622  	}
   623  
   624  	/* Finally delete the block */
   625  	delete_block(block);
   626  }
   627  
   628  #if 0
   629  
   630  /* Visit all successive blocks recursively */
   631  static void
   632  visit_reachable(jit_block_t block)
   633  {
   634  	int index;
   635  
   636  	if(!block->visited)
   637  	{
   638  		block->visited = 1;
   639  		for(index = 0; index < block->num_succs; index++)
   640  		{
   641  			visit_reachable(block->succs[index]->dst);
   642  		}
   643  	}
   644  }
   645  
   646  #endif
   647  
   648  /* Eliminate unreachable blocks */
   649  static void
   650  eliminate_unreachable(jit_function_t func)
   651  {
   652  	jit_block_t block, next_block;
   653  
   654  	block = func->builder->entry_block;
   655  	while(block != func->builder->exit_block)
   656  	{
   657  		next_block = block->next;
   658  		if(block->visited)
   659  		{
   660  			block->visited = 0;
   661  		}
   662  		else if(!block->address_of)
   663  		{
   664  			eliminate_block(block);
   665  		}
   666  		block = next_block;
   667  	}
   668  }
   669  
   670  /* Clear visited blocks */
   671  static void
   672  clear_visited(jit_function_t func)
   673  {
   674  	jit_block_t block;
   675  
   676  	for(block = func->builder->entry_block; block; block = block->next)
   677  	{
   678  		block->visited = 0;
   679  	}
   680  }
   681  
   682  /* TODO: maintain the block count as the blocks are created/deleted */
   683  static int
   684  count_blocks(jit_function_t func)
   685  {
   686  	int count;
   687  	jit_block_t block;
   688  
   689  	count = 0;
   690  	for(block = func->builder->entry_block; block; block = block->next)
   691  	{
   692  		++count;
   693  	}
   694  	return count;
   695  }
   696  
   697  /* Release block order memory */
   698  static void
   699  free_order(jit_function_t func)
   700  {
   701  	jit_free(func->builder->block_order);
   702  	func->builder->block_order = NULL;
   703  	func->builder->num_block_order = 0;
   704  }
   705  
   706  int
   707  _jit_block_init(jit_function_t func)
   708  {
   709  	func->builder->entry_block = _jit_block_create(func);
   710  	if(!func->builder->entry_block)
   711  	{
   712  		return 0;
   713  	}
   714  
   715  	func->builder->exit_block = _jit_block_create(func);
   716  	if(!func->builder->exit_block)
   717  	{
   718  		return 0;
   719  	}
   720  
   721  	func->builder->entry_block->next = func->builder->exit_block;
   722  	func->builder->exit_block->prev = func->builder->entry_block;
   723  	return 1;
   724  }
   725  
   726  void
   727  _jit_block_free(jit_function_t func)
   728  {
   729  	jit_block_t block, next;
   730  
   731  	free_order(func);
   732  
   733  	block = func->builder->entry_block;
   734  	while(block)
   735  	{
   736  		next = block->next;
   737  		_jit_block_destroy(block);
   738  		block = next;
   739  	}
   740  
   741  	block = func->builder->deleted_blocks;
   742  	while(block)
   743  	{
   744  		next = block->next;
   745  		_jit_block_destroy(block);
   746  		block = next;
   747  	}
   748  
   749  	func->builder->entry_block = 0;
   750  	func->builder->exit_block = 0;
   751  }
   752  
   753  void
   754  _jit_block_build_cfg(jit_function_t func)
   755  {
   756  	/* Count the edges */
   757  	build_edges(func, 0);
   758  
   759  	/* Allocate memory for edges */
   760  	alloc_edges(func);
   761  
   762  	/* Actually build the edges */
   763  	build_edges(func, 1);
   764  }
   765  
   766  static int
   767  _jit_invert_condition (int opcode)
   768  {
   769  	switch(opcode)
   770  	{
   771  	case JIT_OP_BR_IEQ:	opcode = JIT_OP_BR_INE;      break;
   772  	case JIT_OP_BR_INE:	opcode = JIT_OP_BR_IEQ;      break;
   773  	case JIT_OP_BR_ILT:	opcode = JIT_OP_BR_IGE;      break;
   774  	case JIT_OP_BR_ILT_UN:	opcode = JIT_OP_BR_IGE_UN;   break;
   775  	case JIT_OP_BR_ILE:	opcode = JIT_OP_BR_IGT;      break;
   776  	case JIT_OP_BR_ILE_UN:	opcode = JIT_OP_BR_IGT_UN;   break;
   777  	case JIT_OP_BR_IGT:	opcode = JIT_OP_BR_ILE;      break;
   778  	case JIT_OP_BR_IGT_UN:	opcode = JIT_OP_BR_ILE_UN;   break;
   779  	case JIT_OP_BR_IGE:	opcode = JIT_OP_BR_ILT;      break;
   780  	case JIT_OP_BR_IGE_UN:	opcode = JIT_OP_BR_ILT_UN;   break;
   781  	case JIT_OP_BR_LEQ:	opcode = JIT_OP_BR_LNE;      break;
   782  	case JIT_OP_BR_LNE:	opcode = JIT_OP_BR_LEQ;      break;
   783  	case JIT_OP_BR_LLT:	opcode = JIT_OP_BR_LGE;      break;
   784  	case JIT_OP_BR_LLT_UN:	opcode = JIT_OP_BR_LGE_UN;   break;
   785  	case JIT_OP_BR_LLE:	opcode = JIT_OP_BR_LGT;      break;
   786  	case JIT_OP_BR_LLE_UN:	opcode = JIT_OP_BR_LGT_UN;   break;
   787  	case JIT_OP_BR_LGT:	opcode = JIT_OP_BR_LLE;      break;
   788  	case JIT_OP_BR_LGT_UN:	opcode = JIT_OP_BR_LLE_UN;   break;
   789  	case JIT_OP_BR_LGE:	opcode = JIT_OP_BR_LLT;      break;
   790  	case JIT_OP_BR_LGE_UN:	opcode = JIT_OP_BR_LLT_UN;   break;
   791  	case JIT_OP_BR_FEQ:	opcode = JIT_OP_BR_FNE;      break;
   792  	case JIT_OP_BR_FNE:	opcode = JIT_OP_BR_FEQ;      break;
   793  	case JIT_OP_BR_FLT:	opcode = JIT_OP_BR_FGE_INV;      break;
   794  	case JIT_OP_BR_FLE:	opcode = JIT_OP_BR_FGT_INV;      break;
   795  	case JIT_OP_BR_FGT:	opcode = JIT_OP_BR_FLE_INV;      break;
   796  	case JIT_OP_BR_FGE:	opcode = JIT_OP_BR_FLT_INV;      break;
   797  	case JIT_OP_BR_FLT_INV:	opcode = JIT_OP_BR_FGE;  break;
   798  	case JIT_OP_BR_FLE_INV:	opcode = JIT_OP_BR_FGT;  break;
   799  	case JIT_OP_BR_FGT_INV:	opcode = JIT_OP_BR_FLE;  break;
   800  	case JIT_OP_BR_FGE_INV:	opcode = JIT_OP_BR_FLT;  break;
   801  	case JIT_OP_BR_DEQ:	opcode = JIT_OP_BR_DNE;      break;
   802  	case JIT_OP_BR_DNE:	opcode = JIT_OP_BR_DEQ;      break;
   803  	case JIT_OP_BR_DLT:	opcode = JIT_OP_BR_DGE_INV;      break;
   804  	case JIT_OP_BR_DLE:	opcode = JIT_OP_BR_DGT_INV;      break;
   805  	case JIT_OP_BR_DGT:	opcode = JIT_OP_BR_DLE_INV;      break;
   806  	case JIT_OP_BR_DGE:	opcode = JIT_OP_BR_DLT_INV;      break;
   807  	case JIT_OP_BR_DLT_INV:	opcode = JIT_OP_BR_DGE;  break;
   808  	case JIT_OP_BR_DLE_INV:	opcode = JIT_OP_BR_DGT;  break;
   809  	case JIT_OP_BR_DGT_INV:	opcode = JIT_OP_BR_DLE;  break;
   810  	case JIT_OP_BR_DGE_INV:	opcode = JIT_OP_BR_DLT;  break;
   811  	case JIT_OP_BR_NFEQ:	opcode = JIT_OP_BR_NFNE;     break;
   812  	case JIT_OP_BR_NFNE:	opcode = JIT_OP_BR_NFEQ;     break;
   813  	case JIT_OP_BR_NFLT:	opcode = JIT_OP_BR_NFGE_INV;     break;
   814  	case JIT_OP_BR_NFLE:	opcode = JIT_OP_BR_NFGT_INV;     break;
   815  	case JIT_OP_BR_NFGT:	opcode = JIT_OP_BR_NFLE_INV;     break;
   816  	case JIT_OP_BR_NFGE:	opcode = JIT_OP_BR_NFLT_INV;     break;
   817  	case JIT_OP_BR_NFLT_INV:	opcode = JIT_OP_BR_NFGE; break;
   818  	case JIT_OP_BR_NFLE_INV:	opcode = JIT_OP_BR_NFGT; break;
   819  	case JIT_OP_BR_NFGT_INV:	opcode = JIT_OP_BR_NFLE; break;
   820  	case JIT_OP_BR_NFGE_INV:	opcode = JIT_OP_BR_NFLT; break;
   821  	default:		abort();
   822  	}
   823  	return opcode;
   824  }
   825  
   826  void
   827  _jit_block_clean_cfg(jit_function_t func)
   828  {
   829  	int index, changed;
   830  	jit_block_t block;
   831  	jit_insn_t insn;
   832  
   833  	/*
   834  	 * The code below is based on the Clean algorithm described in
   835  	 * "Engineering a Compiler" by Keith D. Cooper and Linda Torczon,
   836  	 * section 10.3.1 "Eliminating Useless and Unreachable Code"
   837  	 * (originally presented in a paper by Rob Shillner and John Lu
   838  	 * http://www.cs.princeton.edu/~ras/clean.ps).
   839  	 *
   840  	 * Because libjit IR differs from ILOC the algorithm here has
   841  	 * some differences too.
   842  	 */
   843  
   844  	if(!_jit_block_compute_postorder(func))
   845  	{
   846  		jit_exception_builtin(JIT_RESULT_OUT_OF_MEMORY);
   847  	}
   848  
   849  	set_address_of(func);
   850  	eliminate_unreachable(func);
   851  
   852   loop:
   853  	changed = 0;
   854  
   855  	/* Go through blocks in post order skipping the entry and exit blocks */
   856  	for(index = 1; index < (func->builder->num_block_order - 1); index++)
   857  	{
   858  		block = func->builder->block_order[index];
   859  		if(block->num_succs == 0)
   860  		{
   861  			continue;
   862  		}
   863  
   864  		/* Take care of redundant branches that is, if possible, either
   865  		   replace a branch with NOP turning it to a fallthrough case
   866  		   or reduce a conditional branch to unconditional */
   867  		if(block->succs[0]->flags == _JIT_EDGE_BRANCH)
   868  		{
   869  			insn = _jit_block_get_last(block);
   870  			if(insn->opcode == JIT_OP_JUMP_TABLE)
   871  			{
   872  				/* skip jump tables, handle only branches */
   873  				continue;
   874  			}
   875  			if(block->succs[0]->dst == block->next)
   876  			{
   877  				/* Replace useless branch with NOP */
   878  				changed = 1;
   879  				insn->opcode = JIT_OP_NOP;
   880  				if(block->num_succs == 2)
   881  				{
   882  					/* For conditional branch delete the branch
   883  					   edge while leaving the fallthough edge
   884  					   intact */
   885  #ifdef _JIT_BLOCK_DEBUG
   886  					printf("%d cbranch->fallthru %d\n", index, block->label);
   887  #endif
   888  					delete_edge(func, block->succs[0]);
   889  				}
   890  				else
   891  				{
   892  					/* For unconditional branch replace the branch
   893  					   edge with a fallthrough edge */
   894  #ifdef _JIT_BLOCK_DEBUG
   895  					printf("%d ubranch->fallthru %d\n", index, block->label);
   896  #endif
   897  					block->ends_in_dead = 0;
   898  					block->succs[0]->flags = _JIT_EDGE_FALLTHRU;
   899  				}
   900  			}
   901  			else if(block->num_succs == 2
   902  				&& block->next->num_succs == 1
   903  				&& block->next->succs[0]->flags == _JIT_EDGE_BRANCH
   904  				&& block->succs[0]->dst == block->next->succs[0]->dst
   905  				&& is_empty_block(block->next))
   906  			{
   907  				/* For conditional branch followed by unconditional
   908  				   that has the same target make the first branch
   909  				   unconditional too, remove the fallthrough edge while
   910  				   leaving the branch edge intact */
   911  #ifdef _JIT_BLOCK_DEBUG
   912  				printf("%d cbranch->ubranch %d\n", index, block->label);
   913  #endif
   914  				changed = 1;
   915  				insn->opcode = JIT_OP_BR;
   916  				block->ends_in_dead = 1;
   917  				delete_edge(func, block->succs[1]);
   918  			}
   919  			else if(block->num_succs == 2
   920  				&& is_empty_block(block->next)
   921  				&& block->next->num_succs == 1
   922  				/* This transformation is not safe if
   923  				   the block we're rewriting has other
   924  				   predecessors, or has had its
   925  				   address taken.  */
   926  				&& block->next->num_preds == 1
   927  				&& block->next->address_of == 0
   928  				&& block->next->succs[0]->flags == _JIT_EDGE_BRANCH
   929  				&& block->succs[0]->dst == block->next->next)
   930  			{
   931  				/* We have a conditional branch, that
   932  				   branches around the next block, and
   933  				   the next block consists of just a
   934  				   jump, like:
   935  
   936  					if l7 != 3 then goto .L0
   937  					goto .L1
   938  					.L0:
   939  
   940  				   In this case we can invert the
   941  				   condition and retarget the jump,
   942  				   resulting in:
   943  				   
   944  					if l7 == 3 then goto .L1
   945  					nop
   946  					.L0:
   947  				*/
   948  				insn->opcode = _jit_invert_condition(insn->opcode);
   949  				detach_edge_dst(block->succs[0]);
   950  				attach_edge_dst(block->succs[0], block->next->succs[0]->dst);
   951  				insn->dest = (jit_value_t) block->next->succs[0]->dst->label;
   952  				detach_edge_dst(block->next->succs[0]);
   953  				attach_edge_dst(block->next->succs[0], block->next->next);
   954  				block->next->succs[0]->flags = _JIT_EDGE_FALLTHRU;
   955  				/* Rewrite the last instruction of the
   956  				   unnecessary block to be a NOP.  */
   957  				block->next->insns[block->next->num_insns - 1].opcode = JIT_OP_NOP;
   958  				block->next->ends_in_dead = 0;
   959  				changed = 1;
   960  			}
   961  		}
   962  
   963  		/* Try to simplify basic blocks that end with fallthrough or
   964  		   unconditional branch */
   965  		if(block->num_succs == 1
   966  		   && (block->succs[0]->flags == _JIT_EDGE_BRANCH
   967  		       || block->succs[0]->flags == _JIT_EDGE_FALLTHRU))
   968  		{
   969  			if(is_empty_block(block))
   970  			{
   971  				/* Remove empty block */
   972  #ifdef _JIT_BLOCK_DEBUG
   973  				printf("%d merge_empty %d\n", index, block->label);
   974  #endif
   975  				merge_empty(func, block, &changed);
   976  			}
   977  			else if(block->succs[0]->dst->num_preds == 1
   978  				&& block->succs[0]->dst->address_of == 0)
   979  			{
   980  				/* Combine with the successor block if it has
   981  				   only one predecessor */
   982  #ifdef _JIT_BLOCK_DEBUG
   983  				printf("%d combine_block %d\n", index, block->label);
   984  #endif
   985  				combine_block(func, block, &changed);
   986  			}
   987  
   988  			/* TODO: "hoist branch" part of the Clean algorithm.
   989  			   It is somewhat complicated as libjit conditional
   990  			   branches differ too much from ILOC conditional
   991  			   branches */
   992  		}
   993  	}
   994  
   995  	if(changed)
   996  	{
   997  		if(!_jit_block_compute_postorder(func))
   998  		{
   999  			jit_exception_builtin(JIT_RESULT_OUT_OF_MEMORY);
  1000  		}
  1001  		clear_visited(func);
  1002  		goto loop;
  1003  	}
  1004  }
  1005  
  1006  int
  1007  _jit_block_compute_postorder(jit_function_t func)
  1008  {
  1009  	int num_blocks, index, num, top;
  1010  	jit_block_t *blocks, block, succ;
  1011  	_jit_block_stack_entry_t *stack;
  1012  
  1013  	if(func->builder->block_order)
  1014  	{
  1015  		free_order(func);
  1016  	}
  1017  
  1018  	num_blocks = count_blocks(func);
  1019  
  1020  	blocks = (jit_block_t *) jit_malloc(num_blocks * sizeof(jit_block_t));
  1021  	if(!blocks)
  1022  	{
  1023  		return 0;
  1024  	}
  1025  
  1026  	stack = (_jit_block_stack_entry_t *) jit_malloc(num_blocks * sizeof(_jit_block_stack_entry_t));
  1027  	if(!stack)
  1028  	{
  1029  		jit_free(blocks);
  1030  		return 0;
  1031  	}
  1032  
  1033  	func->builder->entry_block->visited = 1;
  1034  	stack[0].block = func->builder->entry_block;
  1035  	stack[0].index = 0;
  1036  	top = 1;
  1037  	num = 0;
  1038  	do
  1039  	{
  1040  		block = stack[top - 1].block;
  1041  		index = stack[top - 1].index;
  1042  
  1043  		if(index == block->num_succs)
  1044  		{
  1045  			blocks[num++] = block;
  1046  			--top;
  1047  		}
  1048  		else
  1049  		{
  1050  			succ = block->succs[index]->dst;
  1051  			if(succ->visited)
  1052  			{
  1053  				stack[top - 1].index = index + 1;
  1054  			}
  1055  			else
  1056  			{
  1057  				succ->visited = 1;
  1058  				stack[top].block = succ;
  1059  				stack[top].index = 0;
  1060  				++top;
  1061  			}
  1062  		}
  1063  	}
  1064  	while(top);
  1065  
  1066  	jit_free(stack);
  1067  	if(num < num_blocks)
  1068  	{
  1069  		blocks = jit_realloc(blocks, num * sizeof(jit_block_t));
  1070  	}
  1071  
  1072  	func->builder->block_order = blocks;
  1073  	func->builder->num_block_order = num;
  1074  	return 1;
  1075  }
  1076  
  1077  jit_block_t
  1078  _jit_block_create(jit_function_t func)
  1079  {
  1080  	jit_block_t block;
  1081  
  1082  	/* Allocate memory for the block */
  1083  	block = jit_cnew(struct _jit_block);
  1084  	if(!block)
  1085  	{
  1086  		return 0;
  1087  	}
  1088  
  1089  	/* Initialize the block */
  1090  	block->func = func;
  1091  	block->label = jit_label_undefined;
  1092  
  1093  	return block;
  1094  }
  1095  
  1096  void
  1097  _jit_block_destroy(jit_block_t block)
  1098  {
  1099  	/* Free all the memory owned by the block. CFG edges are not freed
  1100  	   because each edge is shared between two blocks so the ownership
  1101  	   of the edge is ambiguous. Sometimes an edge may be redirected to
  1102  	   another block rather than freed. Therefore edges are freed (or
  1103  	   not freed) separately. However succs and preds arrays are freed,
  1104  	   these contain pointers to edges, not edges themselves. */
  1105  	jit_meta_destroy(&block->meta);
  1106  	jit_free(block->succs);
  1107  	jit_free(block->preds);
  1108  	jit_free(block->insns);
  1109  	jit_free(block);
  1110  }
  1111  
  1112  void
  1113  _jit_block_detach(jit_block_t first, jit_block_t last)
  1114  {
  1115  	last->next->prev = first->prev;
  1116  	first->prev->next = last->next;
  1117  }
  1118  
  1119  void
  1120  _jit_block_attach_after(jit_block_t block, jit_block_t first, jit_block_t last)
  1121  {
  1122  	first->prev = block;
  1123  	last->next = block->next;
  1124  	block->next->prev = last;
  1125  	block->next = first;
  1126  }
  1127  
  1128  void
  1129  _jit_block_attach_before(jit_block_t block, jit_block_t first, jit_block_t last)
  1130  {
  1131  	first->prev = block->prev;
  1132  	last->next = block;
  1133  	block->prev->next = first;
  1134  	block->prev = last;
  1135  }
  1136  
  1137  /* Make space for the label in the label info table */
  1138  static int
  1139  ensure_label_table(jit_function_t func, jit_label_t label)
  1140  {
  1141  	jit_label_t num;
  1142  	_jit_label_info_t *info;
  1143  
  1144  	if(label >= func->builder->max_label_info)
  1145  	{
  1146  		num = func->builder->max_label_info;
  1147  		if(num < 64)
  1148  		{
  1149  			num = 64;
  1150  		}
  1151  		while(num <= label)
  1152  		{
  1153  			num *= 2;
  1154  		}
  1155  
  1156  		info = (_jit_label_info_t *) jit_realloc(func->builder->label_info,
  1157  							 num * sizeof(_jit_label_info_t));
  1158  		if(!info)
  1159  		{
  1160  			return 0;
  1161  		}
  1162  
  1163  		jit_memzero(info + func->builder->max_label_info,
  1164  			    sizeof(_jit_label_info_t) * (num - func->builder->max_label_info));
  1165  		func->builder->label_info = info;
  1166  		func->builder->max_label_info = num;
  1167  	}
  1168  
  1169  	return 1;
  1170  }
  1171  
  1172  int
  1173  _jit_block_record_label(jit_block_t block, jit_label_t label)
  1174  {
  1175  	jit_builder_t builder;
  1176  
  1177  	if(!ensure_label_table(block->func, label))
  1178  	{
  1179  		return 0;
  1180  	}
  1181  
  1182  	builder = block->func->builder;
  1183  
  1184  	/* Bail out on previously recorded label */
  1185  	if(builder->label_info[label].block)
  1186  	{
  1187  		return 0;
  1188  	}
  1189  
  1190  	/* Record label info to the table */
  1191  	builder->label_info[label].block = block;
  1192  	builder->label_info[label].alias = block->label;
  1193  	block->label = label;
  1194  
  1195  	return 1;
  1196  }
  1197  
  1198  int
  1199  _jit_block_record_label_flags(jit_function_t func, jit_label_t label, int flags)
  1200  {
  1201  	if(!ensure_label_table(func, label))
  1202  	{
  1203  		return 0;
  1204  	}
  1205  
  1206  	func->builder->label_info[label].flags = flags;
  1207  	return 1;
  1208  }
  1209  
  1210  jit_insn_t
  1211  _jit_block_add_insn(jit_block_t block)
  1212  {
  1213  	int max_insns;
  1214  	jit_insn_t insns;
  1215  
  1216  	/* Make space for the instruction in the block's instruction list */
  1217  	if(block->num_insns == block->max_insns)
  1218  	{
  1219  		max_insns = block->max_insns ? block->max_insns * 2 : 4;
  1220  		insns = (jit_insn_t) jit_realloc(block->insns,
  1221  						 max_insns * sizeof(struct _jit_insn));
  1222  		if(!insns)
  1223  		{
  1224  			return 0;
  1225  		}
  1226  
  1227  		block->insns = insns;
  1228  		block->max_insns = max_insns;
  1229  	}
  1230  
  1231  	/* Zero-init the instruction */
  1232  	jit_memzero(&block->insns[block->num_insns], sizeof(struct _jit_insn));
  1233  
  1234  	/* Return the instruction, which is now ready to fill in */
  1235  	return &block->insns[block->num_insns++];
  1236  }
  1237  
  1238  jit_insn_t
  1239  _jit_block_get_last(jit_block_t block)
  1240  {
  1241  	if(block->num_insns > 0)
  1242  	{
  1243  		return &block->insns[block->num_insns - 1];
  1244  	}
  1245  	else
  1246  	{
  1247  		return 0;
  1248  	}
  1249  }
  1250  
  1251  int
  1252  _jit_block_is_final(jit_block_t block)
  1253  {
  1254  	for(block = block->next; block; block = block->next)
  1255  	{
  1256  		if(block->num_insns)
  1257  		{
  1258  			return 0;
  1259  		}
  1260  	}
  1261  	return 1;
  1262  }
  1263  
  1264  /*@
  1265   * @deftypefun jit_function_t jit_block_get_function (jit_block_t @var{block})
  1266   * Get the function that a particular @var{block} belongs to.
  1267   * @end deftypefun
  1268  @*/
  1269  jit_function_t
  1270  jit_block_get_function(jit_block_t block)
  1271  {
  1272  	if(block)
  1273  	{
  1274  		return block->func;
  1275  	}
  1276  	else
  1277  	{
  1278  		return 0;
  1279  	}
  1280  }
  1281  
  1282  /*@
  1283   * @deftypefun jit_context_t jit_block_get_context (jit_block_t @var{block})
  1284   * Get the context that a particular @var{block} belongs to.
  1285   * @end deftypefun
  1286  @*/
  1287  jit_context_t
  1288  jit_block_get_context(jit_block_t block)
  1289  {
  1290  	if(block)
  1291  	{
  1292  		return block->func->context;
  1293  	}
  1294  	else
  1295  	{
  1296  		return 0;
  1297  	}
  1298  }
  1299  
  1300  /*@
  1301   * @deftypefun jit_label_t jit_block_get_label (jit_block_t @var{block})
  1302   * Get the label associated with a block.
  1303   * @end deftypefun
  1304  @*/
  1305  jit_label_t
  1306  jit_block_get_label(jit_block_t block)
  1307  {
  1308  	if(block)
  1309  	{
  1310  		return block->label;
  1311  	}
  1312  	return jit_label_undefined;
  1313  }
  1314  
  1315  /*@
  1316   * @deftypefun jit_label_t jit_block_get_next_label (jit_block_t @var{block}, jit_label_t @var{label})
  1317   * Get the next label associated with a block.
  1318   * @end deftypefun
  1319  @*/
  1320  jit_label_t
  1321  jit_block_get_next_label(jit_block_t block, jit_label_t label)
  1322  {
  1323  	jit_builder_t builder;
  1324  	if(block)
  1325  	{
  1326  		if(label == jit_label_undefined)
  1327  		{
  1328  			return block->label;
  1329  		}
  1330  		builder = block->func->builder;
  1331  		if(builder
  1332  		   && label < builder->max_label_info
  1333  		   && block == builder->label_info[label].block)
  1334  		{
  1335  			return builder->label_info[label].alias;
  1336  		}
  1337  	}
  1338  	return jit_label_undefined;
  1339  }
  1340  
  1341  /*@
  1342   * @deftypefun jit_block_t jit_block_next (jit_function_t @var{func}, jit_block_t @var{previous})
  1343   * Iterate over the blocks in a function, in order of their creation.
  1344   * The @var{previous} argument should be NULL on the first call.
  1345   * This function will return NULL if there are no further blocks to iterate.
  1346   * @end deftypefun
  1347  @*/
  1348  jit_block_t
  1349  jit_block_next(jit_function_t func, jit_block_t previous)
  1350  {
  1351  	if(previous)
  1352  	{
  1353  		return previous->next;
  1354  	}
  1355  	else if(func && func->builder)
  1356  	{
  1357  		return func->builder->entry_block;
  1358  	}
  1359  	else
  1360  	{
  1361  		return 0;
  1362  	}
  1363  }
  1364  
  1365  /*@
  1366   * @deftypefun jit_block_t jit_block_previous (jit_function_t @var{func}, jit_block_t @var{previous})
  1367   * Iterate over the blocks in a function, in reverse order of their creation.
  1368   * The @var{previous} argument should be NULL on the first call.
  1369   * This function will return NULL if there are no further blocks to iterate.
  1370   * @end deftypefun
  1371  @*/
  1372  jit_block_t
  1373  jit_block_previous(jit_function_t func, jit_block_t previous)
  1374  {
  1375  	if(previous)
  1376  	{
  1377  		return previous->prev;
  1378  	}
  1379  	else if(func && func->builder)
  1380  	{
  1381  		return func->builder->exit_block;
  1382  	}
  1383  	else
  1384  	{
  1385  		return 0;
  1386  	}
  1387  }
  1388  
  1389  /*@
  1390   * @deftypefun jit_block_t jit_block_from_label (jit_function_t @var{func}, jit_label_t @var{label})
  1391   * Get the block that corresponds to a particular @var{label}.
  1392   * Returns NULL if there is no block associated with the label.
  1393   * @end deftypefun
  1394  @*/
  1395  jit_block_t
  1396  jit_block_from_label(jit_function_t func, jit_label_t label)
  1397  {
  1398  	if(func && func->builder && label < func->builder->max_label_info)
  1399  	{
  1400  		return func->builder->label_info[label].block;
  1401  	}
  1402  	else
  1403  	{
  1404  		return 0;
  1405  	}
  1406  }
  1407  
  1408  /*@
  1409   * @deftypefun int jit_block_set_meta (jit_block_t @var{block}, int @var{type}, void *@var{data}, jit_meta_free_func @var{free_data})
  1410   * Tag a block with some metadata.  Returns zero if out of memory.
  1411   * If the @var{type} already has some metadata associated with it, then
  1412   * the previous value will be freed.  Metadata may be used to store
  1413   * dependency graphs, branch prediction information, or any other
  1414   * information that is useful to optimizers or code generators.
  1415   *
  1416   * Metadata type values of 10000 or greater are reserved for internal use.
  1417   * @end deftypefun
  1418  @*/
  1419  int
  1420  jit_block_set_meta(jit_block_t block, int type, void *data, jit_meta_free_func free_data)
  1421  {
  1422  	return jit_meta_set(&(block->meta), type, data, free_data, block->func);
  1423  }
  1424  
  1425  /*@
  1426   * @deftypefun {void *} jit_block_get_meta (jit_block_t @var{block}, int @var{type})
  1427   * Get the metadata associated with a particular tag.  Returns NULL
  1428   * if @var{type} does not have any metadata associated with it.
  1429   * @end deftypefun
  1430  @*/
  1431  void *
  1432  jit_block_get_meta(jit_block_t block, int type)
  1433  {
  1434  	return jit_meta_get(block->meta, type);
  1435  }
  1436  
  1437  /*@
  1438   * @deftypefun void jit_block_free_meta (jit_block_t @var{block}, int @var{type})
  1439   * Free metadata of a specific type on a block.  Does nothing if
  1440   * the @var{type} does not have any metadata associated with it.
  1441   * @end deftypefun
  1442  @*/
  1443  void
  1444  jit_block_free_meta(jit_block_t block, int type)
  1445  {
  1446  	jit_meta_free(&(block->meta), type);
  1447  }
  1448  
  1449  /*@
  1450   * @deftypefun int jit_block_is_reachable (jit_block_t @var{block})
  1451   * Determine if a block is reachable from some other point in
  1452   * its function.  Unreachable blocks can be discarded in their
  1453   * entirety.  If the JIT is uncertain as to whether a block is
  1454   * reachable, or it does not wish to perform expensive flow
  1455   * analysis to find out, then it will err on the side of caution
  1456   * and assume that it is reachable.
  1457   * @end deftypefun
  1458  @*/
  1459  int
  1460  jit_block_is_reachable(jit_block_t block)
  1461  {
  1462  	jit_block_t entry;
  1463  
  1464  	/* Simple-minded reachability analysis that bothers only with
  1465  	   fall-through control flow. The block is considered reachable
  1466  	   if a) it is the entry block b) it has any label c) there is
  1467  	   fall-through path to it from one of the above. */
  1468  	entry = block->func->builder->entry_block;
  1469  	while(block != entry && block->label == jit_label_undefined)
  1470  	{
  1471  		block = block->prev;
  1472  		if(block->ends_in_dead)
  1473  		{
  1474  			/* There is no fall-through path from the prev block */
  1475  			return 0;
  1476  		}
  1477  	}
  1478  
  1479  	return 1;
  1480  }
  1481  
  1482  /*@
  1483   * @deftypefun int jit_block_ends_in_dead (jit_block_t @var{block})
  1484   * Determine if a block ends in a "dead" marker.  That is, control
  1485   * will not fall out through the end of the block.
  1486   * @end deftypefun
  1487  @*/
  1488  int
  1489  jit_block_ends_in_dead(jit_block_t block)
  1490  {
  1491  	return block->ends_in_dead;
  1492  }
  1493  
  1494  /*@
  1495   * @deftypefun int jit_block_current_is_dead (jit_function_t @var{func})
  1496   * Determine if the current point in the function is dead.  That is,
  1497   * there are no existing branches or fall-throughs to this point.
  1498   * This differs slightly from @code{jit_block_ends_in_dead} in that
  1499   * this can skip past zero-length blocks that may not appear to be
  1500   * dead to find the dead block at the head of a chain of empty blocks.
  1501   * @end deftypefun
  1502  @*/
  1503  int
  1504  jit_block_current_is_dead(jit_function_t func)
  1505  {
  1506  	jit_block_t block = jit_block_previous(func, 0);
  1507  	return !block || jit_block_ends_in_dead(block) || !jit_block_is_reachable(block);
  1508  }