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

     1  /*
     2   * jit-meta.c - Functions for manipulating metadata lists.
     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  
    25  /*@
    26  
    27  @section Metadata handling
    28  @cindex Metadata handling
    29  @cindex jit-meta.h
    30  
    31  Many of the structures in the @code{libjit} library can have user-supplied
    32  metadata associated with them.  Metadata may be used to store dependency
    33  graphs, branch prediction information, or any other information that is
    34  useful to optimizers or code generators.
    35  
    36  Metadata can also be used by higher level user code to store information
    37  about the structures that is specific to the user's virtual machine or
    38  language.
    39  
    40  The library structures have special-purpose metadata routines associated
    41  with them (e.g. @code{jit_function_set_meta}, @code{jit_block_get_meta}).
    42  However, sometimes you may wish to create your own metadata lists and
    43  attach them to your own structures.  The functions below enable you
    44  to do this:
    45  
    46  @*/
    47  
    48  /*@
    49   * @deftypefun int jit_meta_set (jit_meta_t *@var{list}, int @var{type}, void *@var{data}, jit_meta_free_func @var{free_data}, jit_function_t @var{pool_owner})
    50   * Set a metadata value on a list.  If the @var{type} is already present
    51   * in the list, then its previous value will be freed.  The @var{free_func}
    52   * is called when the metadata value is freed with @code{jit_meta_free}
    53   * or @code{jit_meta_destroy}.  Returns zero if out of memory.
    54   *
    55   * If @var{pool_owner} is not NULL, then the metadata value will persist
    56   * until the specified function is finished building.  Normally you would
    57   * set this to NULL.
    58   *
    59   * Metadata type values of 10000 or greater are reserved for internal use.
    60   * They should never be used by external user code.
    61   * @end deftypefun
    62  @*/
    63  int jit_meta_set(jit_meta_t *list, int type, void *data,
    64  				 jit_meta_free_func free_data, jit_function_t pool_owner)
    65  {
    66  	jit_meta_t current;
    67  
    68  	/* See if we already have this type in the list */
    69  	current = *list;
    70  	while(current != 0)
    71  	{
    72  		if(current->type == type)
    73  		{
    74  			if(data == current->data)
    75  			{
    76  				/* The value is unchanged, so don't free the previous value */
    77  				return 1;
    78  			}
    79  			if(current->free_data)
    80  			{
    81  				(*(current->free_data))(current->data);
    82  			}
    83  			current->data = data;
    84  			current->free_data = free_data;
    85  			return 1;
    86  		}
    87  		current = current->next;
    88  	}
    89  
    90  	/* Create a new metadata block and add it to the list */
    91  	if(pool_owner)
    92  	{
    93  		if((current = jit_memory_pool_alloc
    94  				(&(pool_owner->builder->meta_pool), struct _jit_meta)) == 0)
    95  		{
    96  			return 0;
    97  		}
    98  	}
    99  	else
   100  	{
   101  		if((current = jit_new(struct _jit_meta)) == 0)
   102  		{
   103  			return 0;
   104  		}
   105  	}
   106  	current->type = type;
   107  	current->data = data;
   108  	current->free_data = free_data;
   109  	current->next = *list;
   110  	current->pool_owner = pool_owner;
   111  	*list = current;
   112  	return 1;
   113  }
   114  
   115  /*@
   116   * @deftypefun {void *} jit_meta_get (jit_meta_t @var{list}, int @var{type})
   117   * Get the value associated with @var{type} in the specified @var{list}.
   118   * Returns NULL if @var{type} is not present.
   119   * @end deftypefun
   120  @*/
   121  void *jit_meta_get(jit_meta_t list, int type)
   122  {
   123  	while(list != 0)
   124  	{
   125  		if(list->type == type)
   126  		{
   127  			return list->data;
   128  		}
   129  		list = list->next;
   130  	}
   131  	return 0;
   132  }
   133  
   134  /*@
   135   * @deftypefun void jit_meta_free (jit_meta_t *@var{list}, int @var{type})
   136   * Free the metadata value in the @var{list} that has the
   137   * specified @var{type}.  Does nothing if the @var{type}
   138   * is not present.
   139   * @end deftypefun
   140  @*/
   141  void jit_meta_free(jit_meta_t *list, int type)
   142  {
   143  	jit_meta_t current = *list;
   144  	jit_meta_t prev = 0;
   145  	while(current != 0)
   146  	{
   147  		if(current->type == type)
   148  		{
   149  			if(current->free_data)
   150  			{
   151  				(*(current->free_data))(current->data);
   152  				current->free_data = 0;
   153  			}
   154  			if(prev)
   155  			{
   156  				prev->next = current->next;
   157  			}
   158  			else
   159  			{
   160  				*list = current->next;
   161  			}
   162  			if(current->pool_owner)
   163  			{
   164  				jit_memory_pool_dealloc
   165  					(&(current->pool_owner->builder->meta_pool), current);
   166  			}
   167  			else
   168  			{
   169  				jit_free(current);
   170  			}
   171  			return;
   172  		}
   173  		else
   174  		{
   175  			prev = current;
   176  			current = current->next;
   177  		}
   178  	}
   179  }
   180  
   181  /*@
   182   * @deftypefun void jit_meta_destroy (jit_meta_t *@var{list})
   183   * Destroy all of the metadata values in the specified @var{list}.
   184   * @end deftypefun
   185  @*/
   186  void jit_meta_destroy(jit_meta_t *list)
   187  {
   188  	jit_meta_t current = *list;
   189  	jit_meta_t next;
   190  	while(current != 0)
   191  	{
   192  		next = current->next;
   193  		if(current->free_data)
   194  		{
   195  			(*(current->free_data))(current->data);
   196  			current->free_data = 0;
   197  		}
   198  		if(current->pool_owner)
   199  		{
   200  			jit_memory_pool_dealloc
   201  				(&(current->pool_owner->builder->meta_pool), current);
   202  		}
   203  		else
   204  		{
   205  			jit_free(current);
   206  		}
   207  		current = next;
   208  	}
   209  }
   210  
   211  void _jit_meta_free_one(void *meta)
   212  {
   213  	jit_meta_t current = (jit_meta_t)meta;
   214  	if(current->free_data)
   215  	{
   216  		(*(current->free_data))(current->data);
   217  	}
   218  }