2 * Bytecode utility functions
4 * Copyright (C) 2001-2007 Peter Johnson
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
29 #include "libyasm-stdint.h"
42 yasm_bc_set_multiple(yasm_bytecode *bc, yasm_expr *e)
45 bc->multiple = yasm_expr_create_tree(bc->multiple, YASM_EXPR_MUL, e,
52 yasm_bc_finalize_common(yasm_bytecode *bc, yasm_bytecode *prev_bc)
57 yasm_bc_calc_len_common(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
60 yasm_internal_error(N_("bytecode length cannot be calculated"));
66 yasm_bc_expand_common(yasm_bytecode *bc, int span, long old_val, long new_val,
67 /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres)
69 yasm_internal_error(N_("bytecode does not have any dependent spans"));
75 yasm_bc_tobytes_common(yasm_bytecode *bc, unsigned char **buf,
76 unsigned char *bufstart, void *d,
77 yasm_output_value_func output_value,
78 /*@null@*/ yasm_output_reloc_func output_reloc)
80 yasm_internal_error(N_("bytecode cannot be converted to bytes"));
86 yasm_bc_transform(yasm_bytecode *bc, const yasm_bytecode_callback *callback,
90 bc->callback->destroy(bc->contents);
91 bc->callback = callback;
92 bc->contents = contents;
96 yasm_bc_create_common(const yasm_bytecode_callback *callback, void *contents,
99 yasm_bytecode *bc = yasm_xmalloc(sizeof(yasm_bytecode));
101 bc->callback = callback;
103 bc->multiple = (yasm_expr *)NULL;
107 bc->offset = ~0UL; /* obviously incorrect / uninitialized value */
109 bc->contents = contents;
115 yasm_bc_get_section(yasm_bytecode *bc)
121 yasm_bc__add_symrec(yasm_bytecode *bc, yasm_symrec *sym)
124 bc->symrecs = yasm_xmalloc(2*sizeof(yasm_symrec *));
125 bc->symrecs[0] = sym;
126 bc->symrecs[1] = NULL;
128 /* Very inefficient implementation for large numbers of symbols. But
129 * that would be very unusual, so use the simple algorithm instead.
132 while (bc->symrecs[count])
134 bc->symrecs = yasm_xrealloc(bc->symrecs,
135 (count+2)*sizeof(yasm_symrec *));
136 bc->symrecs[count] = sym;
137 bc->symrecs[count+1] = NULL;
142 yasm_bc_destroy(yasm_bytecode *bc)
148 bc->callback->destroy(bc->contents);
149 yasm_expr_destroy(bc->multiple);
151 yasm_xfree(bc->symrecs);
156 yasm_bc_print(const yasm_bytecode *bc, FILE *f, int indent_level)
159 fprintf(f, "%*s_Empty_\n", indent_level, "");
161 bc->callback->print(bc->contents, f, indent_level);
162 fprintf(f, "%*sMultiple=", indent_level, "");
164 fprintf(f, "nil (1)");
166 yasm_expr_print(bc->multiple, f);
167 fprintf(f, "\n%*sLength=%lu\n", indent_level, "", bc->len);
168 fprintf(f, "%*sLine Index=%lu\n", indent_level, "", bc->line);
169 fprintf(f, "%*sOffset=%lx\n", indent_level, "", bc->offset);
173 yasm_bc_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
176 bc->callback->finalize(bc, prev_bc);
180 if (yasm_value_finalize_expr(&val, bc->multiple, prev_bc, 0))
181 yasm_error_set(YASM_ERROR_TOO_COMPLEX,
182 N_("multiple expression too complex"));
184 yasm_error_set(YASM_ERROR_NOT_ABSOLUTE,
185 N_("multiple expression not absolute"));
186 /* Finalize creates NULL output if value=0, but bc->multiple is NULL
187 * if value=1 (this difference is to make the common case small).
188 * However, this means we need to set bc->multiple explicitly to 0
189 * here if val.abs is NULL.
192 bc->multiple = val.abs;
194 bc->multiple = yasm_expr_create_ident(
195 yasm_expr_int(yasm_intnum_create_uint(0)), bc->line);
199 /*@null@*/ yasm_intnum *
200 yasm_calc_bc_dist(yasm_bytecode *precbc1, yasm_bytecode *precbc2)
202 unsigned long dist2, dist1;
205 if (precbc1->section != precbc2->section)
208 dist1 = yasm_bc_next_offset(precbc1);
209 dist2 = yasm_bc_next_offset(precbc2);
211 intn = yasm_intnum_create_uint(dist1 - dist2);
212 yasm_intnum_calc(intn, YASM_EXPR_NEG, NULL);
216 return yasm_intnum_create_uint(dist2);
220 yasm_bc_next_offset(yasm_bytecode *precbc)
222 return precbc->offset + precbc->len*precbc->mult_int;
226 yasm_bc_elem_size(yasm_bytecode *bc)
229 yasm_internal_error(N_("got empty bytecode in yasm_bc_elem_size"));
231 } else if (!bc->callback->elem_size)
234 return bc->callback->elem_size(bc);
238 yasm_bc_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
246 yasm_internal_error(N_("got empty bytecode in yasm_bc_calc_len"));
248 retval = bc->callback->calc_len(bc, add_span, add_span_data);
250 /* Check for multiples */
253 /*@dependent@*/ /*@null@*/ const yasm_intnum *num;
255 num = yasm_expr_get_intnum(&bc->multiple, 0);
257 if (yasm_intnum_sign(num) < 0) {
258 yasm_error_set(YASM_ERROR_VALUE, N_("multiple is negative"));
261 bc->mult_int = yasm_intnum_get_int(num);
263 if (yasm_expr__contains(bc->multiple, YASM_EXPR_FLOAT)) {
264 yasm_error_set(YASM_ERROR_VALUE,
265 N_("expression must not contain floating point value"));
269 yasm_value_initialize(&value, bc->multiple, 0);
270 add_span(add_span_data, bc, 0, &value, 0, 0);
271 bc->mult_int = 0; /* assume 0 to start */
276 /* If we got an error somewhere along the line, clear out any calc len */
284 yasm_bc_expand(yasm_bytecode *bc, int span, long old_val, long new_val,
285 /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres)
288 bc->mult_int = new_val;
292 yasm_internal_error(N_("got empty bytecode in yasm_bc_expand"));
296 return bc->callback->expand(bc, span, old_val, new_val, neg_thres,
300 /*@null@*/ /*@only@*/ unsigned char *
301 yasm_bc_tobytes(yasm_bytecode *bc, unsigned char *buf, unsigned long *bufsize,
302 /*@out@*/ int *gap, void *d,
303 yasm_output_value_func output_value,
304 /*@null@*/ yasm_output_reloc_func output_reloc)
307 /*@only@*/ /*@null@*/ unsigned char *mybuf = NULL;
308 unsigned char *bufstart;
309 unsigned char *origbuf, *destbuf;
314 if (yasm_bc_get_multiple(bc, &mult, 1) || mult == 0) {
320 /* special case for reserve bytecodes */
321 if (bc->callback->special == YASM_BC_SPECIAL_RESERVE) {
322 *bufsize = bc->len*bc->mult_int;
324 return NULL; /* we didn't allocate a buffer */
328 if (*bufsize < bc->len*bc->mult_int) {
329 mybuf = yasm_xmalloc(bc->len*bc->mult_int);
335 *bufsize = bc->len*bc->mult_int;
338 yasm_internal_error(N_("got empty bytecode in bc_tobytes"));
339 else for (i=0; i<bc->mult_int; i++) {
341 error = bc->callback->tobytes(bc, &destbuf, bufstart, d, output_value,
344 if (!error && ((unsigned long)(destbuf - origbuf) != bc->len))
346 N_("written length does not match optimized length"));
353 yasm_bc_get_multiple(yasm_bytecode *bc, long *multiple, int calc_bc_dist)
355 /*@dependent@*/ /*@null@*/ const yasm_intnum *num;
359 num = yasm_expr_get_intnum(&bc->multiple, calc_bc_dist);
361 yasm_error_set(YASM_ERROR_VALUE,
362 N_("could not determine multiple"));
365 if (yasm_intnum_sign(num) < 0) {
366 yasm_error_set(YASM_ERROR_VALUE, N_("multiple is negative"));
369 *multiple = yasm_intnum_get_int(num);
375 yasm_bc_get_multiple_expr(const yasm_bytecode *bc)
381 yasm_bc_get_insn(yasm_bytecode *bc)
383 if (bc->callback->special != YASM_BC_SPECIAL_INSN)
385 return (yasm_insn *)bc->contents;