123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386 |
- /*
- * Bytecode utility functions
- *
- * Copyright (C) 2001-2007 Peter Johnson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
- #include "util.h"
- #include "libyasm-stdint.h"
- #include "coretype.h"
- #include "errwarn.h"
- #include "intnum.h"
- #include "expr.h"
- #include "value.h"
- #include "symrec.h"
- #include "bytecode.h"
- void
- yasm_bc_set_multiple(yasm_bytecode *bc, yasm_expr *e)
- {
- if (bc->multiple)
- bc->multiple = yasm_expr_create_tree(bc->multiple, YASM_EXPR_MUL, e,
- e->line);
- else
- bc->multiple = e;
- }
- void
- yasm_bc_finalize_common(yasm_bytecode *bc, yasm_bytecode *prev_bc)
- {
- }
- int
- yasm_bc_calc_len_common(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
- void *add_span_data)
- {
- yasm_internal_error(N_("bytecode length cannot be calculated"));
- /*@unreached@*/
- return 0;
- }
- int
- yasm_bc_expand_common(yasm_bytecode *bc, int span, long old_val, long new_val,
- /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres)
- {
- yasm_internal_error(N_("bytecode does not have any dependent spans"));
- /*@unreached@*/
- return 0;
- }
- int
- yasm_bc_tobytes_common(yasm_bytecode *bc, unsigned char **buf,
- unsigned char *bufstart, void *d,
- yasm_output_value_func output_value,
- /*@null@*/ yasm_output_reloc_func output_reloc)
- {
- yasm_internal_error(N_("bytecode cannot be converted to bytes"));
- /*@unreached@*/
- return 0;
- }
- void
- yasm_bc_transform(yasm_bytecode *bc, const yasm_bytecode_callback *callback,
- void *contents)
- {
- if (bc->callback)
- bc->callback->destroy(bc->contents);
- bc->callback = callback;
- bc->contents = contents;
- }
- yasm_bytecode *
- yasm_bc_create_common(const yasm_bytecode_callback *callback, void *contents,
- unsigned long line)
- {
- yasm_bytecode *bc = yasm_xmalloc(sizeof(yasm_bytecode));
- bc->callback = callback;
- bc->section = NULL;
- bc->multiple = (yasm_expr *)NULL;
- bc->len = 0;
- bc->mult_int = 1;
- bc->line = line;
- bc->offset = ~0UL; /* obviously incorrect / uninitialized value */
- bc->symrecs = NULL;
- bc->contents = contents;
- return bc;
- }
- yasm_section *
- yasm_bc_get_section(yasm_bytecode *bc)
- {
- return bc->section;
- }
- void
- yasm_bc__add_symrec(yasm_bytecode *bc, yasm_symrec *sym)
- {
- if (!bc->symrecs) {
- bc->symrecs = yasm_xmalloc(2*sizeof(yasm_symrec *));
- bc->symrecs[0] = sym;
- bc->symrecs[1] = NULL;
- } else {
- /* Very inefficient implementation for large numbers of symbols. But
- * that would be very unusual, so use the simple algorithm instead.
- */
- size_t count = 1;
- while (bc->symrecs[count])
- count++;
- bc->symrecs = yasm_xrealloc(bc->symrecs,
- (count+2)*sizeof(yasm_symrec *));
- bc->symrecs[count] = sym;
- bc->symrecs[count+1] = NULL;
- }
- }
- void
- yasm_bc_destroy(yasm_bytecode *bc)
- {
- if (!bc)
- return;
- if (bc->callback)
- bc->callback->destroy(bc->contents);
- yasm_expr_destroy(bc->multiple);
- if (bc->symrecs)
- yasm_xfree(bc->symrecs);
- yasm_xfree(bc);
- }
- void
- yasm_bc_print(const yasm_bytecode *bc, FILE *f, int indent_level)
- {
- if (!bc->callback)
- fprintf(f, "%*s_Empty_\n", indent_level, "");
- else
- bc->callback->print(bc->contents, f, indent_level);
- fprintf(f, "%*sMultiple=", indent_level, "");
- if (!bc->multiple)
- fprintf(f, "nil (1)");
- else
- yasm_expr_print(bc->multiple, f);
- fprintf(f, "\n%*sLength=%lu\n", indent_level, "", bc->len);
- fprintf(f, "%*sLine Index=%lu\n", indent_level, "", bc->line);
- fprintf(f, "%*sOffset=%lx\n", indent_level, "", bc->offset);
- }
- void
- yasm_bc_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
- {
- if (bc->callback)
- bc->callback->finalize(bc, prev_bc);
- if (bc->multiple) {
- yasm_value val;
- if (yasm_value_finalize_expr(&val, bc->multiple, prev_bc, 0))
- yasm_error_set(YASM_ERROR_TOO_COMPLEX,
- N_("multiple expression too complex"));
- else if (val.rel)
- yasm_error_set(YASM_ERROR_NOT_ABSOLUTE,
- N_("multiple expression not absolute"));
- /* Finalize creates NULL output if value=0, but bc->multiple is NULL
- * if value=1 (this difference is to make the common case small).
- * However, this means we need to set bc->multiple explicitly to 0
- * here if val.abs is NULL.
- */
- if (val.abs)
- bc->multiple = val.abs;
- else
- bc->multiple = yasm_expr_create_ident(
- yasm_expr_int(yasm_intnum_create_uint(0)), bc->line);
- }
- }
- /*@null@*/ yasm_intnum *
- yasm_calc_bc_dist(yasm_bytecode *precbc1, yasm_bytecode *precbc2)
- {
- unsigned long dist2, dist1;
- yasm_intnum *intn;
- if (precbc1->section != precbc2->section)
- return NULL;
- dist1 = yasm_bc_next_offset(precbc1);
- dist2 = yasm_bc_next_offset(precbc2);
- if (dist2 < dist1) {
- intn = yasm_intnum_create_uint(dist1 - dist2);
- yasm_intnum_calc(intn, YASM_EXPR_NEG, NULL);
- return intn;
- }
- dist2 -= dist1;
- return yasm_intnum_create_uint(dist2);
- }
- unsigned long
- yasm_bc_next_offset(yasm_bytecode *precbc)
- {
- return precbc->offset + precbc->len*precbc->mult_int;
- }
- int
- yasm_bc_elem_size(yasm_bytecode *bc)
- {
- if (!bc->callback) {
- yasm_internal_error(N_("got empty bytecode in yasm_bc_elem_size"));
- return 0;
- } else if (!bc->callback->elem_size)
- return 0;
- else
- return bc->callback->elem_size(bc);
- }
- int
- yasm_bc_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
- void *add_span_data)
- {
- int retval = 0;
- bc->len = 0;
- if (!bc->callback)
- yasm_internal_error(N_("got empty bytecode in yasm_bc_calc_len"));
- else
- retval = bc->callback->calc_len(bc, add_span, add_span_data);
- /* Check for multiples */
- bc->mult_int = 1;
- if (bc->multiple) {
- /*@dependent@*/ /*@null@*/ const yasm_intnum *num;
- num = yasm_expr_get_intnum(&bc->multiple, 0);
- if (num) {
- if (yasm_intnum_sign(num) < 0) {
- yasm_error_set(YASM_ERROR_VALUE, N_("multiple is negative"));
- retval = -1;
- } else
- bc->mult_int = yasm_intnum_get_int(num);
- } else {
- if (yasm_expr__contains(bc->multiple, YASM_EXPR_FLOAT)) {
- yasm_error_set(YASM_ERROR_VALUE,
- N_("expression must not contain floating point value"));
- retval = -1;
- } else {
- yasm_value value;
- yasm_value_initialize(&value, bc->multiple, 0);
- add_span(add_span_data, bc, 0, &value, 0, 0);
- bc->mult_int = 0; /* assume 0 to start */
- }
- }
- }
- /* If we got an error somewhere along the line, clear out any calc len */
- if (retval < 0)
- bc->len = 0;
- return retval;
- }
- int
- yasm_bc_expand(yasm_bytecode *bc, int span, long old_val, long new_val,
- /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres)
- {
- if (span == 0) {
- bc->mult_int = new_val;
- return 1;
- }
- if (!bc->callback) {
- yasm_internal_error(N_("got empty bytecode in yasm_bc_expand"));
- /*@unreached@*/
- return -1;
- } else
- return bc->callback->expand(bc, span, old_val, new_val, neg_thres,
- pos_thres);
- }
- /*@null@*/ /*@only@*/ unsigned char *
- yasm_bc_tobytes(yasm_bytecode *bc, unsigned char *buf, unsigned long *bufsize,
- /*@out@*/ int *gap, void *d,
- yasm_output_value_func output_value,
- /*@null@*/ yasm_output_reloc_func output_reloc)
- /*@sets *buf@*/
- {
- /*@only@*/ /*@null@*/ unsigned char *mybuf = NULL;
- unsigned char *bufstart;
- unsigned char *origbuf, *destbuf;
- long i;
- int error = 0;
- long mult;
- if (yasm_bc_get_multiple(bc, &mult, 1) || mult == 0) {
- *bufsize = 0;
- return NULL;
- }
- bc->mult_int = mult;
- /* special case for reserve bytecodes */
- if (bc->callback->special == YASM_BC_SPECIAL_RESERVE) {
- *bufsize = bc->len*bc->mult_int;
- *gap = 1;
- return NULL; /* we didn't allocate a buffer */
- }
- *gap = 0;
- if (*bufsize < bc->len*bc->mult_int) {
- mybuf = yasm_xmalloc(bc->len*bc->mult_int);
- destbuf = mybuf;
- } else
- destbuf = buf;
- bufstart = destbuf;
- *bufsize = bc->len*bc->mult_int;
- if (!bc->callback)
- yasm_internal_error(N_("got empty bytecode in bc_tobytes"));
- else for (i=0; i<bc->mult_int; i++) {
- origbuf = destbuf;
- error = bc->callback->tobytes(bc, &destbuf, bufstart, d, output_value,
- output_reloc);
- if (!error && ((unsigned long)(destbuf - origbuf) != bc->len))
- yasm_internal_error(
- N_("written length does not match optimized length"));
- }
- return mybuf;
- }
- int
- yasm_bc_get_multiple(yasm_bytecode *bc, long *multiple, int calc_bc_dist)
- {
- /*@dependent@*/ /*@null@*/ const yasm_intnum *num;
- *multiple = 1;
- if (bc->multiple) {
- num = yasm_expr_get_intnum(&bc->multiple, calc_bc_dist);
- if (!num) {
- yasm_error_set(YASM_ERROR_VALUE,
- N_("could not determine multiple"));
- return 1;
- }
- if (yasm_intnum_sign(num) < 0) {
- yasm_error_set(YASM_ERROR_VALUE, N_("multiple is negative"));
- return 1;
- }
- *multiple = yasm_intnum_get_int(num);
- }
- return 0;
- }
- const yasm_expr *
- yasm_bc_get_multiple_expr(const yasm_bytecode *bc)
- {
- return bc->multiple;
- }
- yasm_insn *
- yasm_bc_get_insn(yasm_bytecode *bc)
- {
- if (bc->callback->special != YASM_BC_SPECIAL_INSN)
- return NULL;
- return (yasm_insn *)bc->contents;
- }
|