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 }